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, ¶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(); //断开连接