*********************************************************************
关于13783开关机:
13783上的ON1B管脚是一个输入pin,在其上可以连接一个按键,记过设置后用于power on/off button。
首先该键可用作power/on键,当13783所在的pdk板处于供电状态,而13783对cpu处于断电状态时,也就是没有给cpu供电时,但此时13783的电源有电,此时只有13783由VATLAS电压维持的核心电路和RTC module正常工作。此时的检测电路可以监测ON1B管脚的电压(该脚由VATLAS上拉,47k的电阻太大了,上拉不够,应换为10k左右的)变化状况,当电压出现一个上升沿时,该上升沿会自动进行30ms的消抖,当此上升沿出现时,硬件检测电路会把他识别为一个turn on event,从而载入各regulator的默认参数,并按照默认的顺序依次启动(间隔2ms,避免大的突入电流)。
此键也可以用来关机使用,当ON1BRSTEN位(Register 15,第二个bit)置为高时,4s钟的按键可使13783给cpu断电,但是若RESTARTEN(Register 15,第一个bit)位置为高,13783会在1s钟之后重新给cpu供电,相当于来了一次reset,所以只有先把RESTARTEN位置为低,并且按键4s后,才相当于来了一次power off。
*********************************************************************
power management driver很主要有以下三方面作用:
1、开关所有的regular
2、为所有的regular设值
3、获得所有的regular的当前电流值
和电池的充电没有关系。充电是由PMIC Battery Driver来完成的。
static int pmic_power_probe(struct platform_device *pdev)
{
int irq, ret;
/* configure on/off button */
gpio_power_key_active();
irq = (int)pdev->dev.platform_data;
if (irq == 0) {
pr_info(KERN_INFO "PMIC Power has no platform data/n");
goto done;
}
set_irq_type(irq, IRQF_TRIGGER_RISING);
ret = request_irq(irq, power_key_int, 0, "power_key", 0);
if (ret)
pr_info(KERN_ERR "register on-off key interrupt failed/n");
set_irq_wake(irq, 1);
done:
pr_info(KERN_INFO "PMIC Power successfully probed/n");
return 0;
}
注册了on/off button的中断,中断函数为power_key_int,
中断函数为:
static irqreturn_t power_key_int(int irq, void *dev_id)
{
pr_info(KERN_INFO "on-off key pressed/n");
return 0;
}
可以在此函数内进行事件处理,判断之后进行power方面的操作。13783PMIC及其外围电路使其能够探测充电电源的存在,然后对电池进行充电,辅助电路还能探测和阻止过充电。PMIC Battery Driver附加的功能还有面作用:
1、 支持USB充电
2、 支持电源充电
电池的电压水平能够用AD来监视,过低电压和电池寿命已到能够被通知通过使用硬件中断系统。
PMIC Battery Driver提供IOCTL接口来进行控制和监视电池及充电状态。其中必须的功能有:
1、 充电管理的API包括选择正确的充电通道。
2、 配置充电的模式,比如充电电流。
3、 配置配置电池电压、电流水平监视以及end-of-life函数。
PMIC Battery Drive提供了IOCTL接口通过/dev/pmic_battery设备,每个IOCTL调用都会带来对应的PMIC控制寄存器的操作,当然,这个操作要通过PMIC protocol and SPI drivers来完成。
事件回调函数会通过PMIC protocol driver来直接进行注册,注册的函数会被调用当对应的事件被探测到,并且该事件导致的中断被PMIC protocol driver获知。
在初始化时要注册一个/dev/pmic_battery设备,使得应用层能够访问设备驱动通过IOCTL接口。
源代码在/<ltib_dir>/rpm/BUILD/linux-2.6.24/drivers/mxc/pmic/mc13783下,
pmic_battery.c 是PMIC battery 用户端的驱动
pmic_battery_defs.h 是对硬件寄存器的定义
阅读代码pmic_battery.c如下:
一.关于驱动的注册的代码
在代码pmic_battery.c的底部,有如下注册代码:
static int __init pmic_battery_init(void)
{
pr_debug("PMIC Battery driver loading.../n");
return platform_driver_register(&pmic_battery_driver_ldm);
}
static void __exit pmic_battery_exit(void)
{
platform_driver_unregister(&pmic_battery_driver_ldm);
pr_debug("PMIC Battery driver successfully unloaded/n");
}
module_init(pmic_battery_init);
module_exit(pmic_battery_exit);
从以上代码可看出这里进行了电源管理驱动pmic_battery_driver_ldm的注册,而关于这个驱动的定义同样在该文件中,定义为:
static struct platform_driver pmic_battery_driver_ldm = {
.driver = {
.name = "pmic_battery",
.bus = &platform_bus_type,
},
.suspend = pmic_battery_suspend,
.resume = pmic_battery_resume,
.probe = pmic_battery_probe,
.remove = pmic_battery_remove,
};
其中pmic_battery_probe是该驱动注册时要调用的回调函数,这个函数很重要,在这个函数里可以进行设备device的保存,以及资源的获得,以及其他的。
二.Driver驱动pmic_battery_probe回调函数阅读
static int pmic_battery_probe(struct platform_device *pdev)
{
int ret = 0;
struct class_device *temp_class;
pmic_battery_major = register_chrdev(0, PMIC_BATTERY_STRING,
&pmic_battery_fops);
if (pmic_battery_major < 0) {
printk(KERN_ERR "Unable to get a major for pmic_battery/n");
return pmic_battery_major;
}
init_waitqueue_head(&suspendq);
pmic_battery_class = class_create(THIS_MODULE, PMIC_BATTERY_STRING);
if (IS_ERR(pmic_battery_class)) {
printk(KERN_ERR "Error creating PMIC battery class./n");
ret = PTR_ERR(pmic_battery_class);
goto err_out1;
}
temp_class = class_device_create(pmic_battery_class, NULL,
MKDEV(pmic_battery_major, 0),
NULL, PMIC_BATTERY_STRING);
if (IS_ERR(temp_class)) {
printk(KERN_ERR "Error creating PMIC battery class device./n");
ret = PTR_ERR(temp_class);
goto err_out2;
}
pmic_batt_led_control(true);
pmic_batt_set_5k_pull(true);
printk(KERN_INFO "PMIC Battery successfully probed/n");
return ret;
err_out2:
class_destroy(pmic_battery_class);
err_out1:
unregister_chrdev(pmic_battery_major, PMIC_BATTERY_STRING);
return ret;
}
其中在mc13783/pmic_battery_defs.h有关于字符串的定义:
#define PMIC_BATTERY_STRING "pmic_battery"
可以看出,register_chrdev(0, PMIC_BATTERY_STRING, &pmic_battery_fops);注册了一个字符设备,名字为pmic_battery,同时指定了它的fileoperations结构体为pmic_battery_fops,关于该结构体定义同样子该c文件中,如下:
static struct file_operations pmic_battery_fops = {
.owner = THIS_MODULE,
.ioctl = pmic_battery_ioctl,
.open = pmic_battery_open,
.release = pmic_battery_release,
};
可以看出该设备驱动的用户层操作接口只有三个,还包括打开和关闭的两个必须函数,真正进行操作的函数只有pmic_battery_ioctl一个函数。
三、设备驱动pmic_battery_ioctl函数阅读
……..略()………
四、事件的注册分析
在代码里,看到了以下函数,是用来进行注册和取消注册的,如何使用还有待分析,如
下:
PMIC_STATUS mc13783_battery_event(t_batt_event event, void *callback, bool sub)
{
pmic_event_callback_t bat_callback;
type_event bat_event;
bat_callback.func = callback;
bat_callback.param = NULL;
switch (event) {
case BAT_IT_CHG_DET:
bat_event = EVENT_CHGDETI;
break;
case BAT_IT_CHG_OVERVOLT:
bat_event = EVENT_CHGOVI;
break;
case BAT_IT_CHG_REVERSE:
bat_event = EVENT_CHGREVI;
break;
case BAT_IT_CHG_SHORT_CIRCUIT:
bat_event = EVENT_CHGSHORTI;
break;
case BAT_IT_CCCV:
bat_event = EVENT_CCCVI;
break;
case BAT_IT_BELOW_THRESHOLD:
bat_event = EVENT_CHRGCURRI;
break;
default:
return PMIC_PARAMETER_ERROR;
}
if (sub == true) {
CHECK_ERROR(pmic_event_subscribe(bat_event, bat_callback));
} else {
CHECK_ERROR(pmic_event_unsubscribe(bat_event, bat_callback));
}
return 0;
}
/*!
* This function is used to subscribe on battery event IT.
*
* @param event type of event.
* @param callback event callback function.
*
* @return This function returns 0 if successful.
*/
PMIC_STATUS pmic_batt_event_subscribe(t_batt_event event, void *callback)
{
if (suspend_flag == 1)
return PMIC_ERROR;
return mc13783_battery_event(event, callback, true);
}
/*!
* This function is used to un subscribe on battery event IT.
*
* @param event type of event.
* @param callback event callback function.
*
* @return This function returns 0 if successful.
*/
PMIC_STATUS pmic_batt_event_unsubscribe(t_batt_event event, void *callback)
{
if (suspend_flag == 1)
return PMIC_ERROR;
return mc13783_battery_event(event, callback, false);
}