unplugged-kernel/drivers/misc/mediatek/pmic/mt6358/v1/pmic_auxadc.c

785 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2016 MediaTek Inc.
*/
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/pm_wakeup.h>
#include <linux/delay.h>
#include <linux/ratelimit.h>
#include <linux/timekeeping.h>
#include <linux/math64.h>
#include <linux/of_address.h>
#include <linux/iio/consumer.h>
#include <linux/iio/adc/mt635x-auxadc-internal.h>
#include "include/pmic.h"
#include "include/pmic_auxadc.h"
#ifdef CONFIG_MTK_AEE_FEATURE
#include <mt-plat/aee.h>
#endif
#include <mt-plat/upmu_common.h>
#include <mt-plat/mtk_auxadc_intf.h>
#ifdef CONFIG_MTK_PMIC_WRAP_HAL
#include <mach/mtk_pmic_wrap.h>
#endif
#ifndef CONFIG_MTK_GAUGE_VERSION
#define CONFIG_MTK_GAUGE_VERSION 0
#endif
#if (CONFIG_MTK_GAUGE_VERSION == 30)
#include <mt-plat/v1/mtk_battery.h>
#include <mtk_battery_internal.h>
#endif
static struct device *pmic_auxadc_dev;
static int auxadc_bat_temp_cali(int bat_temp, int precision_factor);
static bool mts_enable = true;
/*********************************
* PMIC AUXADC Exported API
*********************************/
static DEFINE_MUTEX(auxadc_ch3_mutex);
static unsigned int g_pmic_pad_vbif28_vol;
unsigned int pmic_get_vbif28_volt(void)
{
return g_pmic_pad_vbif28_vol;
}
bool is_isense_supported(void)
{
/* PMIC MT6358 does not support ISENSE */
return false;
}
/* BAT_TEMP background control */
void wk_auxadc_bgd_ctrl(unsigned char en)
{
pmic_set_hk_reg_value(PMIC_AUXADC_BAT_TEMP_IRQ_EN_MAX, en);
pmic_set_hk_reg_value(PMIC_AUXADC_BAT_TEMP_EN_MAX, en);
pmic_set_hk_reg_value(PMIC_AUXADC_BAT_TEMP_IRQ_EN_MIN, en);
pmic_set_hk_reg_value(PMIC_AUXADC_BAT_TEMP_EN_MIN, en);
}
void pmic_auxadc_suspend(void)
{
#ifndef IPIMB
wk_auxadc_bgd_ctrl(0);
#endif
/* special call to restore bat_temp_prev when enter suspend */
auxadc_bat_temp_cali(-1, -1);
}
void pmic_auxadc_resume(void)
{
#ifndef IPIMB
wk_auxadc_bgd_ctrl(1);
#endif
}
void lockadcch3(void)
{
mutex_lock(&auxadc_ch3_mutex);
}
void unlockadcch3(void)
{
mutex_unlock(&auxadc_ch3_mutex);
}
void wk_auxadc_reset(void)
{
pmic_set_register_value(PMIC_RG_AUXADC_RST, 1);
pmic_set_register_value(PMIC_RG_AUXADC_RST, 0);
pmic_set_register_value(PMIC_BANK_AUXADC_SWRST, 1);
pmic_set_register_value(PMIC_BANK_AUXADC_SWRST, 0);
/* avoid GPS can't receive AUXADC ready after reset, request again */
pmic_set_register_value(PMIC_AUXADC_RQST_CH7, 1);
pmic_set_register_value(PMIC_AUXADC_RQST_DCXO_BY_GPS, 1);
pr_notice("reset AUXADC done\n");
}
/*********************************
* PMIC AUXADC Calibration
*********************************/
static unsigned int g_DEGC;
static unsigned int g_O_VTS;
static unsigned int g_O_SLOPE_SIGN;
static unsigned int g_O_SLOPE;
static unsigned int g_CALI_FROM_EFUSE_EN;
static unsigned int g_GAIN_AUX;
static unsigned int g_SIGN_AUX;
static unsigned int g_GAIN_BGRL;
static unsigned int g_SIGN_BGRL;
static unsigned int g_TEMP_L_CALI;
static unsigned int g_GAIN_BGRH;
static unsigned int g_SIGN_BGRH;
static unsigned int g_TEMP_H_CALI;
static unsigned int g_AUXCALI_EN;
static unsigned int g_BGRCALI_EN;
static int wk_aux_cali(int T_curr, int vbat_out)
{
signed long long coeff_gain_aux = 0;
signed long long vbat_cali = 0;
coeff_gain_aux = (317220 + 11960 * (signed long long)g_GAIN_AUX);
vbat_cali = div_s64((vbat_out * (T_curr - 250) * coeff_gain_aux), 255);
vbat_cali = div_s64(vbat_cali, 1000000000);
if (g_SIGN_AUX == 0)
vbat_out += vbat_cali;
else
vbat_out -= vbat_cali;
return vbat_out;
}
static int wk_bgr_cali(int T_curr, int vbat_out)
{
signed long long coeff_gain_bgr = 0;
signed int T_L = -100 + g_TEMP_L_CALI * 25;
signed int T_H = 600 + g_TEMP_H_CALI * 25;
if (T_curr < T_L) {
coeff_gain_bgr = (127 + 8 * (signed long long)g_GAIN_BGRL);
if (g_SIGN_BGRL == 0)
vbat_out += div_s64((vbat_out * (T_curr - T_L) *
coeff_gain_bgr), 127000000);
else
vbat_out -= div_s64((vbat_out * (T_curr - T_L) *
coeff_gain_bgr), 127000000);
} else if (T_curr > T_H) {
coeff_gain_bgr = (127 + 8 * (signed long long)g_GAIN_BGRH);
if (g_SIGN_BGRH == 0)
vbat_out -= div_s64((vbat_out * (T_curr - T_H) *
coeff_gain_bgr), 127000000);
else
vbat_out += div_s64((vbat_out * (T_curr - T_H) *
coeff_gain_bgr), 127000000);
}
return vbat_out;
}
/* vbat_out unit is 0.1mV, vthr unit is mV */
int wk_vbat_cali(int vbat_out, int precision_factor)
{
int mV_diff = 0;
int T_curr = 0; /* unit: 0.1 degrees C*/
int vbat_out_old;
int vthr;
vthr = auxadc_priv_read_channel(pmic_auxadc_dev, AUXADC_CHIP_TEMP);
mV_diff = vthr - g_O_VTS * 1800 / 4096;
if (g_O_SLOPE_SIGN == 0)
T_curr = mV_diff * 10000 / (signed int)(1681 + g_O_SLOPE * 10);
else
T_curr = mV_diff * 10000 / (signed int)(1681 - g_O_SLOPE * 10);
T_curr = (g_DEGC * 10 / 2) - T_curr;
/*pr_info("%d\n", T_curr);*/
if (precision_factor > 1)
vbat_out *= precision_factor;
vbat_out_old = vbat_out;
if (g_AUXCALI_EN == 1) {
vbat_out = wk_aux_cali(T_curr, vbat_out);
/*pr_info("vbat_out_auxcali = %d\n", vbat_out);*/
}
if (g_BGRCALI_EN == 1) {
vbat_out = wk_bgr_cali(T_curr, vbat_out);
/*pr_info("vbat_out_bgrcali = %d\n", vbat_out);*/
}
if (abs(vbat_out - vbat_out_old) > 1000) {
pr_notice("vbat_out_old=%d, vthr=%d, T_curr=%d, vbat_out=%d\n",
vbat_out_old, vthr, T_curr, vbat_out);
pr_notice("%d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
g_DEGC, g_O_VTS, g_O_SLOPE_SIGN, g_O_SLOPE,
g_SIGN_AUX, g_SIGN_BGRL, g_SIGN_BGRH,
g_AUXCALI_EN, g_BGRCALI_EN,
g_GAIN_AUX, g_GAIN_BGRL, g_GAIN_BGRH,
g_TEMP_L_CALI, g_TEMP_H_CALI);
#ifdef CONFIG_MTK_AEE_FEATURE
aee_kernel_warning("PMIC AUXADC CALI", "VBAT CALI");
#endif
} else
pr_info("vbat_out_old=%d, vthr=%d, T_curr=%d, vbat_out=%d\n",
vbat_out_old, vthr, T_curr, vbat_out);
if (precision_factor > 1)
vbat_out = DIV_ROUND_CLOSEST(vbat_out, precision_factor);
return vbat_out;
}
static void auxadc_cali_init(struct device_node *np)
{
unsigned int efuse = 0;
unsigned int efuse_offset;
if (of_property_read_u32(np, "cali-efuse-offset", &efuse_offset))
efuse_offset = 0;
if (pmic_get_register_value(PMIC_AUXADC_EFUSE_ADC_CALI_EN) == 1) {
g_DEGC = pmic_get_register_value(PMIC_AUXADC_EFUSE_DEGC_CALI);
if (g_DEGC < 38 || g_DEGC > 60)
g_DEGC = 53;
g_O_VTS = pmic_get_register_value(PMIC_AUXADC_EFUSE_O_VTS);
g_O_SLOPE_SIGN =
pmic_get_register_value(PMIC_AUXADC_EFUSE_O_SLOPE_SIGN);
g_O_SLOPE = pmic_get_register_value(PMIC_AUXADC_EFUSE_O_SLOPE);
} else {
g_DEGC = 50;
g_O_VTS = 1600;
}
efuse = pmic_Read_Efuse_HPOffset(39 + efuse_offset);
g_CALI_FROM_EFUSE_EN = (efuse >> 2) & 0x1;
if (g_CALI_FROM_EFUSE_EN == 1) {
g_SIGN_AUX = (efuse >> 3) & 0x1;
g_AUXCALI_EN = (efuse >> 6) & 0x1;
g_GAIN_AUX = (efuse >> 8) & 0xFF;
} else {
g_SIGN_AUX = 0;
g_AUXCALI_EN = 1;
g_GAIN_AUX = 106;
}
g_SIGN_BGRL = (efuse >> 4) & 0x1;
g_SIGN_BGRH = (efuse >> 5) & 0x1;
g_BGRCALI_EN = (efuse >> 7) & 0x1;
efuse = pmic_Read_Efuse_HPOffset(40 + efuse_offset);
g_GAIN_BGRL = (efuse >> 9) & 0x7F;
efuse = pmic_Read_Efuse_HPOffset(41 + efuse_offset);
g_GAIN_BGRH = (efuse >> 9) & 0x7F;
efuse = pmic_Read_Efuse_HPOffset(42 + efuse_offset);
g_TEMP_L_CALI = (efuse >> 10) & 0x7;
g_TEMP_H_CALI = (efuse >> 13) & 0x7;
pr_info("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
g_DEGC, g_O_VTS, g_O_SLOPE_SIGN, g_O_SLOPE,
g_CALI_FROM_EFUSE_EN, g_SIGN_AUX, g_SIGN_BGRL, g_SIGN_BGRH,
g_AUXCALI_EN, g_BGRCALI_EN,
g_GAIN_AUX, g_GAIN_BGRL, g_GAIN_BGRH,
g_TEMP_L_CALI, g_TEMP_H_CALI);
}
/*********************************
* PMIC AUXADC debug register dump
*********************************/
#define DBG_REG_SIZE 384
#define BAT_TEMP_AEE_DBG 0
struct pmic_adc_dbg_st {
int ktime_sec;
unsigned short reg[DBG_REG_SIZE];
};
static unsigned int adc_dbg_addr[DBG_REG_SIZE];
static void wk_auxadc_dbg_dump(void)
{
unsigned char reg_log[861] = "", reg_str[21] = "";
unsigned short i, j;
static unsigned char dbg_stamp;
static struct pmic_adc_dbg_st pmic_adc_dbg[4];
for (i = 0; adc_dbg_addr[i] != 0; i++)
pmic_adc_dbg[dbg_stamp].reg[i] =
upmu_get_reg_value(adc_dbg_addr[i]);
pmic_adc_dbg[dbg_stamp].ktime_sec = (int)get_monotonic_coarse().tv_sec;
dbg_stamp++;
if (dbg_stamp >= 4)
dbg_stamp = 0;
for (i = 0; i < 4; i++) {
if (pmic_adc_dbg[dbg_stamp].ktime_sec == 0) {
dbg_stamp++;
if (dbg_stamp >= 4)
dbg_stamp = 0;
continue;
}
for (j = 0; adc_dbg_addr[j] != 0; j++) {
if (j != 0 && j % 43 == 0) {
pr_notice("%d %s\n",
pmic_adc_dbg[dbg_stamp].ktime_sec,
reg_log);
strncpy(reg_log, "", 860);
}
snprintf(reg_str, 20, "Reg[0x%x]=0x%x, ",
adc_dbg_addr[j],
pmic_adc_dbg[dbg_stamp].reg[j]);
strncat(reg_log, reg_str, 860);
}
pr_notice("%d %s\n",
pmic_adc_dbg[dbg_stamp].ktime_sec,
reg_log);
strncpy(reg_log, "", 860);
dbg_stamp++;
if (dbg_stamp >= 4)
dbg_stamp = 0;
}
}
/* BAT_TEMP filter Maxima and minima then average */
static int bat_temp_filter(int *arr, unsigned short size)
{
unsigned char i, i_max, i_min = 0;
int arr_max = 0, arr_min = arr[0];
int sum = 0;
for (i = 0; i < size; i++) {
sum += arr[i];
if (arr[i] > arr_max) {
arr_max = arr[i];
i_max = i;
} else if (arr[i] < arr_min) {
arr_min = arr[i];
i_min = i;
}
}
sum = sum - arr_max - arr_min;
return (sum/(size - 2));
}
static int wk_bat_temp_dbg(int bat_temp_prev, int bat_temp)
{
int vbif28, bat_temp_new = bat_temp;
int arr_bat_temp[5];
unsigned short i;
vbif28 = auxadc_priv_read_channel(pmic_auxadc_dev, AUXADC_VBIF);
pr_notice("BAT_TEMP_PREV:%d,BAT_TEMP:%d,VBIF28:%d\n",
bat_temp_prev, bat_temp, vbif28);
if (bat_temp < 200 || abs(bat_temp_prev - bat_temp) > 100) {
wk_auxadc_dbg_dump();
for (i = 0; i < 5; i++) {
arr_bat_temp[i] =
auxadc_priv_read_channel(pmic_auxadc_dev,
AUXADC_BAT_TEMP);
}
bat_temp_new = bat_temp_filter(arr_bat_temp, 5);
pr_notice("%d,%d,%d,%d,%d, BAT_TEMP_NEW:%d\n",
arr_bat_temp[0], arr_bat_temp[1], arr_bat_temp[2],
arr_bat_temp[3], arr_bat_temp[4], bat_temp_new);
}
return bat_temp_new;
}
static void wk_auxadc_dbg_init(void)
{
unsigned short i;
unsigned int addr = 0x1000;
/* All of AUXADC */
for (i = 0; addr <= 0x1266; i++) {
adc_dbg_addr[i] = addr;
addr += 0x2;
}
/* Clock related */
adc_dbg_addr[i++] = MT6358_HK_TOP_CLK_CON0;
adc_dbg_addr[i++] = MT6358_HK_TOP_CLK_CON1;
/* RST related */
adc_dbg_addr[i++] = MT6358_HK_TOP_RST_CON0;
/* Others */
adc_dbg_addr[i++] = MT6358_BATON_ANA_CON0;
adc_dbg_addr[i++] = MT6358_PCHR_VREF_ELR_0;
adc_dbg_addr[i++] = MT6358_PCHR_VREF_ELR_1;
}
/*********************************
* PMIC AUXADC MDRT debug(MTS=Modem Temp Share)
*********************************/
/* global variable */
static unsigned int mdrt_adc;
static struct wakeup_source* mdrt_wakelock;
static struct mutex mdrt_mutex;
static struct task_struct *mdrt_thread_handle;
/* wake up the thread to polling MDRT data in ms period */
void wake_up_mdrt_thread(void)
{
HKLOG("[%s]\n", __func__);
if (mdrt_thread_handle != NULL) {
__pm_stay_awake(mdrt_wakelock);
wake_up_process(mdrt_thread_handle);
} else
pr_notice(PMICTAG "[%s] mdrt_thread_handle not ready\n",
__func__);
}
/* dump MDRT related register */
static void mdrt_reg_dump(void)
{
#ifdef CONFIG_MTK_PMIC_WRAP_HAL
pwrap_dump_all_register();
#endif
pr_notice("AUXADC_ADC15 = 0x%x\n",
upmu_get_reg_value(MT6358_AUXADC_ADC15));
pr_notice("AUXADC_ADC16 = 0x%x\n",
upmu_get_reg_value(MT6358_AUXADC_ADC16));
pr_notice("AUXADC_ADC17 = 0x%x\n",
upmu_get_reg_value(MT6358_AUXADC_ADC17));
pr_notice("AUXADC_ADC31 = 0x%x\n",
upmu_get_reg_value(MT6358_AUXADC_ADC31));
pr_notice("AUXADC_MDRT_0 = 0x%x\n",
upmu_get_reg_value(MT6358_AUXADC_MDRT_0));
pr_notice("AUXADC_MDRT_1 = 0x%x\n",
upmu_get_reg_value(MT6358_AUXADC_MDRT_1));
pr_notice("AUXADC_MDRT_2 = 0x%x\n",
upmu_get_reg_value(MT6358_AUXADC_MDRT_2));
pr_notice("AUXADC_MDRT_3 = 0x%x\n",
upmu_get_reg_value(MT6358_AUXADC_MDRT_3));
pr_notice("AUXADC_MDRT_4 = 0x%x\n",
upmu_get_reg_value(MT6358_AUXADC_MDRT_4));
/*--AUXADC CLK--*/
pr_notice("RG_AUXADC_CK_PDN = 0x%x, RG_AUXADC_CK_PDN_HWEN = 0x%x\n",
pmic_get_register_value(PMIC_RG_AUXADC_CK_PDN),
pmic_get_register_value(PMIC_RG_AUXADC_CK_PDN_HWEN));
}
/* Check MDRT_ADC data has changed or not */
void mdrt_monitor(void)
{
static unsigned int mdrt_cnt;
static int mdrt_timestamp;
int mdrt_timestamp_cur = 0;
unsigned int temp_mdrt_adc = 0;
if (mdrt_adc == 0)
return;
mdrt_timestamp_cur = (int)get_monotonic_coarse().tv_sec;
if ((mdrt_timestamp_cur - mdrt_timestamp) < 5)
return;
mdrt_timestamp = mdrt_timestamp_cur;
temp_mdrt_adc = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_MDRT);
pr_notice("[MDRT_ADC] OLD = 0x%x, NOW = 0x%x, CNT = %d\n",
mdrt_adc, temp_mdrt_adc, mdrt_cnt);
if (temp_mdrt_adc != mdrt_adc) {
mdrt_cnt = 0;
mdrt_adc = temp_mdrt_adc;
return;
}
mdrt_cnt++;
if (mdrt_cnt >= 7 && mdrt_cnt < 9) {
/* trigger CH7 in AP/MD/GPS and just delay 1ms to get data */
pmic_set_hk_reg_value(PMIC_AUXADC_RQST_CH7, 1);
pmic_set_hk_reg_value(PMIC_AUXADC_RQST_CH7_BY_MD, 1);
pmic_set_hk_reg_value(PMIC_AUXADC_RQST_CH7_BY_GPS, 1);
mdelay(1);
mdrt_reg_dump();
}
if (mdrt_cnt > 15) {
mdrt_reg_dump();
mdrt_cnt = 0;
wake_up_mdrt_thread();
}
mdrt_adc = temp_mdrt_adc;
}
static int mdrt_polling_rdy(unsigned int *trig_prd,
unsigned int *rdy_time, unsigned int *mdrt_adc)
{
while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_MDRT) == 1) {
if (*trig_prd > 100) {
pr_notice("[MDRT_ADC] no trigger\n");
return -1;
}
(*trig_prd)++;
mdelay(1);
}
while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_MDRT) == 0) {
if (*rdy_time > 100) {
pr_notice("[MDRT_ADC] no ready\n");
return -2;
}
(*rdy_time)++;
mdelay(1);
}
*mdrt_adc = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_MDRT);
return 0;
}
static int mdrt_kthread(void *x)
{
unsigned int polling_cnt;
unsigned int trig_prd;
unsigned int rdy_time;
unsigned int temp_mdrt_adc;
/* Run on a process content */
while (1) {
mutex_lock(&mdrt_mutex);
polling_cnt = 0;
temp_mdrt_adc = pmic_get_register_value(
PMIC_AUXADC_ADC_OUT_MDRT);
while (mdrt_adc == temp_mdrt_adc) {
trig_prd = 0;
rdy_time = 0;
mdrt_polling_rdy(&trig_prd,
&rdy_time, &temp_mdrt_adc);
if (polling_cnt % 20 == 0) {
pr_notice("[MDRT_ADC] trig_prd=%d, rdy_time=%d, MDRT_OUT=%d\n"
, trig_prd, rdy_time,
temp_mdrt_adc);
}
if (polling_cnt == 156) { /* 156 * 32ms ~= 5s*/
pr_notice("[MDRT_ADC] (%d) reset AUXADC\n",
polling_cnt);
wk_auxadc_reset();
}
if (polling_cnt >= 312) { /* 312 * 32ms ~= 10s*/
mdrt_reg_dump();
#ifdef CONFIG_MTK_AEE_FEATURE
aee_kernel_warning("PMIC AUXADC:MDRT", "MDRT");
#endif
break;
}
polling_cnt++;
}
mutex_unlock(&mdrt_mutex);
__pm_relax(mdrt_wakelock);
set_current_state(TASK_INTERRUPTIBLE);
schedule();
/* Fix Cove.Scan, should not happened */
if (polling_cnt >= 0x1000)
break;
}
return 0;
}
static void mdrt_monitor_init(void)
{
//wakeup_source_init(&mdrt_wakelock, "MDRT Monitor wakelock");
mdrt_wakelock = wakeup_source_register(NULL, "MDRT Monitor wakelock");
mutex_init(&mdrt_mutex);
mdrt_adc = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_MDRT);
mdrt_thread_handle = kthread_run(mdrt_kthread, NULL, "mdrt_thread");
if (IS_ERR(mdrt_thread_handle)) {
mdrt_thread_handle = NULL;
pr_notice(PMICTAG "[%s] creation fails\n", __func__);
} else
HKLOG("[%s] creation Done\n", __func__);
}
/*********************************
* Legacy API for getting PMIC AUXADC value
*********************************/
struct legacy_auxadc_t {
const char *channel_name;
struct iio_channel *chan;
};
#define LEGACY_AUXADC_GEN(_name) \
{ \
.channel_name = "AUXADC_"#_name,\
}
static struct legacy_auxadc_t legacy_auxadc[] = {
LEGACY_AUXADC_GEN(BATADC),
LEGACY_AUXADC_GEN(VCDT),
LEGACY_AUXADC_GEN(BAT_TEMP),
LEGACY_AUXADC_GEN(VBIF),
LEGACY_AUXADC_GEN(CHIP_TEMP),
LEGACY_AUXADC_GEN(DCXO_TEMP),
LEGACY_AUXADC_GEN(ACCDET),
LEGACY_AUXADC_GEN(TSX_TEMP),
LEGACY_AUXADC_GEN(HPOFS_CAL),
LEGACY_AUXADC_GEN(VCORE_TEMP),
LEGACY_AUXADC_GEN(VPROC_TEMP),
LEGACY_AUXADC_GEN(VGPU_TEMP),
LEGACY_AUXADC_GEN(VDCXO),
};
static void legacy_auxadc_init(struct device *dev)
{
int i = 0;
for (i = AUXADC_LIST_START; i <= AUXADC_LIST_END; i++) {
legacy_auxadc[i].chan =
devm_iio_channel_get(dev,
legacy_auxadc[i].channel_name);
if (IS_ERR(legacy_auxadc[i].chan))
pr_notice("%s get fail with list %d, dev_name:%s\n",
legacy_auxadc[i].channel_name, i,
dev_name(dev));
}
}
int pmic_get_auxadc_value(int list)
{
int bat_cur = 0, is_charging = 0;
int value = 0, ret = 0;
if (list < AUXADC_LIST_START || list > AUXADC_LIST_END) {
pr_notice("[%s] Invalid channel list(%d)\n", __func__, list);
return -EINVAL;
}
if (!(legacy_auxadc[list].chan) || IS_ERR(legacy_auxadc[list].chan)) {
pr_notice("[%s] iio channel consumer error(%s)\n",
__func__, legacy_auxadc[list].channel_name);
return PTR_ERR(legacy_auxadc[list].chan);
}
if (list == AUXADC_LIST_BATTEMP) {
#if (CONFIG_MTK_GAUGE_VERSION == 30)
is_charging = gauge_get_current(&bat_cur);
#endif
if (is_charging == 0)
bat_cur = 0 - bat_cur;
pr_notice("[CH3_DBG] bat_cur = %d\n", bat_cur);
}
if (list == AUXADC_LIST_HPOFS_CAL) {
ret = iio_read_channel_raw(
legacy_auxadc[list].chan, &value);
} else {
ret = iio_read_channel_processed(
legacy_auxadc[list].chan, &value);
}
if (ret < 0)
return ret;
return value;
}
/*********************************
* PMIC AUXADC chip setting for IIO ADC driver
*********************************/
static void auxadc_batadc_convert(unsigned char convert)
{
/* when user wants to get BATADC, starting monitor MDRT for debugging*/
if (convert == 0)
mdrt_monitor();
}
static void auxadc_bat_temp_convert(unsigned char convert)
{
if (convert == 1)
mutex_lock(&auxadc_ch3_mutex);
else if (convert == 0)
mutex_unlock(&auxadc_ch3_mutex);
}
static void auxadc_vdcxo_convert(unsigned char convert)
{
/* Turn on CH6 measured switch, set AUXADC_ANA_CON0[7] = 1b1 */
if (convert == 1)
pmic_config_interface(MT6358_AUXADC_ANA_CON0, 0x1, 0x1, 7);
else if (convert == 0)
pmic_config_interface(MT6358_AUXADC_ANA_CON0, 0x0, 0x1, 7);
}
static void auxadc_vbif_convert(unsigned char convert)
{
if (convert == 1)
pmic_set_hk_reg_value(PMIC_RG_BATON_TDET_EN, 0);
else if (convert == 0)
pmic_set_hk_reg_value(PMIC_RG_BATON_TDET_EN, 1);
}
static int auxadc_bat_temp_cali(int bat_temp, int precision_factor)
{
static int bat_temp_prev;
static unsigned int dbg_count;
static unsigned int aee_count;
if (bat_temp == -1 && precision_factor == -1) {
bat_temp_prev = 0;
return 0;
}
if (bat_temp_prev == 0)
goto out;
dbg_count++;
if (bat_temp < 200 || abs(bat_temp_prev - bat_temp) > 100) {
/* dump debug log when BAT_TEMP being abnormal */
bat_temp = wk_bat_temp_dbg(bat_temp_prev, bat_temp);
#if BAT_TEMP_AEE_DBG
#ifdef CONFIG_MTK_AEE_FEATURE
if (aee_count < 2)
aee_kernel_warning("PMIC AUXADC:BAT_TEMP", "BAT_TEMP");
#endif
pr_notice("PMIC AUXADC BAT_TEMP aee_count=%d\n", aee_count);
#endif
aee_count++;
} else if (dbg_count % 50 == 0) {
/* dump debug log in normal case */
wk_bat_temp_dbg(bat_temp_prev, bat_temp);
}
out:
bat_temp_prev = bat_temp;
return bat_temp;
}
static void parsing_cust_setting(void)
{
struct device_node *np;
unsigned int disable_modem;
/* check customer setting */
np = of_find_compatible_node(NULL, NULL,
"mediatek,mt-pmic-custom-setting");
if (!np) {
HKLOG("[%s]Failed to find device-tree node\n", __func__);
return;
}
if (!of_property_read_u32(np, "disable-modem", &disable_modem)) {
if (disable_modem)
mts_enable = false;
}
of_node_put(np);
}
int pmic_auxadc_chip_init(struct device *dev)
{
int ret = 0;
struct iio_channel *chan_vbif;
HKLOG("%s\n", __func__);
pmic_auxadc_dev = dev;
auxadc_set_convert_fn(AUXADC_BATADC, auxadc_batadc_convert);
auxadc_set_convert_fn(AUXADC_BAT_TEMP, auxadc_bat_temp_convert);
auxadc_set_convert_fn(AUXADC_VDCXO, auxadc_vdcxo_convert);
auxadc_set_convert_fn(AUXADC_VBIF, auxadc_vbif_convert);
auxadc_set_cali_fn(AUXADC_BATADC, wk_vbat_cali);
auxadc_set_cali_fn(AUXADC_BAT_TEMP, auxadc_bat_temp_cali);
#if 1 /*TBD*/
legacy_auxadc_init(dev);
#endif
auxadc_cali_init(dev->of_node);
wk_auxadc_dbg_init();
parsing_cust_setting();
if (mts_enable)
mdrt_monitor_init();
/* update VBIF28 by AUXADC */
chan_vbif = iio_channel_get(dev, "AUXADC_VBIF");
if (IS_ERR(chan_vbif)) {
pr_notice("[%s] iio channel consumer error(AUXADC_VBIF)\n",
__func__);
} else {
ret = iio_read_channel_processed(chan_vbif,
&g_pmic_pad_vbif28_vol);
iio_channel_release(chan_vbif);
}
pr_info("****[%s] VBIF28 = %d, MDRT_ADC = 0x%x\n",
__func__, pmic_get_vbif28_volt(), mdrt_adc);
return ret;
}