Example #1
0
static int s3c_rtc_resume(struct platform_device *pdev)
{
	s3c_rtc_enable(pdev, 1);
	writeb(ticnt_save, s3c_rtc_base + S3C_TICNT);
#ifdef CONFIG_RTC_SYNC
	rtc_sync_start ();
#endif
	printk ("%s\n", __func__);
	return 0;
}
Example #2
0
static void rtc_sync_work_handler(struct work_struct * __unused)
{
	static unsigned int 	old_idle_tick, busy_count;
	int 			next_interval;
	int 			cpu_idle;

	if (rtc_sync_state == RS_SAVE_DELTA)
	{
		rtc_sync_save_delta();
		rtc_sync_start();
		return;
	}

	switch (rtc_sync_state)
	{
	case RS_WAIT_ADJUST_TIME:
		/* start adjust service */
		busy_count = 0;
	case RS_WAIT_ADJUST_TIME_AFTER_BUSY:
		/* prepare detect cpu idle */
		old_idle_tick = kstat_cpu(0).cpustat.idle + kstat_cpu(0).cpustat.iowait;
		rtc_sync_state = RS_DETECT_IDLE;
		next_interval = RTC_SYNC_DETECT_IDLE_INTERVAL;
		break;
	case RS_DETECT_IDLE:
		cpu_idle = detect_cpu_idle(old_idle_tick);

		/* when cpu idle or passing the adjust force time */
		if (cpu_idle || ++busy_count > RTC_SYNC_MAX_BUSY_COUNT)
		{
			rtc_sync_state = RS_TRY_ADJUST;
			rtc_sync_adjust();
			rtc_sync_state = RS_WAIT_ADJUST_TIME;
			next_interval = RTC_SYNC_ADJUST_INTERVAL;
		}
		else
		{
			rtc_sync_state = RS_WAIT_ADJUST_TIME_AFTER_BUSY;
			next_interval = RTC_SYNC_AFTER_BUSY_INTERVAL;
		}
		break;
	default:
		return;
	}
	schedule_delayed_work(&rtc_sync_work, next_interval);
}
Example #3
0
static int __devinit s3c_rtc_probe(struct platform_device *pdev)
{
	struct rtc_device *rtc;
	struct resource *res;
        unsigned char bcd_tmp,bcd_loop;
	int ret;
#ifdef CONFIG_RTC_DRV_MAX8998
	struct rtc_time tm;
#endif

	pr_debug("%s: probe=%p\n", __func__, pdev);

	/* find the IRQs */

	s3c_rtc_tickno = platform_get_irq(pdev, 1);
	if (s3c_rtc_tickno < 0) {
		dev_err(&pdev->dev, "no irq for rtc tick\n");
		return -ENOENT;
	}

	s3c_rtc_alarmno = platform_get_irq(pdev, 0);
	if (s3c_rtc_alarmno < 0) {
		dev_err(&pdev->dev, "no irq for alarm\n");
		return -ENOENT;
	}

	pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n",
		 s3c_rtc_tickno, s3c_rtc_alarmno);

	/* get the memory region */

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(&pdev->dev, "failed to get memory region resource\n");
		return -ENOENT;
	}

	s3c_rtc_mem = request_mem_region(res->start,
					 res->end-res->start+1,
					 pdev->name);

	if (s3c_rtc_mem == NULL) {
		dev_err(&pdev->dev, "failed to reserve memory region\n");
		ret = -ENOENT;
		goto err_nores;
	}

	s3c_rtc_base = ioremap(res->start, res->end - res->start + 1);
	if (s3c_rtc_base == NULL) {
		dev_err(&pdev->dev, "failed ioremap()\n");
		ret = -EINVAL;
		goto err_nomap;
	}

	/* check to see if everything is setup correctly */

	s3c_rtc_enable(pdev, 1);

 	pr_debug("s3c2410_rtc: RTCCON=%02x\n",
		 readb(s3c_rtc_base + S3C2410_RTCCON));

	s3c_rtc_setfreq(&pdev->dev, 1);

	device_init_wakeup(&pdev->dev, 1);

#ifdef CONFIG_RTC_DRV_MAX8998
	max8998_rtc_read_time(&tm);
#endif

	/* register RTC and exit */

	rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,
				  THIS_MODULE);

	if (IS_ERR(rtc)) {
		dev_err(&pdev->dev, "cannot attach rtc\n");
		ret = PTR_ERR(rtc);
		goto err_nortc;
	}

	rtc->max_user_freq = S3C_MAX_CNT;

#ifdef CONFIG_RTC_DRV_MAX8998
	s3c_rtc_settime(rtc, &tm);  //update from pmic
#endif

#ifdef SET_RTC_DEFAULT_RESET_TIME
	{
		struct rtc_time tm;

		s3c_rtc_gettime (pdev, &tm);
		if (rtc_valid_tm (&tm) != 0)
		{
			struct rtc_time reset_tm = {
				.tm_sec = DEFAULT_RESET_TIME_SEC,
				.tm_min = DEFAULT_RESET_TIME_MIN,
				.tm_hour = DEFAULT_RESET_TIME_HOUR,
				.tm_mday = DEFAULT_RESET_TIME_DATE,
				.tm_mon = DEFAULT_RESET_TIME_MON - 1,
				.tm_year = DEFAULT_RESET_TIME_YEAR - 1900,
				};

			s3c_rtc_settime (pdev, &reset_tm);
			#ifdef CONFIG_RTC_DRV_MAX8998
			max8998_rtc_set_time(&reset_tm); // also update pmic rtc as default 
			#endif
		}
	}
#else

	/* check rtc time */
	for (bcd_loop = S3C2410_RTCSEC ; bcd_loop <= S3C2410_RTCYEAR ; bcd_loop +=0x4)
	{
		bcd_tmp = readb(s3c_rtc_base + bcd_loop);
		if(((bcd_tmp & 0xf) > 0x9) || ((bcd_tmp & 0xf0) > 0x90))
			writeb(0, s3c_rtc_base + bcd_loop);
	}
#endif /* SET_RTC_DEFAULT_RESET_TIME */

	platform_set_drvdata(pdev, rtc);

#ifdef CONFIG_RTC_S3C_SYNC_SYSTEM_TIME
	rtc_sync_start_save_delta();
#endif	/* CONFIG_RTC_S3C_SYNC_SYSTEM_TIME */

	return 0;

 err_nortc:
	s3c_rtc_enable(pdev, 0);
	iounmap(s3c_rtc_base);

 err_nomap:
	release_resource(s3c_rtc_mem);

 err_nores:
	return ret;
}

#ifdef CONFIG_PM

/* RTC Power management control */

static struct timespec s3c_rtc_delta;
static int ticnt_save;

static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
{
	struct rtc_time tm;
	struct timespec time;

	time.tv_nsec = 0;
	/* save TICNT for anyone using periodic interrupts */
	ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);

	s3c_rtc_gettime(&pdev->dev, &tm);
	rtc_tm_to_time(&tm, &time.tv_sec);
	save_time_delta(&s3c_rtc_delta, &time);

	if (gpio_get_value(GPIO_WLAN_BT_EN) == 0) /* BCM4329 isnt working */
		s3c_rtc_enable(pdev, 0);
	
#ifdef CONFIG_RTC_S3C_SYNC_SYSTEM_TIME
	cancel_delayed_work(&rtc_sync_work);
#endif	/* CONFIG_RTC_S3C_SYNC_SYSTEM_TIME */

	return 0;
}

static int s3c_rtc_resume(struct platform_device *pdev)
{
	struct rtc_time tm;
	struct timespec time;

	time.tv_nsec = 0;

	if (gpio_get_value(GPIO_WLAN_BT_EN) == 0) /* BCM4329 isnt working */
		s3c_rtc_enable(pdev, 1);

	s3c_rtc_gettime(&pdev->dev, &tm);
	rtc_tm_to_time(&tm, &time.tv_sec);
	restore_time_delta(&s3c_rtc_delta, &time);
	writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);

#ifdef CONFIG_RTC_S3C_SYNC_SYSTEM_TIME
	rtc_sync_start ();
#endif

	return 0;
}
#else
#define s3c_rtc_suspend NULL
#define s3c_rtc_resume  NULL
#endif

static struct platform_driver s3c2410_rtc_driver = {
	.probe		= s3c_rtc_probe,
	.remove		= __devexit_p(s3c_rtc_remove),
	.suspend	= s3c_rtc_suspend,
	.resume		= s3c_rtc_resume,
	.driver		= {
		.name	= "s3c2410-rtc",
		.owner	= THIS_MODULE,
	},
};

static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n";

static int __init s3c_rtc_init(void)
{
	printk(banner);
	return platform_driver_register(&s3c2410_rtc_driver);
}