NTC(电池温度检测)

https://blog.csdn.net/mcgrady_tracy/article/details/52818100

NTC 那是當作電池的溫度偵測用, 通常 NTC 是要包裝在電池內部。但是有些電池沒有 NTC,所以就需要外掛 NTC 放置於電池附近去偵測電池溫度。

如果直接使用外部電源而且沒有充電功能,基本上 NTC 是可以拿掉。(但是軟件人員要會改 MTK 的程序代碼,否則會開不機或是其他問題出現)

手机里面电池通常有4个引脚,即电池的+、-极,ID引脚、NTC引脚。

ID引脚用来识别电池的类型,例如是锂电池还是镍氢电池,不过现在手机上基本用的都是锂电池了。

NTC引脚主要用来测量电池温度的,还可以用来检测手机有没有接上电池

PL启动流程:

main

struct bldr_command_handler handler;

->bldr_pre_process  //main.c

 ->platform_pre_init  //platform.c

  ->mtk_timer_init();  //timer.c

  ->mt_pll_init();  //pll.c

  ->mtk_uart_init(UART_SRC_CLK_FRQ, CFG_LOG_BAUDRATE);  //uart.c  CFG_LOG_BAUDRATE :=921600 in default.mak

  ->mt_gpio_init();  //gpio.c

  ->i2c_hw_init();  //i2c.c

  ->pmic_init  //pmic.c、pmic_mt6392.c

   ->pmic_DetectVbatDrop();

    ->U32 just_rst=0;

    ->pmic_read_interface( MT6350_PMIC_JUST_PWRKEY_RST_ADDR, (&just_rst), MT6350_PMIC_JUST_PWRKEY_RST_MASK, MT6350_PMIC_JUST_PWRKEY_RST_SHIFT );

    ->pmic_config_interface(MT6350_PMIC_CLR_JUST_RST_ADDR, 1, MT6350_PMIC_CLR_JUST_RST_MASK, MT6350_PMIC_CLR_JUST_RST_SHIFT);
    ->if(just_rst)           //用这个来判断是normal,还是force reset
     vbat_status = PMIC_VBAT_DROP;  //force reset
    ->else
     vbat_status = PMIC_VBAT_NOT_DROP;  //normal

->hw_check_battery  //pmic.c  mt8321 only

->FCHR_ENB init  //add for FCHR mt8321 only

 ->g_boot_mode = NORMAL_BOOT;  //初始值

 ->platform_init

  ->rtc_init();    //rtc.c  mt8168 only

  ->pmic_init_setting();  //pmic_initial_setting.c  mt8168 only

  ->pl_battery_init(false);  //battery.c  mt8168 only

   ->fuel_gauge_init();     //battery.c  mt8168 only

    ->if (hw_check_battery() == 1)  //charging_bat.c  mt8168 only  battery exists

    ->pl_check_bat_protect_status()  //charging_bat.c  mt8168 only

      ->while (bat_val < BATTERY_LOWVOL_THRESOLD)  //charging_bat.c  mt8168 only  #define BATTERY_LOWVOL_THRESOLD 3300

       ->pchr_turn_on_charging(KAL_TRUE);      //charging_bat.c  mt8168 only  PL充电

  ->mtk_wdt_init();  //wdt.c  init watch dog, will enable AP watch dog

   ->Dump RGU regisers

   ->mtk_wdt_check_trig_reboot_reason();

    ->mtk_wdt_boot_check();  //wdt.c  check bypass power key info

  ->set_kpd_pmic_mode();  //mtk_key.c  init kpd PMIC mode support

  ->g_boot_reason = reason = platform_boot_status()  //platform.c

   ->rtc_boot_check()  //rtc.c  start of platform_boot_status()

    ->#if RTC_2SEC_REBOOT_ENABLE

      ->rtc_save_2sec_stat();  //rtc.c

       ->rtc_2sec_stat_clear();  //rtc.c

       ->g_rtc_2sec_stat = false/true;

    ->#endif

   ->if ... return BR_RTC/BR_WDT/BR_WDT_BY_PASS_PWK

   ->if (mtk_detect_key(PL_PMIC_PWR_KEY) && hw_check_battery())  //keypad.c & pmic.c(8321)、pmic_mt6392.c(8167)  8168:if (mtk_detect_key(PL_PMIC_PWR_KEY)) {

    ->rtc_mark_bypass_pwrkey();  //rtc.c

    ->return BR_POWER_KEY;

   ->if (usb_accessory_in())  //platform.c

    ->if (PMIC_CHRDET_EXIST == pmic_IsUsbCableIn())  //start of usb_accessory_in()

      ->pmic_read_interface( (U32)(PMIC_RGS_CHRDET_ADDR), (&val), (U32)(PMIC_RGS_CHRDET_MASK), (U32)(PMIC_RGS_CHRDET_SHIFT)  //pmic_IsUsbCableIn()相当于upmu_is_chr_det()

     ->exist = 1;

     #if !CFG_USBIF_COMPLIANCE

      ->platform_set_chrg_cur(450);  //platform.c  enable charging current as early as possible to avoid can't enter following battery charging flow when low battery

       ->hw_set_cc(ma);  //pmic.c、pmic_6392.c、charging_bat.c

     #endif

     ->return exist;  //end of usb_accessory_in()

    ->return BR_USB  //USB/charger boot

   ->if (rtc_2sec_reboot_check())  //rtc.c

    #if RTC_2SEC_REBOOT_ENABLE

            return g_rtc_2sec_stat;

    #else

            return false;

    #endif

    ->return BR_2SEC_REBOOT;

   ->pl_power_off();  //rtc.c  Unknown boot  如果前面都没return,那么将跑到这里,强制关机

    ->rtc_bbpu_power_down()  //rtc.c  end of platform_boot_status()

  ->if (reason == BR_RTC || reason == BR_POWER_KEY || reason == BR_USB || reason == BR_WDT || reason ==BR_WDT_BY_PASS_PWK || reason == BR_2SEC_REBOOT)  //mt8321 only 

    ->rtc_bbpu_power_on();  //rtc.c  mt8321 mt8167 mt8168

  ->mt_mem_init();  //memory.c  init memory

   ->mt_set_emi      //emi.c
  ->init_dram_buffer();

  ->ram_console_init();

  ->ram_console_reboot_reason_save(g_rgu_status);

  ->boot_device_init();  //platform.c  init device storage  end of platform_init()

->bldr_handshake(&handler);

 ->#ifdef MTK_SECURITY_SW_SUPPORT

  ->mode = seclib_brom_meta_mode();  //get mode type  找不到定义,不开源

  ->isSBC = seclib_sbc_enabled();    //找不到定义,不开源

 ->#endif

 ->switch (mode) { case NORMAL_BOOT:

  ->#if CFG_USB_TOOL_HANDSHAKE  //yes

   ->if (TRUE == usb_handshake(handler))  //handshake_usb.c  //这里可以设置force_download

    ->uint32 enum_tmo = CFG_USB_ENUM_TIMEOUT_EN ? USB_ENUM_TIMEOUT : 0;  //start of usb_handshake()

    ->if (usb_connect(enum_tmo) == FALSE) {  //handshake_usb.c

     ->if (enum_tmo) {  //start of usb_connect()

      ->ulong start_time = get_timer(0);

      ->if (get_timer(start_time) > i * 1000) {  //cable plugged-out and power key detection each 1 second

       ->if (!usb_accessory_in() && !pmic_detect_powerkey())  //如果USB没有插入,并且也不是power key press,强制关机

        ->pl_power_off();  //end of usb_connect()  /* ret = pmic_read_interface((U32)(PMIC_PWRKEY_DEB_ADDR), (&val), (U32)(PMIC_PWRKEY_DEB_MASK), (U32)(PMIC_PWRKEY_DEB_SHIFT)); */

     ->print("%s USB enum timeout!\n", MOD); goto end;  //end of usb_handshake()

    ->g_meta_com_type = META_USB_COM;

  ->#endif

 ->case META_BOOT/FACTORY_BOOT/FACTORY_BOOT/ADVMETA_BOOT/ATE_FACTORY_BOOT:

  ->if(!usb_cable_in())

   ->if ((g_boot_reason == BR_USB) || usb_accessory_in()) {  //start of usb_cable_in()

    ->ret = mt_charger_type_detection();

    ->if (ret == STANDARD_HOST || ret == CHARGING_HOST) {

     ->mt_usb_phy_poweron();

     ->mt_usb_phy_savecurrent();

     ->exist = 1;

    ->} else if (ret == NONSTANDARD_CHARGER || ret == STANDARD_CHARGER) {

      ->#if CFG_USBIF_COMPLIANCE  //not defined

       ->platform_set_chrg_cur(450);

      ->#endif

    ->return exist;  //end of usb_cable_in()

//end of bldr_handshake()

->bldr_post_process

 ->platform_post_init

  ->#if CFG_BATTERY_DETECT  //这个似乎没有定义

   ->if (g_boot_mode == NORMAL_BOOT && !hw_check_battery() && usb_accessory_in()) {

    ->pl_close_pre_chr_led();  //pmic.c、pmic_mt6392.c、charging_bat.c  disable pmic pre-charging led

    ->pl_charging(1);  //pmic.c、pmic_mt6392.c、charging_bat.c  enable force charging mode

    ->do { mdelay(300); if (hw_check_battery()){break;}platform_wdt_all_kick();} while(1);  //check battery exists or not & kick all watchdogs

    ->pl_charging(0);  //end of platform_post_init()

  ->#endif

 /vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt8167/src/drivers/inc/upmu_hw.h 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

#define MT6392_PMIC_REG_BASE (0x0000)
#define MT6392_CHR_CON0                         ((UINT32)(MT6392_PMIC_REG_BASE+0x0000))
#define MT6392_CHR_CON3                         ((UINT32)(MT6392_PMIC_REG_BASE+0x0006))
#define MT6392_CHR_CON4                         ((UINT32)(MT6392_PMIC_REG_BASE+0x0008))
#define MT6392_CHR_CON7                         ((UINT32)(MT6392_PMIC_REG_BASE+0x000E))

#define MT6392_PMIC_RG_CHR_EN_ADDR                                       MT6392_CHR_CON0    //充电使能脚,还需配合其它寄存器使用
#define MT6392_PMIC_RG_CHR_EN_MASK                                       0x1
#define MT6392_PMIC_RG_CHR_EN_SHIFT                                      4
#define MT6392_PMIC_RGS_CHRDET_ADDR                                      MT6392_CHR_CON0    //充电器检测脚
#define MT6392_PMIC_RGS_CHRDET_MASK                                      0x1
#define MT6392_PMIC_RGS_CHRDET_SHIFT                                     5

#define MT6392_PMIC_RG_VBAT_CV_VTH_ADDR                                  MT6392_CHR_CON3    //恒压充电电压
#define MT6392_PMIC_RG_VBAT_CV_VTH_MASK                                  0x1F
#define MT6392_PMIC_RG_VBAT_CV_VTH_SHIFT                                 0

#define MT6392_PMIC_RG_CS_VTH_ADDR                                       MT6392_CHR_CON4    //充电电流
#define MT6392_PMIC_RG_CS_VTH_MASK                                       0xF
#define MT6392_PMIC_RG_CS_VTH_SHIFT                                      0

#define MT6392_PMIC_RG_BATON_EN_ADDR                                     MT6392_CHR_CON7    //电池检测总开关
#define MT6392_PMIC_RG_BATON_EN_MASK                                     0x1
#define MT6392_PMIC_RG_BATON_EN_SHIFT                                    0
#define MT6392_PMIC_RG_BATON_HT_EN_ADDR                                  MT6392_CHR_CON7    //HW高温检测开关
#define MT6392_PMIC_RG_BATON_HT_EN_MASK                                  0x1
#define MT6392_PMIC_RG_BATON_HT_EN_SHIFT                                 1
#define MT6392_PMIC_BATON_TDET_EN_ADDR                                   MT6392_CHR_CON7    //温度检测开关,应该是打开了这个,BATON ADC才生效
#define MT6392_PMIC_BATON_TDET_EN_MASK                                   0x1
#define MT6392_PMIC_BATON_TDET_EN_SHIFT                                  2
#define MT6392_PMIC_RG_BATON_HT_TRIM_ADDR                                MT6392_CHR_CON7
#define MT6392_PMIC_RG_BATON_HT_TRIM_MASK                                0x7
#define MT6392_PMIC_RG_BATON_HT_TRIM_SHIFT                               4
#define MT6392_PMIC_RG_BATON_HT_TRIM_SET_ADDR                            MT6392_CHR_CON7
#define MT6392_PMIC_RG_BATON_HT_TRIM_SET_MASK                            0x1
#define MT6392_PMIC_RG_BATON_HT_TRIM_SET_SHIFT                           7
#define MT6392_PMIC_RGS_BATON_UNDET_ADDR                                 MT6392_CHR_CON7    //电池检测,0:存在,1:不存在
#define MT6392_PMIC_RGS_BATON_UNDET_MASK                                 0x1
#define MT6392_PMIC_RGS_BATON_UNDET_SHIFT                                12

1.电池检测

电池的NTC引脚需要接到MT6350的BATON引脚上,preloader中的检测代码如下:

 /vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6580/src/drivers/pmic.c 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

int hw_check_battery(void)
{
#ifndef MTK_DISABLE_POWER_ON_OFF_VOLTAGE_LIMITATION
    U32 ret_val;
    U32 reg_val=0;

    ret_val=pmic_config_interface(MT6350_CHR_CON7,0x01, MT6350_PMIC_RG_BATON_EN_MASK, MT6350_PMIC_RG_BATON_EN_SHIFT);      //BATON_EN=1
    ret_val=pmic_config_interface(MT6350_CHR_CON7,    0x01, MT6350_PMIC_BATON_TDET_EN_MASK, MT6350_PMIC_BATON_TDET_EN_SHIFT);  //BATON_TDET_EN=1
    ret_val=pmic_read_interface(MT6350_CHR_CON7,®_val, MT6350_PMIC_RGS_BATON_UNDET_MASK, MT6350_PMIC_RGS_BATON_UNDET_SHIFT);  //电池检测,0:存在,1:不存在

    if (reg_val == 1)
    {
        print("No Battery\n");

        ret_val=pmic_read_interface(MT6350_CHR_CON7,®_val,0xFFFF,0x0);
        print("[0x%x]=0x%x\n",MT6350_CHR_CON7,reg_val);

        return 0;
    }
    else
    {
        print("Battery exist\n");

        ret_val=pmic_read_interface(MT6350_CHR_CON7,®_val,0xFF,0x0);
        print("[0x%x]=0x%x\n",MT6350_CHR_CON7,reg_val);

        pl_hw_ulc_det();

        return 1;
    }
#else
    return 1;
#endif
}

如果需要去掉电池检测,则在preloader和ProjectConfig配置:MTK_DISABLE_POWER_ON_OFF_VOLTAGE_LIMITATION = yes

KernelConfig配置:CONFIG_MTK_DISABLE_POWER_ON_OFF_VOLTAGE_LIMITATION=y

2.电池温度检测

电池的温度也是通过NTC引脚来测量的,如果去掉电池检测,那么温度检测也会去掉

温度检测的等效电路如下:

其中10k(25℃)是一个温敏电阻,随着温度的升高,阻值降低,一般电池厂商会提供一个温度与阻值的曲线图,通过测量baton的电压值计算出阻值,然后根据阻值曲线计算出温度值,这就是温度测量的原理。

NTC阻值曲线如下(tb8321p2_bsp_bat_setting.dtsi/mt_battery_meter_table.h):

上拉参考电压为PMIC TREF提供的1.8v,通过计算可以得到在25℃(即10Khm)下,baton电压值大概为0.669v

 /kernel-4.9-lc/drivers/misc/mediatek/include/mt-plat/mt6580/include/mach/mt_battery_meter_table.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#define BAT_NTC_10 1
#define BAT_NTC_47 0

#if (BAT_NTC_10 == 1)
#define RBAT_PULL_UP_R  16900
#define RBAT_PULL_DOWN_R    27000
#endif

#if (BAT_NTC_47 == 1)
#define RBAT_PULL_UP_R  61900
#define RBAT_PULL_DOWN_R    100000
#endif
#define RBAT_PULL_UP_VOLT   1800

#if (BAT_NTC_10 == 1)
    BATT_TEMPERATURE Batt_Temperature_Table[] = {
        {-20, 68237},
        {-15, 53650},
        {-10, 42506},
        { -5, 33892},
        {  0, 27219},
        {  5, 22021},
        { 10, 17926},
        { 15, 14674},
        { 20, 12081},
        { 25, 10000},
        { 30, 8315},
        { 35, 6948},
        { 40, 5834},
        { 45, 4917},
        { 50, 4161},
        { 55, 3535},
        { 60, 3014}
};
#endif

#if (BAT_NTC_47 == 1)
    BATT_TEMPERATURE Batt_Temperature_Table[] = {
        {-20, 483954},
        {-15, 360850},
        {-10, 271697},
        { -5, 206463},
        {  0, 158214},
        {  5, 122259},
        { 10, 95227},
        { 15, 74730},
        { 20, 59065},
        { 25, 47000},
        { 30, 37643},
        { 35, 30334},
        { 40, 24591},
        { 45, 20048},
        { 50, 16433},
        { 55, 13539},
        { 60, 11210}
    };
#endif

我们来看一下代码:

如果是使用dts,那么需要重新获取NTC温度与阻值关系,否则直接使用.h默认值

battery_probe->batt_meter_init_cust_data->__batt_meter_init_cust_data_from_dt

 /kernel-4.9-lc/drivers/misc/mediatek/include/mt-plat/battery_meter.h

1
2
3
4

typedef struct {
    signed int BatteryTemp;
    signed int TemperatureR;
} BATT_TEMPERATURE;

 /kernel-4.9-lc/drivers/power/supply/mediatek/battery_meter.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

int __batt_meter_init_cust_data_from_dt(void)
{
#if (BAT_NTC_10 == 1)
        batt_meter_cust_data.bat_ntc = 10;
#elif (BAT_NTC_47 == 1)
        batt_meter_cust_data.bat_ntc = 47;
#endif

#if defined(RBAT_PULL_UP_R)     
        batt_meter_cust_data.rbat_pull_up_r = RBAT_PULL_UP_R;
#endif
#if defined(RBAT_PULL_UP_VOLT)
        batt_meter_cust_data.rbat_pull_up_volt = RBAT_PULL_UP_VOLT;
#endif
...
    __batt_meter_parse_node(np, "batt_temperature_table_num", &num);

    idx = 0;
    while (!of_property_read_u32_index(np, "batt_temperature_table", idx, &addr)) {
        idx++;
        if (!of_property_read_u32_index(np, "batt_temperature_table", idx, &val)) {
            battery_log(BAT_LOG_CRTI, "batt_temperature_table: addr: %d, val: %d\n",
                    addr, val);
        }
        Batt_Temperature_Table[idx / 2].BatteryTemp = addr;
        Batt_Temperature_Table[idx / 2].TemperatureR = val;

        idx++;
        if (idx >= num * 2)
            break;
    }
...
}

获取电池温度函数如下:

battery_meter_get_battery_temperature

 ->force_get_tbat(KAL_TRUE)

  ->battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP, &bat_temperature_volt) //获取ADC电压

  ->BattVoltToTemp(bat_temperature_volt)

   ->...    //根据串并联电阻分压,计算得到热敏电阻阻值TRes

   ->sBaTTMP = BattThermistorConverTemp((int)TRes)  //查表,根据阻值换算温度

 /kernel-4.9-lc/drivers/power/supply/mediatek/battery_meter.c 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

signed int battery_meter_get_battery_temperature(void)
{
#ifdef MTK_BATTERY_LIFETIME_DATA_SUPPORT  //NO
    signed int batt_temp = force_get_tbat(KAL_TRUE);

    if (batt_temp > gFG_max_temperature)
        gFG_max_temperature = batt_temp;
    if (batt_temp < gFG_min_temperature)
        gFG_min_temperature = batt_temp;

    return batt_temp;
#else
    return force_get_tbat(KAL_TRUE);
#endif
}

 /kernel-4.9-lc/drivers/power/supply/mediatek/battery_meter.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

int force_get_tbat(kal_bool update)
{
#if defined(CONFIG_POWER_EXT) || defined(FIXED_TBAT_25)
    bm_print(BM_LOG_CRTI, "[force_get_tbat] fixed TBAT=25 t\n");
    return 25;
#else
    int bat_temperature_volt = 0;
    int bat_temperature_val = 0;
    static int pre_bat_temperature_val = -1;
    int fg_r_value = 0;
    signed int fg_current_temp = 0;
    kal_bool fg_current_state = KAL_FALSE;
    int bat_temperature_volt_temp = 0;
    int ret = 0;

    if (batt_meter_cust_data.fixed_tbat_25) {
        bm_print(BM_LOG_CRTI, "[force_get_tbat] fixed TBAT=25 t\n");
        return 25;
    }

    if (update == KAL_TRUE || pre_bat_temperature_val == -1) {
        /* Get V_BAT_Temperature */
        bat_temperature_volt = 2;
        ret =                       /* 获取BATON的adc电压 */
            battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP, &bat_temperature_volt);

        if (bat_temperature_volt != 0) {
#if defined(SOC_BY_HW_FG)  //NO
            fg_r_value = get_r_fg_value();

            ret =
                battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT,
                           &fg_current_temp);
            ret =
                battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT_SIGN,
                           &fg_current_state);
            fg_current_temp = fg_current_temp / 10;

            if (fg_current_state == KAL_TRUE) {
                bat_temperature_volt_temp = bat_temperature_volt;
                bat_temperature_volt =
                    bat_temperature_volt - ((fg_current_temp * fg_r_value) / 1000);
            } else {
                bat_temperature_volt_temp = bat_temperature_volt;
                bat_temperature_volt =
                    bat_temperature_volt + ((fg_current_temp * fg_r_value) / 1000);
            }
#endif

            bat_temperature_val = BattVoltToTemp(bat_temperature_volt);
        }
#ifdef CONFIG_MTK_BIF_SUPPORT
        battery_charging_control(CHARGING_CMD_GET_BIF_TBAT, &bat_temperature_val);
#endif
        bm_print(BM_LOG_CRTI, "[force_get_tbat] %d,%d,%d,%d,%d,%d\n",
             bat_temperature_volt_temp, bat_temperature_volt, fg_current_state,
             fg_current_temp, fg_r_value, bat_temperature_val);
        pre_bat_temperature_val = bat_temperature_val;

        if (bat_temperature_val > 55)
            pr_notice("[force_get_tbat] %d,%d,%d,%d,%d,%d\n",
             bat_temperature_volt_temp, bat_temperature_volt, fg_current_state,
             fg_current_temp, fg_r_value, bat_temperature_val);

    } else {
        bat_temperature_val = pre_bat_temperature_val;
    }
    return bat_temperature_val;
#endif
}
EXPORT_SYMBOL(force_get_tbat);

 /kernel-4.9-lc/drivers/misc/mediatek/power/mt6580/battery_meter_hal.c 

1
2
3
4

signed int bm_ctrl_cmd(BATTERY_METER_CTRL_CMD cmd, void *data)
    bm_func[BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP] = read_adc_v_bat_temp
    ... ...
}

 /kernel-4.9-lc/drivers/misc/mediatek/include/mt-plat/mt6580/include/mach/upmu_sw.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

/* ADC Channel Number */
typedef enum {
    /* MT6350 */

    MT6350_AUX_BATON2 = 0x000,
    MT6350_AUX_CH6,
    MT6350_AUX_THR_SENSE2,
    MT6350_AUX_THR_SENSE1,
    MT6350_AUX_VCDT,
    MT6350_AUX_BATON1,
    MT6350_AUX_ISENSE,
    MT6350_AUX_BATSNS,
    MT6350_AUX_ACCDET,
    MT6350_AUX_CH9,
    MT6350_AUX_CH10,
    MT6350_AUX_CH11,
    MT6350_AUX_CH12,
    MT6350_AUX_CH13,
    MT6350_AUX_CH14,
    MT6350_AUX_CH15,
    MT6350_AUX_CH16,
} pmic_adc_ch_list_enum;

 /kernel-4.9-lc/drivers/misc/mediatek/power/mt6580/battery_meter_hal.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

static signed int read_adc_v_bat_temp(void *data)
{
#if defined(CONFIG_POWER_EXT)
    *(signed int *)(data) = 0;
#else
#if defined(MTK_PCB_TBAT_FEATURE)  //no

    int ret = 0, data[4], i, ret_value = 0, ret_temp = 0;
    int Channel = 1;

    if (IMM_IsAdcInitReady() == 0) {
        bm_print(BM_LOG_CRTI, "[get_tbat_volt] AUXADC is not ready");
        return 0;
    }

    i = times;
    while (i--) {
        ret_value = IMM_GetOneChannelValue(Channel, data, &ret_temp);
        ret += ret_temp;
        bm_print(BM_LOG_FULL, "[get_tbat_volt] ret_temp=%d\n", ret_temp);
    }

    ret = ret * 1500 / 4096;
    ret = ret / times;
    bm_print(BM_LOG_CRTI, "[get_tbat_volt] Battery output mV = %d\n", ret);

    *(signed int *)(data) = ret;

#else
    bm_print(BM_LOG_FULL,
         "[read_adc_v_charger] return PMIC_IMM_GetOneChannelValue(4,times,1);\n");
    *(signed int *)(data) =
        PMIC_IMM_GetOneChannelValue(MT6350_AUX_BATON1, *(signed int *)(data), 1);  //参数data没用到,返回值才是ADC电压
#endif
#endif

    return STATUS_OK;
}

PS:PL和LK阶段获取ADC也是int PMIC_IMM_GetOneChannelValue(int dwChannel, int deCount, int trimd)

KERNEL的参数deCount没有任何作用,但PL和LK的参数deCount为获取的次数,比如deCount为5,那就是连续获取5次,最后返回5次的平均值

另外,对于其他平台(比如MT8768/MT8788)

KERNEL用int iio_read_channel_processed(struct iio_channel *chan, int *val)

PL和LK是使用int pmic_get_auxadc_value(PMIC_AUXADC_LIST list)

获取到ADC电压后,然后调用BattVoltToTemp,得到RNTC的阻值

 /kernel-4.9-lc/drivers/power/supply/mediatek/battery_meter.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

int BattVoltToTemp(int dwVolt)
{
    long long TRes_temp;
    long long TRes;
    int sBaTTMP = -100;
    
    /* 根据串联分压,计算下半部分电阻阻值TRes_temp*/
    /* TRes_temp = ((long long)RBAT_PULL_UP_R*(long long)dwVolt) / (RBAT_PULL_UP_VOLT-dwVolt); */
    
    /* 如果下半部分只有一个电阻,那么TRes_temp就是热敏电阻阻值 */
    /* 如果热敏电阻并联了一个下拉电阻,那么通过计算得到热敏电阻阻值TRes */
    /* TRes = (TRes_temp * (long long)RBAT_PULL_DOWN_R)/((long long)RBAT_PULL_DOWN_R - TRes_temp); */

    TRes_temp = (batt_meter_cust_data.rbat_pull_up_r * (long long) dwVolt);

#if defined(__LP64__) || defined(_LP64)
    do_div(TRes_temp, (batt_meter_cust_data.rbat_pull_up_volt - dwVolt));
#else
    TRes_temp = div_s64(TRes_temp, (batt_meter_cust_data.rbat_pull_up_volt - dwVolt));
#endif

#ifdef RBAT_PULL_DOWN_R
    TRes = (TRes_temp * RBAT_PULL_DOWN_R);
#if defined(__LP64__) || defined(_LP64)
    do_div(TRes, abs(RBAT_PULL_DOWN_R - TRes_temp));
#else
    TRes = div_s64(TRes, abs(RBAT_PULL_DOWN_R - TRes_temp));
#endif
#else
    TRes = TRes_temp;
#endif

    /* convert register to temperature */
    sBaTTMP = BattThermistorConverTemp((int)TRes);

    return sBaTTMP;
}

TRes为计算得到的阻值,然后通过BattThermistorConverTemp,转换为对应温度:

 /kernel-4.9-lc/drivers/power/supply/mediatek/battery_meter.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

int BattThermistorConverTemp(int Res)
{
    int i = 0;
    int RES1 = 0, RES2 = 0;
    int TBatt_Value = -200, TMP1 = 0, TMP2 = 0;

    if (Res >= Batt_Temperature_Table[0].TemperatureR) {
        TBatt_Value = -20;
    } else if (Res <= Batt_Temperature_Table[16].TemperatureR) {
        TBatt_Value = 60;
    } else {
        RES1 = Batt_Temperature_Table[0].TemperatureR;
        TMP1 = Batt_Temperature_Table[0].BatteryTemp;

        for (i = 0; i <= 16; i++) {
            if (Res <  Batt_Temperature_Table[i].TemperatureR) {
                RES1 = Batt_Temperature_Table[i].TemperatureR;  //RES1是比Res大,且Batt_Temperature_Table数组里最接近Res的阻值
                TMP1 = Batt_Temperature_Table[i].BatteryTemp;

            } else {
                RES2 = Batt_Temperature_Table[i].TemperatureR;  //RES2是比Res小,且Batt_Temperature_Table数组里最接近Res的阻值
                TMP2 = Batt_Temperature_Table[i].BatteryTemp;
                break;
            }
        }
        /* 也就是说 RES1>Res>Res2, 通过计算得到Res对应的温度TBatt_Value */
        TBatt_Value = (((Res - RES2) * TMP1) + ((RES1 - Res) * TMP2)) / (RES1 - RES2);
    }

    return TBatt_Value;
}

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值