diff options
author | Po Xu <jg_poxu@mediatek.com> | 2020-08-04 11:39:47 +0800 |
---|---|---|
committer | Hung-Te Lin <hungte@chromium.org> | 2020-11-20 08:40:19 +0000 |
commit | 3f11803075cc13e377287240734cf82654f48ade (patch) | |
tree | 71cf455b55236aab0514dec6c31c31939f1e31a8 /src/soc/mediatek/common/auxadc.c | |
parent | 0fd62f5b7963b2128d48aca190a93e9b94d70d13 (diff) |
soc/mediatek: Move auxadc driver from MT8183 to common
The auxadc (auxiliary analogue-to-digital conversion) is a unit
to identify the plugged peripherals or measure the temperature
or voltages.
The MT8183 auxadc driver can be shared by multiple MediaTek SoCs
so we should move it to the common folder.
Signed-off-by: Po Xu <jg_poxu@mediatek.com>
Change-Id: Id4553e99c3578fa40e28b19a6e010b52650ba41e
Reviewed-on: https://review.coreboot.org/c/coreboot/+/46390
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Diffstat (limited to 'src/soc/mediatek/common/auxadc.c')
-rw-r--r-- | src/soc/mediatek/common/auxadc.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/soc/mediatek/common/auxadc.c b/src/soc/mediatek/common/auxadc.c new file mode 100644 index 0000000000..6dbf12bbe9 --- /dev/null +++ b/src/soc/mediatek/common/auxadc.c @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <assert.h> +#include <delay.h> +#include <device/mmio.h> +#include <soc/addressmap.h> +#include <soc/auxadc.h> +#include <soc/efuse.h> +#include <timer.h> + +static struct mtk_auxadc_regs *const mtk_auxadc = (void *)AUXADC_BASE; + +#define ADC_GE_A_SHIFT 10 +#define ADC_GE_A_MASK (0x3ff << ADC_GE_A_SHIFT) +#define ADC_OE_A_SHIFT 0 +#define ADC_OE_A_MASK (0x3ff << ADC_OE_A_SHIFT) +#define ADC_CALI_EN_A_SHIFT 20 +#define ADC_CALI_EN_A_MASK (0x1 << ADC_CALI_EN_A_SHIFT) + +static int cali_oe; +static int cali_ge; +static int calibrated = 0; +static void mt_auxadc_update_cali(void) +{ + uint32_t cali_reg; + int cali_ge_a; + int cali_oe_a; + + cali_reg = read32(&mtk_efuse->adc_cali_reg); + + if ((cali_reg & ADC_CALI_EN_A_MASK) != 0) { + cali_oe_a = (cali_reg & ADC_OE_A_MASK) >> ADC_OE_A_SHIFT; + cali_ge_a = (cali_reg & ADC_GE_A_MASK) >> ADC_GE_A_SHIFT; + cali_ge = cali_ge_a - 512; + cali_oe = cali_oe_a - 512; + } +} + +static uint32_t auxadc_get_rawdata(int channel) +{ + setbits32(&mtk_infracfg->module_sw_cg_1_clr, 1 << 10); + assert(wait_ms(300, !(read32(&mtk_auxadc->con2) & 0x1))); + + clrbits32(&mtk_auxadc->con1, 1 << channel); + assert(wait_ms(300, !(read32(&mtk_auxadc->data[channel]) & (1 << 12)))); + + setbits32(&mtk_auxadc->con1, 1 << channel); + udelay(25); + assert(wait_ms(300, read32(&mtk_auxadc->data[channel]) & (1 << 12))); + + uint32_t value = read32(&mtk_auxadc->data[channel]) & 0x0FFF; + + setbits32(&mtk_infracfg->module_sw_cg_1_set, 1 << 10); + + return value; +} + +unsigned int auxadc_get_voltage_uv(unsigned int channel) +{ + uint32_t raw_value; + assert(channel < 16); + + if (!calibrated) { + mt_auxadc_update_cali(); + calibrated = 1; + } + + /* 1.5V in 4096 steps */ + raw_value = auxadc_get_rawdata(channel); + raw_value = raw_value - cali_oe; + return (unsigned int)((int64_t)raw_value * 1500000 / (4096 + cali_ge)); +} |