一.初始化分析
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, ¶m); //這里是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;
pmic_register_interrupt_callback(38,chrdet_int_handler); //單獨分析5,充電器的插入
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(7,bat_l_int_handler); //與bat_h_int_handler差不多,這里設置為3V
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(); //斷開連接


