diff -drupN a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c --- a/kernel/time/alarmtimer.c 2018-08-06 17:23:04.000000000 +0300 +++ b/kernel/time/alarmtimer.c 2022-06-12 05:28:14.000000000 +0300 @@ -206,6 +206,18 @@ ktime_t alarm_expires_remaining(const st EXPORT_SYMBOL_GPL(alarm_expires_remaining); #ifdef CONFIG_RTC_CLASS +static int boot_mode; //0:normal boot; 1:charger mode; 2:recovery mode +static int __init boot_mode_setup(char *str) +{ + if (!str) + return -EINVAL; + + // androidboot.mode=charger + if (!strncmp(str, "charger", strlen("charger"))) + boot_mode = 1; + return 1; +} +__setup("androidboot.mode=", boot_mode_setup); /** * alarmtimer_suspend - Suspend time callback * @dev: unused @@ -280,6 +292,58 @@ static int alarmtimer_resume(struct devi rtc_timer_cancel(rtc, &rtctimer); return 0; } +static void alarmtimer_shutdown(struct platform_device *dev) +{ + struct rtc_time tm; + ktime_t min, now; + unsigned long flags; + struct rtc_device *rtc; + int ret; + struct alarm_base *base = &alarm_bases[ALARM_REALTIME_SHUTDOWN]; + // struct alarm_base *base = &alarm_bases[ALARM_BOOTTIME]; + struct timerqueue_node *next; + ktime_t delta; + + spin_lock_irqsave(&freezer_delta_lock, flags); + min = freezer_delta; + freezer_delta = ktime_set(0, 0); + spin_unlock_irqrestore(&freezer_delta_lock, flags); + + rtc = alarmtimer_get_rtcdev(); + /* If we have no rtcdev, just return */ + if (!rtc) + return; + + /* Find the soonest timer to expire*/ + spin_lock_irqsave(&base->lock, flags); + next = timerqueue_getnext(&base->timerqueue); + spin_unlock_irqrestore(&base->lock, flags); + if (!next) { + printk("[alarmtimer] have no shutdown alarm! %s %d\n", __FUNCTION__, __LINE__); + return; + } + delta = ktime_sub(next->expires, base->gettime()); + if (!min.tv64 || (delta.tv64 < min.tv64)) + min = delta; + + /*if the current time is less 50 seconds than the alarm time, the alarm should turn off*/ + if (ktime_to_ms(min) < 50 * MSEC_PER_SEC) { + printk("[alarmtimer] shutdown alarm interval is too short, less than 50s! %s %d\n", __FUNCTION__, __LINE__); + return; + } + /* Setup an rtc timer to fire that far in the future */ + rtc_timer_cancel(rtc, &rtctimer); + rtc_read_time(rtc, &tm); + now = rtc_tm_to_ktime(tm); + /* make the alarm trigger ahead of the alarm time, because the power on spend about 50s */ + min = ktime_sub(min, ktime_set(50, 0)); + printk("[alarmtimer] add shutdown alarm interval=%lldms, %s %d\n", ktime_to_ms(min), __FUNCTION__, __LINE__); + now = ktime_add(now, min); + + /* Set alarm, if in the past reject suspend briefly to handle */ + ret = rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); + return; +} #else static int alarmtimer_suspend(struct device *dev) @@ -829,7 +893,10 @@ static struct platform_driver alarmtimer .driver = { .name = "alarmtimer", .pm = &alarmtimer_pm_ops, - } + }, +#ifdef CONFIG_RTC_CLASS + .shutdown = alarmtimer_shutdown, +#endif }; /** @@ -863,6 +930,8 @@ static int __init alarmtimer_init(void) alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real; alarm_bases[ALARM_BOOTTIME].base_clockid = CLOCK_BOOTTIME; alarm_bases[ALARM_BOOTTIME].gettime = &ktime_get_boottime; + alarm_bases[ALARM_REALTIME_SHUTDOWN].base_clockid = CLOCK_REALTIME; + alarm_bases[ALARM_REALTIME_SHUTDOWN].gettime = &ktime_get_real; for (i = 0; i < ALARM_NUMTYPE; i++) { timerqueue_init_head(&alarm_bases[i].timerqueue); spin_lock_init(&alarm_bases[i].lock);