2  * An RTC driver for the AVR32 AT32AP700x processor series.
 
   4  * Copyright (C) 2007 Atmel Corporation
 
   6  * This program is free software; you can redistribute it and/or modify it
 
   7  * under the terms of the GNU General Public License version 2 as published
 
   8  * by the Free Software Foundation.
 
  11 #include <linux/module.h>
 
  12 #include <linux/kernel.h>
 
  13 #include <linux/platform_device.h>
 
  14 #include <linux/rtc.h>
 
  18  * This is a bare-bones RTC. It runs during most system sleep states, but has
 
  19  * no battery backup and gets reset during system restart.  It must be
 
  20  * initialized from an external clock (network, I2C, etc) before it can be of
 
  23  * The alarm functionality is limited by the hardware, not supporting
 
  24  * periodic interrupts.
 
  29 #define RTC_CTRL_PCLR              1
 
  30 #define RTC_CTRL_TOPEN             2
 
  31 #define RTC_CTRL_PSEL              8
 
  38 #define RTC_IER_TOPI               0
 
  41 #define RTC_IDR_TOPI               0
 
  44 #define RTC_IMR_TOPI               0
 
  47 #define RTC_ISR_TOPI               0
 
  50 #define RTC_ICR_TOPI               0
 
  52 #define RTC_BIT(name)           (1 << RTC_##name)
 
  53 #define RTC_BF(name, value)     ((value) << RTC_##name)
 
  55 #define rtc_readl(dev, reg)                             \
 
  56         __raw_readl((dev)->regs + RTC_##reg)
 
  57 #define rtc_writel(dev, reg, value)                     \
 
  58         __raw_writel((value), (dev)->regs + RTC_##reg)
 
  60 struct rtc_at32ap700x {
 
  61         struct rtc_device       *rtc;
 
  63         unsigned long           alarm_time;
 
  65         /* Protect against concurrent register access. */
 
  69 static int at32_rtc_readtime(struct device *dev, struct rtc_time *tm)
 
  71         struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
 
  74         now = rtc_readl(rtc, VAL);
 
  75         rtc_time_to_tm(now, tm);
 
  80 static int at32_rtc_settime(struct device *dev, struct rtc_time *tm)
 
  82         struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
 
  86         ret = rtc_tm_to_time(tm, &now);
 
  88                 rtc_writel(rtc, VAL, now);
 
  93 static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
  95         struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
 
  97         spin_lock_irq(&rtc->lock);
 
  98         rtc_time_to_tm(rtc->alarm_time, &alrm->time);
 
  99         alrm->enabled = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0;
 
 100         alrm->pending = rtc_readl(rtc, ISR) & RTC_BIT(ISR_TOPI) ? 1 : 0;
 
 101         spin_unlock_irq(&rtc->lock);
 
 106 static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 108         struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
 
 109         unsigned long rtc_unix_time;
 
 110         unsigned long alarm_unix_time;
 
 113         rtc_unix_time = rtc_readl(rtc, VAL);
 
 115         ret = rtc_tm_to_time(&alrm->time, &alarm_unix_time);
 
 119         if (alarm_unix_time < rtc_unix_time)
 
 122         spin_lock_irq(&rtc->lock);
 
 123         rtc->alarm_time = alarm_unix_time;
 
 124         rtc_writel(rtc, TOP, rtc->alarm_time);
 
 126                 rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
 
 127                                 | RTC_BIT(CTRL_TOPEN));
 
 129                 rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
 
 130                                 & ~RTC_BIT(CTRL_TOPEN));
 
 131         spin_unlock_irq(&rtc->lock);
 
 136 static int at32_rtc_ioctl(struct device *dev, unsigned int cmd,
 
 139         struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
 
 142         spin_lock_irq(&rtc->lock);
 
 146                 if (rtc_readl(rtc, VAL) > rtc->alarm_time) {
 
 150                 rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
 
 151                                 | RTC_BIT(CTRL_TOPEN));
 
 152                 rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
 
 153                 rtc_writel(rtc, IER, RTC_BIT(IER_TOPI));
 
 156                 rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
 
 157                                 & ~RTC_BIT(CTRL_TOPEN));
 
 158                 rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
 
 159                 rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
 
 166         spin_unlock_irq(&rtc->lock);
 
 171 static irqreturn_t at32_rtc_interrupt(int irq, void *dev_id)
 
 173         struct rtc_at32ap700x *rtc = (struct rtc_at32ap700x *)dev_id;
 
 174         unsigned long isr = rtc_readl(rtc, ISR);
 
 175         unsigned long events = 0;
 
 178         spin_lock(&rtc->lock);
 
 180         if (isr & RTC_BIT(ISR_TOPI)) {
 
 181                 rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
 
 182                 rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
 
 183                 rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
 
 184                                 & ~RTC_BIT(CTRL_TOPEN));
 
 185                 rtc_writel(rtc, VAL, rtc->alarm_time);
 
 186                 events = RTC_AF | RTC_IRQF;
 
 187                 rtc_update_irq(rtc->rtc, 1, events);
 
 191         spin_unlock(&rtc->lock);
 
 196 static struct rtc_class_ops at32_rtc_ops = {
 
 197         .ioctl          = at32_rtc_ioctl,
 
 198         .read_time      = at32_rtc_readtime,
 
 199         .set_time       = at32_rtc_settime,
 
 200         .read_alarm     = at32_rtc_readalarm,
 
 201         .set_alarm      = at32_rtc_setalarm,
 
 204 static int __init at32_rtc_probe(struct platform_device *pdev)
 
 206         struct resource *regs;
 
 207         struct rtc_at32ap700x *rtc;
 
 211         rtc = kzalloc(sizeof(struct rtc_at32ap700x), GFP_KERNEL);
 
 213                 dev_dbg(&pdev->dev, "out of memory\n");
 
 217         regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 219                 dev_dbg(&pdev->dev, "no mmio resource defined\n");
 
 224         irq = platform_get_irq(pdev, 0);
 
 226                 dev_dbg(&pdev->dev, "could not get irq\n");
 
 232         rtc->regs = ioremap(regs->start, regs->end - regs->start + 1);
 
 235                 dev_dbg(&pdev->dev, "could not map I/O memory\n");
 
 238         spin_lock_init(&rtc->lock);
 
 241          * Maybe init RTC: count from zero at 1 Hz, disable wrap irq.
 
 243          * Do not reset VAL register, as it can hold an old time
 
 244          * from last JTAG reset.
 
 246         if (!(rtc_readl(rtc, CTRL) & RTC_BIT(CTRL_EN))) {
 
 247                 rtc_writel(rtc, CTRL, RTC_BIT(CTRL_PCLR));
 
 248                 rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
 
 249                 rtc_writel(rtc, CTRL, RTC_BF(CTRL_PSEL, 0xe)
 
 253         ret = request_irq(irq, at32_rtc_interrupt, IRQF_SHARED, "rtc", rtc);
 
 255                 dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
 
 259         rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
 
 260                                 &at32_rtc_ops, THIS_MODULE);
 
 261         if (IS_ERR(rtc->rtc)) {
 
 262                 dev_dbg(&pdev->dev, "could not register rtc device\n");
 
 263                 ret = PTR_ERR(rtc->rtc);
 
 267         platform_set_drvdata(pdev, rtc);
 
 268         device_init_wakeup(&pdev->dev, 1);
 
 270         dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n",
 
 271                         (unsigned long)rtc->regs, rtc->irq);
 
 284 static int __exit at32_rtc_remove(struct platform_device *pdev)
 
 286         struct rtc_at32ap700x *rtc = platform_get_drvdata(pdev);
 
 288         device_init_wakeup(&pdev->dev, 0);
 
 290         free_irq(rtc->irq, rtc);
 
 292         rtc_device_unregister(rtc->rtc);
 
 294         platform_set_drvdata(pdev, NULL);
 
 299 MODULE_ALIAS("platform:at32ap700x_rtc");
 
 301 static struct platform_driver at32_rtc_driver = {
 
 302         .remove         = __exit_p(at32_rtc_remove),
 
 304                 .name   = "at32ap700x_rtc",
 
 305                 .owner  = THIS_MODULE,
 
 309 static int __init at32_rtc_init(void)
 
 311         return platform_driver_probe(&at32_rtc_driver, at32_rtc_probe);
 
 313 module_init(at32_rtc_init);
 
 315 static void __exit at32_rtc_exit(void)
 
 317         platform_driver_unregister(&at32_rtc_driver);
 
 319 module_exit(at32_rtc_exit);
 
 321 MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
 
 322 MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x");
 
 323 MODULE_LICENSE("GPL");