/*************************************************************************** * * Copyright 2015-2019 BES. * All rights reserved. All unpublished rights reserved. * * No part of this work may be used or reproduced in any form or by any * means, or stored in a database or retrieval system, without prior written * permission of BES. * * Use of this work is governed by a license granted by BES. * This work contains confidential and proprietary information of * BES. which is protected by copyright, trade secret, * trademark and other intellectual property rights. * ****************************************************************************/ #include "plat_addr_map.h" #ifndef GPADC_CHIP_SPECIFIC #include "cmsis_nvic.h" #include "hal_analogif.h" #include "hal_gpadc.h" #include "hal_trace.h" #include "pmu.h" #include "stddef.h" #define HAL_GPADC_TRACE(n, s, ...) // TRACE(n, s, ##__VA_ARGS__) #define VBAT_DIV_ALWAYS_ON #define gpadc_reg_read(reg, val) pmu_read(reg, val) #define gpadc_reg_write(reg, val) pmu_write(reg, val) // Battery voltage = gpadc voltage * 4 // adc rate 0~2v(10bit) // Battery_voltage:Adc_rate = 4:1 #define HAL_GPADC_MVOLT_A 800 #define HAL_GPADC_MVOLT_B 1050 #define HAL_GPADC_CALIB_DEFAULT_A 428 #define HAL_GPADC_CALIB_DEFAULT_B 565 #if 0 #elif defined(CHIP_BEST1400) || defined(CHIP_BEST1402) || \ defined(CHIP_BEST2000) || defined(CHIP_BEST2001) || \ defined(CHIP_BEST2300) || defined(CHIP_BEST2300A) || \ defined(CHIP_BEST2300P) || defined(CHIP_BEST3001) || \ defined(CHIP_BEST3005) #if defined(CHIP_BEST1400) || defined(CHIP_BEST1402) || defined(CHIP_BEST2001) enum GPADC_REG_T { GPADC_REG_VBAT_EN = 0x02, GPADC_REG_INTVL_EN = 0x18, GPADC_REG_INTVL_VAL = 0x1C, GPADC_REG_START = 0x4F, GPADC_REG_CH_EN = 0x1D, GPADC_REG_INT_MASK = 0x1F, GPADC_REG_INT_EN = 0x20, GPADC_REG_INT_RAW_STS = 0x50, GPADC_REG_INT_MSKED_STS = 0x51, GPADC_REG_INT_CLR = 0x51, GPADC_REG_CH0_DATA = 0x56, }; #else enum GPADC_REG_T { GPADC_REG_VBAT_EN = 0x02, GPADC_REG_INTVL_EN = 0x1F, GPADC_REG_INTVL_VAL = 0x23, GPADC_REG_START = 0x4F, GPADC_REG_CH_EN = 0x24, GPADC_REG_INT_MASK = 0x26, GPADC_REG_INT_EN = 0x27, #if defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A) GPADC_REG_INT_RAW_STS = 0x52, GPADC_REG_INT_MSKED_STS = 0x53, GPADC_REG_INT_CLR = 0x51, #else GPADC_REG_INT_RAW_STS = 0x50, GPADC_REG_INT_MSKED_STS = 0x51, GPADC_REG_INT_CLR = 0x51, #endif GPADC_REG_CH0_DATA = 0x56, }; #endif // GPADC_REG_VBAT_EN #define REG_PU_VBAT_DIV (1 << 15) // GPADC_REG_INTVL_EN #define GPADC_INTERVAL_MODE (1 << 12) // GPADC_REG_START #define GPADC_START (1 << 5) #define KEY_START (1 << 4) // GPADC_REG_CH_EN #define CHAN_EN_REG_SHIFT 0 #define CHAN_EN_REG_MASK (0xFF << CHAN_EN_REG_SHIFT) #define CHAN_EN_REG(n) BITFIELD_VAL(CHAN_EN_REG, n) // GPADC_REG_INT_MASK #define KEY_ERR1_INTR_MSK (1 << 12) #define KEY_ERR0_INTR_MSK (1 << 11) #define KEY_PRESS_INTR_MSK (1 << 10) #define KEY_RELEASE_INTR_MSK (1 << 9) #define SAMPLE_DONE_INTR_MSK (1 << 8) #define CHAN_DATA_INTR_MSK_SHIFT 0 #define CHAN_DATA_INTR_MSK_MASK (0xFF << CHAN_DATA_INTR_MSK_SHIFT) #define CHAN_DATA_INTR_MSK(n) BITFIELD_VAL(CHAN_DATA_INTR_MSK, n) // GPADC_REG_INT_EN #define KEY_ERR1_INTR_EN (1 << 12) #define KEY_ERR0_INTR_EN (1 << 11) #define KEY_PRESS_INTR_EN (1 << 10) #define KEY_RELEASE_INTR_EN (1 << 9) #define SAMPLE_DONE_INTR_EN (1 << 8) #define CHAN_DATA_INTR_EN_SHIFT 0 #define CHAN_DATA_INTR_EN_MASK (0xFF << CHAN_DATA_INTR_EN_SHIFT) #define CHAN_DATA_INTR_EN(n) BITFIELD_VAL(CHAN_DATA_INTR_EN, n) // GPADC_REG_INT_RAW_STS #define KEY_ERR1_INTR (1 << 12) #define KEY_ERR0_INTR (1 << 11) #define KEY_PRESS_INTR (1 << 10) #define KEY_RELEASE_INTR (1 << 9) #define SAMPLE_PERIOD_DONE_INTR (1 << 8) #define CHAN_DATA_VALID_INTR_SHIFT 0 #define CHAN_DATA_VALID_INTR_MASK (0xFF << CHAN_DATA_VALID_INTR_SHIFT) #define CHAN_DATA_VALID_INTR(n) BITFIELD_VAL(CHAN_DATA_VALID_INTR, n) // GPADC_REG_INT_MSKED_STS #define KEY_ERR1_INTR_MSKED (1 << 12) #define KEY_ERR0_INTR_MSKED (1 << 11) #define KEY_PRESS_INTR_MSKED (1 << 10) #define KEY_RELEASE_INTR_MSKED (1 << 9) #define SAMPLE_DONE_INTR_MSKED (1 << 8) #define CHAN_DATA_INTR_MSKED_SHIFT 0 #define CHAN_DATA_INTR_MSKED_MASK (0xFF << CHAN_DATA_INTR_MSKED_SHIFT) #define CHAN_DATA_INTR_MSKED(n) BITFIELD_VAL(CHAN_DATA_INTR_MSKED, n) // GPADC_REG_INT_CLR #define KEY_ERR1_INTR_CLR (1 << 12) #define KEY_ERR0_INTR_CLR (1 << 11) #define KEY_PRESS_INTR_CLR (1 << 10) #define KEY_RELEASE_INTR_CLR (1 << 9) #define SAMPLE_DONE_INTR_CLR (1 << 8) #define CHAN_DATA_INTR_CLR_SHIFT 0 #define CHAN_DATA_INTR_CLR_MASK (0xFF << CHAN_DATA_INTR_CLR_SHIFT) #define CHAN_DATA_INTR_CLR(n) BITFIELD_VAL(CHAN_DATA_INTR_CLR, n) // GPADC_REG_CH0_DATA #define DATA_CHAN0_SHIFT 0 #define DATA_CHAN0_MASK (0x3FF << DATA_CHAN0_SHIFT) #define DATA_CHAN0(n) BITFIELD_VAL(DATA_CHAN0, n) #elif defined(CHIP_BEST1000) enum GPADC_REG_T { GPADC_REG_VBAT_EN = 0x45, GPADC_REG_INTVL_EN = 0x60, GPADC_REG_INTVL_VAL = 0x64, GPADC_REG_START = 0x65, GPADC_REG_CH_EN = 0x65, GPADC_REG_INT_MASK = 0x67, GPADC_REG_INT_EN = 0x68, GPADC_REG_INT_RAW_STS = 0x69, GPADC_REG_INT_MSKED_STS = 0x6A, GPADC_REG_INT_CLR = 0x6A, GPADC_REG_CH0_DATA = 0x78, }; // GPADC_REG_VBAT_EN #define REG_PU_VBAT_DIV (1 << 0) // GPADC_REG_INTVL_EN #define GPADC_INTERVAL_MODE (1 << 12) // GPADC_REG_START #define KEY_START (1 << 9) #define GPADC_START (1 << 8) // GPADC_REG_CH_EN #define CHAN_EN_REG_SHIFT 0 #define CHAN_EN_REG_MASK (0xFF << CHAN_EN_REG_SHIFT) #define CHAN_EN_REG(n) BITFIELD_VAL(CHAN_EN_REG, n) // GPADC_REG_INT_MASK #define KEY_ERR1_INTR_MSK (1 << 12) #define KEY_ERR0_INTR_MSK (1 << 11) #define KEY_PRESS_INTR_MSK (1 << 10) #define KEY_RELEASE_INTR_MSK (1 << 9) #define SAMPLE_DONE_INTR_MSK (1 << 8) #define CHAN_DATA_INTR_MSK_SHIFT 0 #define CHAN_DATA_INTR_MSK_MASK (0xFF << CHAN_DATA_INTR_MSK_SHIFT) #define CHAN_DATA_INTR_MSK(n) BITFIELD_VAL(CHAN_DATA_INTR_MSK, n) // GPADC_REG_INT_EN #define KEY_ERR1_INTR_EN (1 << 12) #define KEY_ERR0_INTR_EN (1 << 11) #define KEY_PRESS_INTR_EN (1 << 10) #define KEY_RELEASE_INTR_EN (1 << 9) #define SAMPLE_DONE_INTR_EN (1 << 8) #define CHAN_DATA_INTR_EN_SHIFT 0 #define CHAN_DATA_INTR_EN_MASK (0xFF << CHAN_DATA_INTR_EN_SHIFT) #define CHAN_DATA_INTR_EN(n) BITFIELD_VAL(CHAN_DATA_INTR_EN, n) // GPADC_REG_INT_RAW_STS #define KEY_ERR1_INTR (1 << 12) #define KEY_ERR0_INTR (1 << 11) #define KEY_PRESS_INTR (1 << 10) #define KEY_RELEASE_INTR (1 << 9) #define SAMPLE_PERIOD_DONE_INTR (1 << 8) #define CHAN_DATA_VALID_INTR_SHIFT 0 #define CHAN_DATA_VALID_INTR_MASK (0xFF << CHAN_DATA_VALID_INTR_SHIFT) #define CHAN_DATA_VALID_INTR(n) BITFIELD_VAL(CHAN_DATA_VALID_INTR, n) // GPADC_REG_INT_MSKED_STS #define KEY_ERR1_INTR_MSKED (1 << 12) #define KEY_ERR0_INTR_MSKED (1 << 11) #define KEY_PRESS_INTR_MSKED (1 << 10) #define KEY_RELEASE_INTR_MSKED (1 << 9) #define SAMPLE_DONE_INTR_MSKED (1 << 8) #define CHAN_DATA_INTR_MSKED_SHIFT 0 #define CHAN_DATA_INTR_MSKED_MASK (0xFF << CHAN_DATA_INTR_MSKED_SHIFT) #define CHAN_DATA_INTR_MSKED(n) BITFIELD_VAL(CHAN_DATA_INTR_MSKED, n) // GPADC_REG_INT_CLR #define KEY_ERR1_INTR_CLR (1 << 12) #define KEY_ERR0_INTR_CLR (1 << 11) #define KEY_PRESS_INTR_CLR (1 << 10) #define KEY_RELEASE_INTR_CLR (1 << 9) #define SAMPLE_DONE_INTR_CLR (1 << 8) #define CHAN_DATA_INTR_CLR_SHIFT 0 #define CHAN_DATA_INTR_CLR_MASK (0xFF << CHAN_DATA_INTR_CLR_SHIFT) #define CHAN_DATA_INTR_CLR(n) BITFIELD_VAL(CHAN_DATA_INTR_CLR, n) // GPADC_REG_CH0_DATA #define DATA_CHAN0_SHIFT 0 #define DATA_CHAN0_MASK (0x3FF << DATA_CHAN0_SHIFT) #define DATA_CHAN0(n) BITFIELD_VAL(DATA_CHAN0, n) #else #error "Please update GPADC register definitions" #endif static int32_t g_adcSlope = 0; static int32_t g_adcIntcpt = 0; static bool gpadc_enabled = false; static bool adckey_enabled = false; static bool irq_enabled = false; static bool g_adcCalibrated = false; static HAL_GPADC_EVENT_CB_T gpadc_event_cb[HAL_GPADC_CHAN_QTY]; static enum HAL_GPADC_ATP_T gpadc_atp[HAL_GPADC_CHAN_QTY]; static enum HAL_GPADC_ATP_T hal_gpadc_get_min_atp(void) { enum HAL_GPADC_CHAN_T ch; enum HAL_GPADC_ATP_T atp = HAL_GPADC_ATP_NULL; for (ch = HAL_GPADC_CHAN_0; ch < HAL_GPADC_CHAN_QTY; ch++) { if (gpadc_atp[ch] != HAL_GPADC_ATP_NULL) { if (atp == HAL_GPADC_ATP_NULL || (uint32_t)gpadc_atp[ch] < (uint32_t)atp) { atp = gpadc_atp[ch]; } } } return atp; } static void hal_gpadc_update_atp(void) { enum HAL_GPADC_ATP_T atp; uint16_t val; atp = hal_gpadc_get_min_atp(); if (atp == HAL_GPADC_ATP_NULL || atp == HAL_GPADC_ATP_ONESHOT) { gpadc_reg_read(GPADC_REG_INTVL_EN, &val); val &= ~GPADC_INTERVAL_MODE; gpadc_reg_write(GPADC_REG_INTVL_EN, val); } else { gpadc_reg_read(GPADC_REG_INTVL_EN, &val); val |= GPADC_INTERVAL_MODE; gpadc_reg_write(GPADC_REG_INTVL_EN, val); val = atp * 1000 / 1024; gpadc_reg_write(GPADC_REG_INTVL_VAL, val); } } static int hal_gpadc_adc2volt_calib(void) { int32_t y1, y2, x1, x2; unsigned short efuse_a = 0; unsigned short efuse_b = 0; if (!g_adcCalibrated) { y1 = HAL_GPADC_MVOLT_A * 1000; y2 = HAL_GPADC_MVOLT_B * 1000; pmu_get_efuse(PMU_EFUSE_PAGE_BATTER_LV, &efuse_a); x1 = efuse_a > 0 ? efuse_a : HAL_GPADC_CALIB_DEFAULT_A; pmu_get_efuse(PMU_EFUSE_PAGE_BATTER_HV, &efuse_b); x2 = efuse_b > 0 ? efuse_b : HAL_GPADC_CALIB_DEFAULT_B; g_adcSlope = (y2 - y1) / (x2 - x1); g_adcIntcpt = ((y1 * x2) - (x1 * y2)) / ((x2 - x1) * 1000); g_adcCalibrated = true; TRACE(7, "%s efuse:%d/%d LV=%d, HV=%d, Slope:%d Intcpt:%d", __func__, efuse_a, efuse_b, x1, x2, g_adcSlope, g_adcIntcpt); } return 0; } static HAL_GPADC_MV_T hal_gpadc_adc2volt(uint16_t gpadcVal) { int32_t voltage; hal_gpadc_adc2volt_calib(); if (gpadcVal == HAL_GPADC_BAD_VALUE) { // Bad values from the GPADC are still Bad Values // for the voltage-speaking user. return HAL_GPADC_BAD_VALUE; } else { voltage = (((g_adcSlope * gpadcVal) / 1000) + (g_adcIntcpt)); return (voltage < 0) ? 0 : voltage; } } #ifdef PMU_IRQ_UNIFIED #define GPADC_IRQ_HDLR_PARAM uint16_t irq_status #else #define GPADC_IRQ_HDLR_PARAM void #endif static void hal_gpadc_irq_handler(GPADC_IRQ_HDLR_PARAM) { uint32_t lock; enum HAL_GPADC_CHAN_T ch; unsigned short read_val; uint16_t adc_val; HAL_GPADC_MV_T volt; #ifndef PMU_IRQ_UNIFIED unsigned short irq_status; gpadc_reg_read(GPADC_REG_INT_MSKED_STS, &irq_status); irq_status &= (CHAN_DATA_INTR_MSKED_MASK | SAMPLE_DONE_INTR_MSKED | KEY_RELEASE_INTR_MSKED | KEY_PRESS_INTR_MSKED | KEY_ERR0_INTR_MSKED | KEY_ERR1_INTR_MSKED); gpadc_reg_write(GPADC_REG_INT_CLR, irq_status); #endif if (irq_status & CHAN_DATA_INTR_MSKED((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6))) { for (ch = HAL_GPADC_CHAN_0; ch < HAL_GPADC_CHAN_QTY; ch++) { if (irq_status & CHAN_DATA_INTR_MSKED(1 << ch)) { switch (ch) { case HAL_GPADC_CHAN_BATTERY: case HAL_GPADC_CHAN_0: case HAL_GPADC_CHAN_2: case HAL_GPADC_CHAN_3: case HAL_GPADC_CHAN_4: case HAL_GPADC_CHAN_5: case HAL_GPADC_CHAN_6: gpadc_reg_read(GPADC_REG_CH0_DATA + ch, &adc_val); adc_val = GET_BITFIELD(adc_val, DATA_CHAN0); volt = hal_gpadc_adc2volt(adc_val); if (gpadc_event_cb[ch]) { gpadc_event_cb[ch](adc_val, volt); } if (gpadc_atp[ch] == HAL_GPADC_ATP_NULL || gpadc_atp[ch] == HAL_GPADC_ATP_ONESHOT) { lock = int_lock(); #ifndef VBAT_DIV_ALWAYS_ON if (ch == HAL_GPADC_CHAN_BATTERY) { gpadc_reg_read(GPADC_REG_VBAT_EN, &read_val); read_val &= ~REG_PU_VBAT_DIV; gpadc_reg_write(GPADC_REG_VBAT_EN, read_val); } #endif // Int mask gpadc_reg_read(GPADC_REG_INT_MASK, &read_val); read_val &= ~CHAN_DATA_INTR_MSK(1 << ch); gpadc_reg_write(GPADC_REG_INT_MASK, read_val); // Int enable gpadc_reg_read(GPADC_REG_INT_EN, &read_val); read_val &= ~CHAN_DATA_INTR_EN(1 << ch); gpadc_reg_write(GPADC_REG_INT_EN, read_val); // Channel enable gpadc_reg_read(GPADC_REG_CH_EN, &read_val); read_val &= ~CHAN_EN_REG(1 << ch); gpadc_reg_write(GPADC_REG_CH_EN, read_val); int_unlock(lock); } break; default: break; } } } } // Disable GPADC (GPADC_START will be cleared automatically unless in interval // mode) lock = int_lock(); gpadc_reg_read(GPADC_REG_CH_EN, &read_val); if ((read_val & CHAN_EN_REG((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6))) == 0) { gpadc_reg_read(GPADC_REG_START, &read_val); read_val &= ~GPADC_START; gpadc_reg_write(GPADC_REG_START, read_val); } int_unlock(lock); if (irq_status & (CHAN_DATA_INTR_MSKED(1 << 7) | KEY_RELEASE_INTR_MSKED | KEY_PRESS_INTR_MSKED | KEY_ERR0_INTR_MSKED | KEY_ERR1_INTR_MSKED)) { if (gpadc_event_cb[HAL_GPADC_CHAN_ADCKEY]) { enum HAL_ADCKEY_IRQ_STATUS_T adckey_irq; adckey_irq = 0; if (irq_status & KEY_RELEASE_INTR_MSKED) { adckey_irq |= HAL_ADCKEY_RELEASED; } if (irq_status & KEY_PRESS_INTR_MSKED) { adckey_irq |= HAL_ADCKEY_PRESSED; } if (irq_status & KEY_ERR0_INTR_MSKED) { adckey_irq |= HAL_ADCKEY_ERR0; } if (irq_status & KEY_ERR1_INTR_MSKED) { adckey_irq |= HAL_ADCKEY_ERR1; } if (irq_status & CHAN_DATA_INTR_MSKED(1 << 7)) { adckey_irq |= HAL_ADCKEY_ADC_VALID; lock = int_lock(); // Int mask gpadc_reg_read(GPADC_REG_INT_MASK, &read_val); read_val &= ~CHAN_DATA_INTR_MSK(1 << 7); gpadc_reg_write(GPADC_REG_INT_MASK, read_val); // Int enable gpadc_reg_read(GPADC_REG_INT_EN, &read_val); read_val &= ~CHAN_DATA_INTR_EN(1 << 7); gpadc_reg_write(GPADC_REG_INT_EN, read_val); int_unlock(lock); // No voltage conversion gpadc_reg_read(GPADC_REG_CH0_DATA + HAL_GPADC_CHAN_ADCKEY, &adc_val); adc_val = GET_BITFIELD(adc_val, DATA_CHAN0); } else { adc_val = HAL_GPADC_BAD_VALUE; } ((HAL_ADCKEY_EVENT_CB_T)gpadc_event_cb[HAL_GPADC_CHAN_ADCKEY])(adckey_irq, adc_val); } } } bool hal_gpadc_get_volt(enum HAL_GPADC_CHAN_T ch, HAL_GPADC_MV_T *volt) { bool res = false; unsigned short read_val; if (ch >= HAL_GPADC_CHAN_QTY) { return res; } gpadc_reg_read(GPADC_REG_INT_RAW_STS, &read_val); if (read_val & CHAN_DATA_VALID_INTR(1 << ch)) { // Clear the channel valid status gpadc_reg_write(GPADC_REG_INT_CLR, CHAN_DATA_INTR_CLR(1 << ch)); gpadc_reg_read(GPADC_REG_CH0_DATA + ch, &read_val); read_val = GET_BITFIELD(read_val, DATA_CHAN0); *volt = hal_gpadc_adc2volt(read_val); res = true; } return res; } static void hal_gpadc_irq_control(void) { if (gpadc_enabled || adckey_enabled) { if (!irq_enabled) { irq_enabled = true; #ifdef PMU_IRQ_UNIFIED pmu_set_irq_unified_handler(PMU_IRQ_TYPE_GPADC, hal_gpadc_irq_handler); #else NVIC_SetVector(GPADC_IRQn, (uint32_t)hal_gpadc_irq_handler); NVIC_SetPriority(GPADC_IRQn, IRQ_PRIORITY_NORMAL); NVIC_ClearPendingIRQ(GPADC_IRQn); NVIC_EnableIRQ(GPADC_IRQn); #endif } } else { if (irq_enabled) { irq_enabled = false; #ifdef PMU_IRQ_UNIFIED pmu_set_irq_unified_handler(PMU_IRQ_TYPE_GPADC, NULL); #else NVIC_DisableIRQ(GPADC_IRQn); #endif } } } int hal_gpadc_open(enum HAL_GPADC_CHAN_T channel, enum HAL_GPADC_ATP_T atp, HAL_GPADC_EVENT_CB_T cb) { uint32_t lock; unsigned short val; unsigned short reg_start_mask; if (channel >= HAL_GPADC_CHAN_QTY) { return -1; } // NOTE: ADCKEY callback is not set here, but in hal_adckey_set_irq_handler() if (channel != HAL_GPADC_CHAN_ADCKEY) { gpadc_event_cb[channel] = cb; gpadc_atp[channel] = atp; } switch (channel) { case HAL_GPADC_CHAN_BATTERY: // Enable vbat measurement clock // vbat div enable lock = int_lock(); gpadc_reg_read(GPADC_REG_VBAT_EN, &val); val |= REG_PU_VBAT_DIV; gpadc_reg_write(GPADC_REG_VBAT_EN, val); int_unlock(lock); #ifndef VBAT_DIV_ALWAYS_ON // GPADC VBAT needs 10us to be stable and consumes 13mA current hal_sys_timer_delay_us(20); #endif case HAL_GPADC_CHAN_0: case HAL_GPADC_CHAN_2: case HAL_GPADC_CHAN_3: case HAL_GPADC_CHAN_4: case HAL_GPADC_CHAN_5: case HAL_GPADC_CHAN_6: case HAL_GPADC_CHAN_ADCKEY: lock = int_lock(); #if defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A) if (channel == HAL_GPADC_CHAN_3) { pmu_led_set_hiz(HAL_GPIO_PIN_LED2); } #endif // Int mask if (channel == HAL_GPADC_CHAN_ADCKEY || gpadc_event_cb[channel]) { // 1) Always enable ADCKEY mask // 2) Enable mask if handler is not null gpadc_reg_read(GPADC_REG_INT_MASK, &val); val |= CHAN_DATA_INTR_MSK(1 << channel); gpadc_reg_write(GPADC_REG_INT_MASK, val); gpadc_enabled = true; hal_gpadc_irq_control(); } // Int enable gpadc_reg_read(GPADC_REG_INT_EN, &val); val |= CHAN_DATA_INTR_EN(1 << channel); gpadc_reg_write(GPADC_REG_INT_EN, val); // Clear the channel valid status gpadc_reg_write(GPADC_REG_INT_CLR, CHAN_DATA_INTR_CLR(1 << channel)); // Channel enable if (channel == HAL_GPADC_CHAN_ADCKEY) { reg_start_mask = KEY_START; } else { hal_gpadc_update_atp(); reg_start_mask = GPADC_START; if (GPADC_REG_START == GPADC_REG_CH_EN) { reg_start_mask |= CHAN_EN_REG(1 << channel); } else { gpadc_reg_read(GPADC_REG_CH_EN, &val); val |= CHAN_EN_REG(1 << channel); gpadc_reg_write(GPADC_REG_CH_EN, val); } } // GPADC enable gpadc_reg_read(GPADC_REG_START, &val); val |= reg_start_mask; gpadc_reg_write(GPADC_REG_START, val); int_unlock(lock); break; default: break; } return 0; } int hal_gpadc_close(enum HAL_GPADC_CHAN_T channel) { uint32_t lock; unsigned short val; unsigned short chan_int_en; unsigned short reg_start; if (channel >= HAL_GPADC_CHAN_QTY) { return -1; } if (channel != HAL_GPADC_CHAN_ADCKEY) { gpadc_atp[channel] = HAL_GPADC_ATP_NULL; } switch (channel) { case HAL_GPADC_CHAN_BATTERY: #ifndef VBAT_DIV_ALWAYS_ON // disable vbat measurement clock // vbat div disable lock = int_lock(); gpadc_reg_read(GPADC_REG_VBAT_EN, &val); val &= ~REG_PU_VBAT_DIV; gpadc_reg_write(GPADC_REG_VBAT_EN, val); int_unlock(lock); #endif case HAL_GPADC_CHAN_0: case HAL_GPADC_CHAN_2: case HAL_GPADC_CHAN_3: case HAL_GPADC_CHAN_4: case HAL_GPADC_CHAN_5: case HAL_GPADC_CHAN_6: case HAL_GPADC_CHAN_ADCKEY: lock = int_lock(); // Int mask gpadc_reg_read(GPADC_REG_INT_MASK, &val); val &= ~CHAN_DATA_INTR_MSK(1 << channel); gpadc_reg_write(GPADC_REG_INT_MASK, val); // Int enable gpadc_reg_read(GPADC_REG_INT_EN, &chan_int_en); chan_int_en &= ~CHAN_DATA_INTR_EN(1 << channel); gpadc_reg_write(GPADC_REG_INT_EN, chan_int_en); // Channel/GPADC enable gpadc_reg_read(GPADC_REG_START, ®_start); if (channel == HAL_GPADC_CHAN_ADCKEY) { reg_start &= ~KEY_START; } else { if (GPADC_REG_START == GPADC_REG_CH_EN) { reg_start &= ~CHAN_EN_REG(1 << channel); val = reg_start; } else { gpadc_reg_read(GPADC_REG_CH_EN, &val); val &= ~CHAN_EN_REG(1 << channel); gpadc_reg_write(GPADC_REG_CH_EN, val); } if (val & CHAN_EN_REG((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6))) { hal_gpadc_update_atp(); } else { reg_start &= ~GPADC_START; } } gpadc_reg_write(GPADC_REG_START, reg_start); if ((chan_int_en & CHAN_DATA_INTR_EN((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7))) == 0) { gpadc_enabled = false; hal_gpadc_irq_control(); } int_unlock(lock); break; default: break; } return 0; } void hal_gpadc_sleep(void) { unsigned short val; #if defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A) return; #endif gpadc_reg_read(GPADC_REG_START, &val); if (val & GPADC_START) { val &= ~GPADC_START; gpadc_reg_write(GPADC_REG_START, val); } } void hal_gpadc_wakeup(void) { unsigned short val; #if defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A) return; #endif gpadc_reg_read(GPADC_REG_CH_EN, &val); if (val & CHAN_EN_REG((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6))) { if (GPADC_REG_START != GPADC_REG_CH_EN) { gpadc_reg_read(GPADC_REG_START, &val); } val |= GPADC_START; gpadc_reg_write(GPADC_REG_START, val); } } void hal_adckey_set_irq_handler(HAL_ADCKEY_EVENT_CB_T cb) { gpadc_event_cb[HAL_GPADC_CHAN_ADCKEY] = (HAL_GPADC_EVENT_CB_T)cb; } int hal_adckey_set_irq(enum HAL_ADCKEY_IRQ_T type) { uint32_t lock; uint16_t val; uint16_t set_mask; uint16_t clr_mask; uint16_t set_en; uint16_t clr_en; set_mask = 0; clr_mask = 0; set_en = 0; clr_en = 0; if (type == HAL_ADCKEY_IRQ_NONE) { clr_mask = KEY_RELEASE_INTR_MSK | KEY_PRESS_INTR_MSK | KEY_ERR0_INTR_MSK | KEY_ERR1_INTR_MSK; clr_en = KEY_RELEASE_INTR_EN | KEY_PRESS_INTR_EN | KEY_ERR0_INTR_EN | KEY_ERR1_INTR_EN; adckey_enabled = false; } else if (type == HAL_ADCKEY_IRQ_PRESSED) { set_mask = KEY_PRESS_INTR_MSK | KEY_ERR0_INTR_MSK | KEY_ERR1_INTR_MSK; clr_mask = KEY_RELEASE_INTR_MSK; set_en = KEY_PRESS_INTR_EN | KEY_ERR0_INTR_EN | KEY_ERR1_INTR_EN; clr_en = KEY_RELEASE_INTR_EN; adckey_enabled = true; } else if (type == HAL_ADCKEY_IRQ_RELEASED) { set_mask = KEY_RELEASE_INTR_MSK | KEY_ERR0_INTR_MSK | KEY_ERR1_INTR_MSK; clr_mask = KEY_PRESS_INTR_MSK; set_en = KEY_RELEASE_INTR_EN | KEY_ERR0_INTR_EN | KEY_ERR1_INTR_EN; clr_en = KEY_PRESS_INTR_EN; adckey_enabled = true; } else if (type == HAL_ADCKEY_IRQ_BOTH) { set_mask = KEY_RELEASE_INTR_MSK | KEY_PRESS_INTR_MSK | KEY_ERR0_INTR_MSK | KEY_ERR1_INTR_MSK; set_en = KEY_RELEASE_INTR_EN | KEY_PRESS_INTR_EN | KEY_ERR0_INTR_EN | KEY_ERR1_INTR_EN; adckey_enabled = true; } else { return 1; } lock = int_lock(); gpadc_reg_read(GPADC_REG_INT_MASK, &val); val &= ~clr_mask; val |= set_mask; gpadc_reg_write(GPADC_REG_INT_MASK, val); gpadc_reg_read(GPADC_REG_INT_EN, &val); val &= ~clr_en; val |= set_en; gpadc_reg_write(GPADC_REG_INT_EN, val); hal_gpadc_irq_control(); int_unlock(lock); return 0; } #endif // !GPADC_CHIP_SPECIFIC