summaryrefslogtreecommitdiffstats
path: root/src/soc/mediatek/common/auxadc.c
diff options
context:
space:
mode:
authorPo Xu <jg_poxu@mediatek.com>2020-08-04 11:39:47 +0800
committerHung-Te Lin <hungte@chromium.org>2020-11-20 08:40:19 +0000
commit3f11803075cc13e377287240734cf82654f48ade (patch)
tree71cf455b55236aab0514dec6c31c31939f1e31a8 /src/soc/mediatek/common/auxadc.c
parent0fd62f5b7963b2128d48aca190a93e9b94d70d13 (diff)
downloadcoreboot-3f11803075cc13e377287240734cf82654f48ade.tar.gz
coreboot-3f11803075cc13e377287240734cf82654f48ade.tar.bz2
coreboot-3f11803075cc13e377287240734cf82654f48ade.zip
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.c72
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 000000000000..6dbf12bbe9ed
--- /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));
+}