经硬件排查发现led灯的电源域在休眠的过程中没有掉电,而是控制led灯的IO口掉电,接着排查驱动。
查看led驱动的suspend和resume发现:
static int led_suspend(struct device *dev, pm_message_t state)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
if (led_cdev->flags & LED_CORE_SUSPENDRESUME)
led_classdev_suspend(led_cdev);
return 0;
}
static int led_resume(struct device *dev)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
if (led_cdev->flags & LED_CORE_SUSPENDRESUME)
led_classdev_resume(led_cdev);
return 0;
}
在suspend和resume中都会对led_cdev->flags这个标志位进行判断,而这种情况就是由于led_cdev->flags & LED_CORE_SUSPENDRESUME判断一直true。导致会调用led_classdev_suspend和led_classdev_resume
/**
* led_classdev_suspend - suspend an led_classdev.
* @led_cdev: the led_classdev to suspend.
*/
void led_classdev_suspend(struct led_classdev *led_cdev)
{
led_dbg();
led_cdev->flags |= LED_SUSPENDED;
led_cdev->brightness_set(led_cdev, 0);
}
EXPORT_SYMBOL_GPL(led_classdev_suspend);
/**
* led_classdev_resume - resume an led_classdev.
* @led_cdev: the led_classdev to resume.
*/
void led_classdev_resume(struct led_classdev *led_cdev)
{
led_dbg();
led_cdev->brightness_set(led_cdev, led_cdev->brightness);
led_cdev->flags &= ~LED_SUSPENDED;
}
led_classdev_suspend的led_cdev->brightness_set(led_cdev, 0)把指示灯关掉了。
根本原因是 led_cdev->flags的设置,在drivers/leds/leds-gpios.c的create_gpio_led中
if (!template->retain_state_suspended)
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
将此处改为:
if (!template->retain_state_suspended)
led_dat->cdev.flags &= ~LED_CORE_SUSPENDRESUME; //dingzhihua for charging keep on
这应该能使用在RK3288上面(不过我并没有在RK3288平台上面测试过)