/*************************************************************************** * * 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 "stddef.h" #include "cmsis_nvic.h" #include "hal_gpadc.h" #include "hal_trace.h" #include "hal_analogif.h" #include "pmu.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<= HAL_GPADC_CHAN_QTY) { return res; } gpadc_reg_read(GPADC_REG_INT_RAW_STS, &read_val); if (read_val & CHAN_DATA_VALID_INTR(1<= 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<= 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<