PMIC驱动分析

 

一.初始化分析

Pmic.c (kernel-3.10\drivers\misc\mediatek\power\mt6735)
 
struct platform_device pmic_mt_device = {
    .name   = "mt-pmic",
    .id        = -1,
};
 
static struct platform_driver pmic_mt_driver = {
    .probe        = pmic_mt_probe,
    .remove       = pmic_mt_remove,
    .shutdown     = pmic_mt_shutdown,
    //#ifdef CONFIG_PM
    .suspend      = pmic_mt_suspend,
    .resume       = pmic_mt_resume,
    //#endif
    .driver       = {
        .name = "mt-pmic",
    },
};
 
pmic_mt_init
    ret = platform_device_register(&pmic_mt_device);
    ret = platform_driver_register(&pmic_mt_driver); //进入probe
    pmic_auxadc_init();//
Pmic_auxadc.c (kernel-3.10\drivers\misc\mediatek\power\mt6735)
 
 
 
 
二.probe函数
    pmic_mt_probe
        PMIC_INIT_SETTING_V1
 
            pmic_set_register_value(PMIC_WDTRSTB_STATUS_CLR,1); //
            .......一系列寄存器的初始化。。。。。
            PMIC_CUSTOM_SETTING_V1
                pmu_drv_tool_customization_init(); //DCT,也就是dct/DrvGen
            //PMIC Interrupt Service
    pmic_thread_handle = kthread_create(pmic_thread_kthread, (void *) NULL, "pmic_thread");
            wake_up_process(pmic_thread_handle); //运行这个thread,单独分析1
            PMIC_EINT_SETTING();  //中断设置,单独分析2
            mtk_regulator_init
                mtk_ldos[MT6328_POWER_LDO_VMC].pvoltages=(void *)mt6328_VMC_E1_2_voltages; //设置SD2.0/3.0  memory card用到的电压
                for (i = 0; i < ARRAY_SIZE(mtk_ldos); i++) //设置pmic输出的ldos
                    ......对每个ldo进行赋值,mtk_ldos是个数组,原型是mtk_regulator,在pmic.h中声明
                    mtk_ldos[i].rdev= regulator_register(&mtk_ldos[i].desc,&mtk_ldos[i].config); //注册regulator
                    //lookup and obtain a reference to a regulator.
                    mtk_ldos[i].reg=regulator_get(&(dev->dev), mtk_ldos[i].desc.name); 
            low_battery_protect_init(); //初始化电池电量过低保护
            battery_oc_protect_init(); //应该是电池大电流保护
            bat_percent_notify_init //电池电量通知,单独分析3
            dlpt_notify_init //动态频率调节,单独分析4
            pmic_debug_init //调试节点初始化
                proc_mkdir("mt_pmic", NULL); ///proc/mt_pmic
                proc_create("dump_ldo_status", S_IRUGO | S_IWUSR, mt_pmic_dir, &pmic_debug_proc_fops); //打印ldo
                proc_create("dump_pmic_reg", S_IRUGO | S_IWUSR, mt_pmic_dir, &pmic_dump_register_proc_fops); //打印寄存器
           pmic_ftm_init  //初始化,提供一些接口给应用,这里不太重要
                alloc_chrdev_region(&pmic_devno, 0, 1, PMIC_DEVNAME);
                pmic_cdev = cdev_alloc();
                pmic_cdev->owner = THIS_MODULE;
                pmic_cdev->ops = &pmic_ftm_fops;
                ret = cdev_add(pmic_cdev, pmic_devno, 1);
                pmic_class = class_create(THIS_MODULE, PMIC_DEVNAME);
            for (i = 0; i < ARRAY_SIZE(mtk_bucks); i++) //降压滤波,DCDC口的调试sysfs,/sys/devices/platform/mt-pmic
                ret_device_file = device_create_file(&(dev->dev),&mtk_bucks[i].en_att);
ret_device_file = device_create_file(&(dev->dev),&mtk_bucks[i].voltage_att);
            for (i = 0; i < ARRAY_SIZE(mtk_ldos); i++) //LDO的sysfs
                ret_device_file = device_create_file(&(dev->dev),&mtk_ldos[i].en_att);
ret_device_file = device_create_file(&(dev->dev),&mtk_ldos[i].voltage_att);
            device_create_file(&(dev->dev), &dev_attr_pmic_access); //读取寄存器的接口
            .........其他的一些调试接口..............
                
            
 
 
三.单独分析
1.单独分析1
static struct pmic_interrupts interrupts[] = {
PMIC_M_INTS_GEN(MT6328_INT_STATUS0,MT6328_INT_CON0,MT6328_INT_CON0_SET,MT6328_INT_CON0_CLR,interrupt_status0),
PMIC_M_INTS_GEN(MT6328_INT_STATUS1,MT6328_INT_CON1,MT6328_INT_CON1_SET,MT6328_INT_CON1_CLR,interrupt_status1),
PMIC_M_INTS_GEN(MT6328_INT_STATUS2,MT6328_INT_CON2,MT6328_INT_CON2_SET,MT6328_INT_CON2_CLR,interrupt_status2),
};
 
pmic_thread_kthread
    //sched_setscheduler()函数将pid所指定进程的调度策略和调度参数分别设置为param指向的sched_param结构中指定的policy和参数。sched_param结构中的sched_priority成员的值可以    为任何整数,该整数位于policy所指定调度策略的优先级范围内(含边界值)。policy参数的可能值在头文件中定义。
    sched_setscheduler(current, SCHED_FIFO, &param); //这里是FIFO优先级策略调度,优先级是98
    set_current_state(TASK_INTERRUPTIBLE); //可以中断的等待
    pmic_enable_charger_detection_int
        pmic_rdy=1; //赋值为1
    while (1) {
 
        pmic_wrap_eint_status //得到PMIC到AP中断脚的状态
            mt_pmic_wrap_eint_status
                WRAP_RD32(PMIC_WRAP_EINT_STA); //INT related control, this INT is for PMIC chip to AP
        pmic_int_handler //配置初始化PMIC中断
            for (i = 0; i < ARRAY_SIZE(interrupts); i++) //有3个寄存器
                interrupts[i].interrupts[j].callback(); //找到具体的中断,调用中断处理函数,这里分析插拔充电器,单独分析5
interrupts[i].interrupts[j].times++;
                ret=pmic_config_interface(interrupts[i].address,0x1,0x1,j);
        pmic_wrap_eint_clr(0x0); //清除
            mt_pmic_wrap_eint_clr
                WRAP_WR32(PMIC_WRAP_EINT_CLR,(1<<offset));
        int_status_val=upmu_get_reg_value(interrupts[i].address); //得到中断状态
 
 
 
 
2.单独分析2
PMIC_EINT_SETTING
    //enable pwrkey/homekey interrupt
    upmu_set_reg_value(MT6328_INT_CON0_SET, 0xf);
    //for all interrupt events, turn on interrupt module clock
    pmic_set_register_value(PMIC_RG_INTRP_CK_PDN,0);
    //For BUCK OC related interrupt, please turn on pwmoc_6m_ck (6MHz) ,DCDC相关降压口
    pmic_set_register_value(PMIC_RG_PWMOC_6M_CK_PDN,0);
    pmic_register_interrupt_callback(0,pwrkey_int_handler);  //电源键按下中断回调

    pmic_register_interrupt_callback(1,homekey_int_handler); //home键按下相关回调
    pmic_register_interrupt_callback(2,pwrkey_int_handler_r);  //电源键释放中断回调
    pmic_register_interrupt_callback(3,homekey_int_handler_r); //home键释放中断回调
    pmic_register_interrupt_callback(6,bat_h_int_handler);  

        g_low_battery_level=0;
exec_low_battery_callback(LOW_BATTERY_LEVEL_0); //调用回调函数,由register_low_battery_notify注册的回调函数
            low_battery_callback = lbcb_tb[i].lbcb;
            low_battery_callback(low_battery_level); //执行回调函数
        pmic_set_register_value(PMIC_AUXADC_LBAT_VOLT_MIN,BAT_LV_1_THD); //最小值设置为3.25V
        lbat_min_en_setting(0);
lbat_max_en_setting(0); //关闭setting
        lbat_min_en_setting(1); //启动setting,打开中断
    pmic_register_interrupt_callback(7,bat_l_int_handler); //与bat_h_int_handler差不多,这里设置为3V
    pmic_register_interrupt_callback(38,chrdet_int_handler); //单独分析5,充电器的插入
       
    pmic_register_interrupt_callback(42,fg_cur_h_int_handler);
        g_battery_oc_level=0;
        exec_battery_oc_callback(BATTERY_OC_LEVEL_0); //调用register_battery_oc_notify注册的函数
        bat_oc_h_en_setting(0);
        bat_oc_l_en_setting(0);
        bat_oc_l_en_setting(1); //使能低电流中断
    pmic_register_interrupt_callback(43,fg_cur_l_int_handler); //与fg_cur_h_int_handler差不多
    mt_eint_registration(g_eint_pmic_num,g_cust_eint_mt_pmic_type,mt_pmic_eint_irq,0); //注册中断
        wake_up_pmic();
            wake_up_process(pmic_thread_handle);
                pmic_thread_kthread //执行这个函数,前面有分析
    
 
3.单独分析3
bat_percent_notify_init
    ktime = ktime_set(20, 0); //20s
    hrtimer_init(&bat_percent_notify_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    bat_percent_notify_timer.function = bat_percent_notify_task;    
    hrtimer_start(&bat_percent_notify_timer, ktime, HRTIMER_MODE_REL);
    bat_percent_notify_thread = kthread_run(bat_percent_notify_handler, 0, "bat_percent_notify_thread");
    
 
电池线程调用函数
bat_percent_notify_handler
    ktime = ktime_set(10, 0);  //10s
    wait_event_interruptible(bat_percent_notify_waiter, (bat_percent_notify_flag == KAL_TRUE));
    bat_per_val=bat_get_ui_percentage(); //得到bat的电量
        if (chr_wake_up_bat == KAL_TRUE)
return BMT_status.SOC;
else
return BMT_status.UI_SOC;
    //如果(没有充电器&&电池电量保护LEVE = 0&& 电量小于等于15%)
    if( (upmu_get_rgs_chrdet()==0) && (g_battery_percent_level==0) && (bat_per_val<=BAT_PERCENT_LINIT) )
        g_battery_percent_level=1;
        exec_battery_percent_callback(BATTERY_PERCENT_LEVEL_1); //其他模块通过register_battery_percent_notify注册回调函数
            battery_percent_callback = bpcb_tb[i].bpcb;  //注册的回调函数bpcb_tb[i].bpcb;
            battery_percent_callback(battery_percent_level); //调用
    //如果(g_battery_percent_level = 1 && 电量大于15%)
    else if( (g_battery_percent_level==1) && (bat_per_val>BAT_PERCENT_LINIT) )
        g_battery_percent_level=0;
        exec_battery_percent_callback(BATTERY_PERCENT_LEVEL_0); //一样的回调函数
    hrtimer_start(&bat_percent_notify_timer, ktime, HRTIMER_MODE_REL); //启动定时器
 
 
定时器执行函数
bat_percent_notify_task
    bat_percent_notify_flag = KAL_TRUE; 
    wake_up_interruptible(&bat_percent_notify_waiter); //唤醒电池线程调用函数
 
 
4.单独分析4
dlpt_notify_init
    
ktime = ktime_set(30, 0); //30s
 
    hrtimer_init(&dlpt_notify_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    dlpt_notify_timer.function = dlpt_notify_task;    //定时器执行函数
    hrtimer_start(&dlpt_notify_timer, ktime, HRTIMER_MODE_REL);
    dlpt_notify_thread = kthread_run(dlpt_notify_handler, 0, "dlpt_notify_thread"); //线程执行函数
    pmic_set_register_value(PMIC_RG_UVLO_VTHL,0); //设置低压锁定电压为2.5V
    switch(POWER_UVLO_VOLT_LEVEL) //现在设置是2.6v
        pmic_set_register_value(PMIC_RG_UVLO_VTHL,3);
 
 
低电压锁定线程
dlpt_notify_handler
    pre_ui_soc=bat_get_ui_percentage(); //获取电量
    cur_ui_soc=pre_ui_soc;
    do //下面都是循环
        ktime = ktime_set(10, 0);  //10s
        wait_event_interruptible(dlpt_notify_waiter, (dlpt_notify_flag == KAL_TRUE));
        cur_ui_soc=bat_get_ui_percentage();  //获取电量
        if (upmu_get_rgs_chrdet())    //如果有充电器
            g_imix_val=get_dlpt_imix_charging();
                zcv_val=PMIC_IMM_GetOneChannelValue(MT6328_AUX_ISENSE_AP,5,1); //电池电压
                imix_val=(zcv_val-vsys_min_1_val)*1000/ptim_rac_val_avg*9/10; ==》imix值
else
     g_imix_val=get_dlpt_imix();
                //adc and fg--------------------------------------------------------
do_ptim(KAL_FALSE); //得到一些值
                imix=(curr_avg+(volt_avg-g_lbatInt1)*1000/ptim_rac_val_avg)/10; ==>imix值
         if(g_imix_val >= 1)
     exec_dlpt_callback(g_imix_val);    
                dlpt_callback = dlpt_cb_tb[i].dlpt_cb;                
                dlpt_callback(g_dlpt_val);          //执行register_dlpt_notify 注册的回调函数         
         else
            exec_dlpt_callback(1);
 
定时器执行函数
dlpt_notify_task
    dlpt_notify_flag = KAL_TRUE; 
    wake_up_interruptible(&dlpt_notify_waiter);
 
 
 
//单独分析5,充电器插拔
 
chrdet_int_handler
    if (!upmu_get_rgs_chrdet())
    boot_mode = get_boot_mode();
    if(boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT || boot_mode == LOW_POWER_OFF_CHARGING_BOOT)
        mt_power_off(); //关机
    pmic_set_register_value(PMIC_RG_USBDL_RST,1); //强制离开usb Down load模式
    do_chrdet_int_task  //在Battery_common.c (kernel-3.10\drivers\power\mediatek)
        if (upmu_is_chr_det() == KAL_TRUE) //==》get_charger_detect_status();mt_usb_is_device
            BMT_status.charger_exist = KAL_TRUE;
        else
            BMT_status.charger_exist = KAL_FALSE;
            if (g_platform_boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT || g_platform_boot_mode == LOW_POWER_OFF_CHARGING_BOOT) //关机充电拔出
                battery_charging_control(CHARGING_CMD_SET_POWER_OFF, NULL); //停止充电
        mt_battery_charger_detect_check(); //检测充电器
            if (upmu_is_chr_det() == KAL_TRUE) //再次调用upmu_is_chr_det
                BMT_status.charger_exist = KAL_TRUE;
                mt_charger_type_detection(); //检测是那种充电器插入,在代码中的电量相关,充电模式第五章
                if ((BMT_status.charger_type == STANDARD_HOST) || (BMT_status.charger_type == CHARGING_HOST))  //如果是这两种
mt_usb_connect(); //ubs连接
            else
                BMT_status.charger_exist = KAL_FALSE;
BMT_status.charger_type = CHARGER_UNKNOWN;
                mt_usb_disconnect(); //断开连接
 
 
 
 

    
 
        
        
        
        
    
posted @ 2020-11-25 16:43  luoyuna  阅读(2155)  评论(0编辑  收藏  举报