#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/irq.h>
+#include <asm/rtc.h>
+#include <asm/mach/time.h>
#include "omap-rtc.h"
extern spinlock_t rtc_lock;
+static int omap_rtc_alarm = NO_IRQ;
+static int omap_rtc_timer = NO_IRQ;
+
/* OMAP RTC register access macros: */
* A very tiny interrupt handler. It runs with SA_INTERRUPT set.
*/
-static irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
/*
* Either an alarm interrupt or update complete interrupt.
.fops = &rtc_fops,
};
-static int __init omap_rtc_probe(struct device *dev)
+static int __init omap_rtc_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(dev);
struct resource *res, *mem;
+ /* find the IRQs */
+
+ omap_rtc_timer = platform_get_irq(pdev, 0);
+ if (omap_rtc_timer <= 0) {
+ dev_err(&pdev->dev, "no irq for rtc timer\n");
+ return -ENOENT;
+ }
+
+ omap_rtc_alarm = platform_get_irq(pdev, 1);
+ if (omap_rtc_alarm <= 0) {
+ dev_err(&pdev->dev, "no irq for alarm\n");
+ return -ENOENT;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res)
mem = request_mem_region(res->start,
pdev->name, OMAP_RTC_BASE);
return -EBUSY;
}
- dev_set_drvdata(dev, mem);
+ platform_set_drvdata(pdev, mem);
if (CMOS_READ(OMAP_RTC_STATUS_REG) & OMAP_RTC_STATUS_POWER_UP) {
pr_info("%s: RTC power up reset detected.\n",
CMOS_WRITE(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
}
- if (request_irq(INT_RTC_TIMER, rtc_interrupt, SA_INTERRUPT,
+ if (request_irq(omap_rtc_timer, rtc_interrupt, SA_INTERRUPT,
pdev->name, NULL)) {
pr_debug("%s: RTC timer interrupt IRQ%d is not free.\n",
- pdev->name, INT_RTC_TIMER);
+ pdev->name, omap_rtc_timer);
goto fail;
}
- if (request_irq(INT_RTC_ALARM, rtc_interrupt, SA_INTERRUPT,
+ if (request_irq(omap_rtc_alarm, rtc_interrupt, SA_INTERRUPT,
pdev->name, NULL)) {
pr_debug("%s: RTC alarm interrupt IRQ%d is not free.\n",
- pdev->name, INT_RTC_ALARM);
- free_irq(INT_RTC_TIMER, NULL);
+ pdev->name, omap_rtc_alarm);
+ free_irq(omap_rtc_timer, NULL);
goto fail;
}
return -EIO;
}
-static int __exit omap_rtc_remove(struct device *dev)
+static int omap_rtc_remove(struct platform_device *pdev)
{
- free_irq (INT_RTC_TIMER, NULL);
- free_irq (INT_RTC_ALARM, NULL);
+ free_irq (omap_rtc_timer, NULL);
+ free_irq (omap_rtc_alarm, NULL);
remove_proc_entry ("driver/rtc", NULL);
misc_deregister(&rtc_dev);
- release_resource(dev_get_drvdata(dev));
+ release_resource(platform_get_drvdata(pdev));
return 0;
}
spin_unlock_irq(&rtc_lock);
}
-static struct device_driver omap_rtc_driver = {
- .name = "omap_rtc",
- .bus = &platform_bus_type,
+#ifdef CONFIG_PM
+static struct timespec rtc_delta;
+
+static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct rtc_time rtc_tm;
+ struct timespec time;
+
+ time.tv_nsec = 0;
+ get_rtc_time(&rtc_tm);
+ rtc_tm_to_time(&rtc_tm, &time.tv_sec);
+
+ save_time_delta(&rtc_delta, &time);
+
+ return 0;
+}
+
+static int omap_rtc_resume(struct platform_device *pdev)
+{
+ struct rtc_time rtc_tm;
+ struct timespec time;
+
+ time.tv_nsec = 0;
+ get_rtc_time(&rtc_tm);
+ rtc_tm_to_time(&rtc_tm, &time.tv_sec);
+
+ restore_time_delta(&rtc_delta, &time);
+
+ return 0;
+}
+#else
+#define omap_rtc_suspend NULL
+#define omap_rtc_resume NULL
+#endif
+
+static struct platform_driver omap_rtc_driver = {
.probe = omap_rtc_probe,
- .remove = __exit_p(omap_rtc_remove),
+ .remove = omap_rtc_remove,
+ .suspend = omap_rtc_suspend,
+ .resume = omap_rtc_resume,
+ .driver = {
+ .name = "omap_rtc",
+ .owner = THIS_MODULE,
+ },
};
+static char __initdata banner[] = KERN_INFO "OMAP RTC Driver\n";
+
static int __init rtc_init(void)
{
- return driver_register(&omap_rtc_driver);
+ printk(banner);
+ return platform_driver_register(&omap_rtc_driver);
}
static void __exit rtc_exit(void)
{
- driver_unregister(&omap_rtc_driver);
+ platform_driver_unregister(&omap_rtc_driver);
}
module_init(rtc_init);