static int rtc_ops_read_time(struct device *dev, struct rtc_time *tm)
{
    unsigned long time, flags;

    spin_lock_irqsave(&rtc_lock, flags);
    hal_rtc_get_tick_time(tm);
    spin_unlock_irqrestore(&rtc_lock, flags);

    tm->tm_year += RTC_MIN_YEAR_OFFSET;
    tm->tm_mon--;
    rtc_tm_to_time(tm, &time);
#if RTC_OVER_TIME_RESET
    if (unlikely(time > (unsigned long)LONG_MAX)) {
        rtc_reset_to_deftime(tm);
        rtc_tm_to_time(tm, &time);
    }
#endif
    tm->tm_wday = (time / 86400 + 4) % 7;	/* 1970/01/01 is Thursday */

    if (rtc_show_time) {
        rtc_xinfo("read tc time = %04d/%02d/%02d (%d) %02d:%02d:%02d\n",
                  tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
                  tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
    }

    return 0;
}
static int rtc_ops_set_time(struct device *dev, struct rtc_time *tm)
{
//                                                                
        printk("mtk_rtc_set_time\n");

#if defined(CONFIG_RTC_INTF_SECCLK)
        secclk_rtc_changed(rtc_ops_read_time, dev, tm);
#endif
//                                                                

	unsigned long time, flags;

	rtc_tm_to_time(tm, &time);
	if (time > (unsigned long)LONG_MAX)
		return -EINVAL;

	tm->tm_year -= RTC_MIN_YEAR_OFFSET;
	tm->tm_mon++;

	rtc_xinfo("set tc time = %04d/%02d/%02d %02d:%02d:%02d\n",
	          tm->tm_year + RTC_MIN_YEAR, tm->tm_mon, tm->tm_mday,
	          tm->tm_hour, tm->tm_min, tm->tm_sec);

	spin_lock_irqsave(&rtc_lock, flags);
	hal_rtc_set_tick_time(tm);
	spin_unlock_irqrestore(&rtc_lock, flags);

	return 0;
}
static int __init rtc_late_init(void)
{
    unsigned long flags;

    spin_lock_irqsave(&rtc_lock, flags);
    hal_rtc_read_rg();
    spin_unlock_irqrestore(&rtc_lock, flags);

    if (crystal_exist_status() == true)
        rtc_xinfo("There is Crystal\n");
    else
        rtc_xinfo("There is no Crystal\n");

#if (defined(MTK_GPS_MT3332))
    hal_rtc_set_gpio_32k_status(0, true);
#endif

    return 0;
}
static int rtc_ops_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
    /* dump_stack(); */
    rtc_xinfo("rtc_ops_ioctl cmd=%d\n", cmd);
    switch (cmd) {
    case RTC_AUTOBOOT_ON:
    {
        hal_rtc_set_register_status("AUTOBOOT", AUTOBOOT_ON);
        rtc_xinfo("rtc_ops_ioctl cmd=RTC_AUTOBOOT_ON\n");
        return 0;
    }
    case RTC_AUTOBOOT_OFF:	/* IPO shutdown */
    {
        hal_rtc_set_register_status("AUTOBOOT", AUTOBOOT_OFF);
        rtc_xinfo("rtc_ops_ioctl cmd=RTC_AUTOBOOT_OFF\n");
        return 0;
    }
    default:
        break;
    }
    return -ENOIOCTLCMD;
}
void rtc_pwm_enable_check(void)
{
#ifdef VRTC_PWM_ENABLE
    U64 time;

    rtc_xinfo("rtc_pwm_enable_check()\n");

    time = sched_clock();
    do_div(time, 1000000000);


    if(time > RTC_PWM_ENABLE_POLLING_TIMER)
    {
        hal_rtc_pwm_enable();
    }
    else
    {
        rtc_xinfo("time=%lld, less than %d, don't enable rtc pwm\n",time,RTC_PWM_ENABLE_POLLING_TIMER);
    }

#endif
}
static int rtc_ops_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
    unsigned long flags;
    struct rtc_time *tm = &alm->time;

    spin_lock_irqsave(&rtc_lock, flags);
    hal_rtc_get_alarm_time(tm, alm);
    spin_unlock_irqrestore(&rtc_lock, flags);

    tm->tm_year += RTC_MIN_YEAR_OFFSET;
    tm->tm_mon--;

    rtc_xinfo("read al time = %04d/%02d/%02d %02d:%02d:%02d (%d)\n",
              tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
              tm->tm_hour, tm->tm_min, tm->tm_sec, alm->enabled);

    return 0;
}
void rtc_read_pwron_alarm(struct rtc_wkalrm *alm)
{
    unsigned long flags;
    struct rtc_time *tm;

    if (alm == NULL)
        return;
    tm = &alm->time;
    spin_lock_irqsave(&rtc_lock, flags);
    hal_rtc_get_pwron_alarm(tm, alm);
    spin_unlock_irqrestore(&rtc_lock, flags);
    tm->tm_year += RTC_MIN_YEAR_OFFSET;
    tm->tm_mon -= 1;
    if (rtc_show_alarm) {
        rtc_xinfo("power-on = %04d/%02d/%02d %02d:%02d:%02d (%d)(%d)\n",
                  tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
                  tm->tm_hour, tm->tm_min, tm->tm_sec, alm->enabled, alm->pending);
    }
}
static int rtc_ops_set_time(struct device *dev, struct rtc_time *tm)
{
    unsigned long time, flags;

    rtc_tm_to_time(tm, &time);
    if (time > (unsigned long)LONG_MAX)
        return -EINVAL;

    tm->tm_year -= RTC_MIN_YEAR_OFFSET;
    tm->tm_mon++;

    rtc_xinfo("set tc time = %04d/%02d/%02d %02d:%02d:%02d\n",
              tm->tm_year + RTC_MIN_YEAR, tm->tm_mon, tm->tm_mday,
              tm->tm_hour, tm->tm_min, tm->tm_sec);

    spin_lock_irqsave(&rtc_lock, flags);
    hal_rtc_set_tick_time(tm);
    spin_unlock_irqrestore(&rtc_lock, flags);

    return 0;
}
static int __init rtc_device_init(void)
{
    int r;
    rtc_xinfo("rtc_init");

    r = platform_device_register(&rtc_pdev);
    if (r) {
        rtc_xerror("register device failed (%d)\n", r);
        return r;
    }

    r = platform_driver_register(&rtc_pdrv);
    if (r) {
        rtc_xerror("register driver failed (%d)\n", r);
        platform_device_unregister(&rtc_pdev);
        return r;
    }
#if (defined(MTK_GPS_MT3332))
    hal_rtc_set_gpio_32k_status(0, true);
#endif


    return 0;
}
static int rtc_ops_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
    unsigned long time, flags;
    struct rtc_time *tm = &alm->time;

    rtc_tm_to_time(tm, &time);
    if (time > (unsigned long)LONG_MAX)
        return -EINVAL;

    tm->tm_year -= RTC_MIN_YEAR_OFFSET;
    tm->tm_mon++;

    rtc_xinfo("set al time = %04d/%02d/%02d %02d:%02d:%02d (%d)\n",
              tm->tm_year + RTC_MIN_YEAR, tm->tm_mon, tm->tm_mday,
              tm->tm_hour, tm->tm_min, tm->tm_sec, alm->enabled);

    spin_lock_irqsave(&rtc_lock, flags);
    if (alm->enabled == 2) {	/* enable power-on alarm */
        rtc_save_pwron_time(true, tm, false);
    } else if (alm->enabled == 3) {	/* enable power-on alarm with logo */
        rtc_save_pwron_time(true, tm, true);
    } else if (alm->enabled == 4) {	/* disable power-on alarm */
        /* alm->enabled = 0; */
        rtc_save_pwron_time(false, tm, false);
    }

    /* disable alarm and clear Power-On Alarm bit */
    hal_rtc_clear_alarm(tm);

    if (alm->enabled) {
        hal_rtc_set_alarm_time(tm);
    }
    spin_unlock_irqrestore(&rtc_lock, flags);

    return 0;
}
/* static void rtc_tasklet_handler(unsigned long data) */
static void rtc_handler(void)
{
    bool pwron_alm = false, isLowPowerIrq = false, pwron_alarm = false;
    struct rtc_time nowtm;
    struct rtc_time tm;
    rtc_xinfo("rtc_tasklet_handler start\n");

    spin_lock(&rtc_lock);
    isLowPowerIrq = hal_rtc_is_lp_irq();
    if (isLowPowerIrq) {
        spin_unlock(&rtc_lock);
        return;
    }
#if RTC_RELPWR_WHEN_XRST
    /* set AUTO bit because AUTO = 0 when PWREN = 1 and alarm occurs */
    hal_rtc_reload_power();
#endif
    pwron_alarm = hal_rtc_check_pwron_alarm_rg(&nowtm, &tm);
    nowtm.tm_year += RTC_MIN_YEAR;
    tm.tm_year += RTC_MIN_YEAR;
    if (pwron_alarm) {
        unsigned long now_time, time;

        now_time =
            mktime(nowtm.tm_year, nowtm.tm_mon, nowtm.tm_mday, nowtm.tm_hour, nowtm.tm_min,
                   nowtm.tm_sec);
        time = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);

        if (now_time >= time - 1 && now_time <= time + 4) {	/* power on */
#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING)
            if (g_boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT
                    || g_boot_mode == LOW_POWER_OFF_CHARGING_BOOT) {
                time += 1;
                rtc_time_to_tm(time, &tm);
                tm.tm_year -= RTC_MIN_YEAR_OFFSET;
                tm.tm_mon += 1;
                /* tm.tm_sec += 1; */
                hal_rtc_set_alarm_time(&tm);
                spin_unlock(&rtc_lock);
                arch_reset(0, "kpoc");
            } else {
                hal_rtc_set_pwron_alarm();
                pwron_alm = true;
            }
#else
            hal_rtc_set_pwron_alarm();
            pwron_alm = true;
#endif
        } else if (now_time < time) {	/* set power-on alarm */
            if (tm.tm_sec == 0) {
                tm.tm_sec = 59;
                tm.tm_min -= 1;
            } else {
                tm.tm_sec -= 1;
            }
            hal_rtc_set_alarm_time(&tm);
        }
    }
    spin_unlock(&rtc_lock);

    if (rtc != NULL)
        rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);

    if (rtc_show_alarm)
        rtc_xinfo("%s time is up\n", pwron_alm ? "power-on" : "alarm");

}