linux/drivers/rtc/rtc-stmp3xxx.c
<<
>>
Prefs
   1/*
   2 * Freescale STMP37XX/STMP378X Real Time Clock driver
   3 *
   4 * Copyright (c) 2007 Sigmatel, Inc.
   5 * Peter Hartley, <peter.hartley@sigmatel.com>
   6 *
   7 * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
   8 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
   9 */
  10
  11/*
  12 * The code contained herein is licensed under the GNU General Public
  13 * License. You may obtain a copy of the GNU General Public License
  14 * Version 2 or later at the following locations:
  15 *
  16 * http://www.opensource.org/licenses/gpl-license.html
  17 * http://www.gnu.org/copyleft/gpl.html
  18 */
  19#include <linux/kernel.h>
  20#include <linux/module.h>
  21#include <linux/init.h>
  22#include <linux/platform_device.h>
  23#include <linux/interrupt.h>
  24#include <linux/rtc.h>
  25#include <linux/slab.h>
  26
  27#include <mach/platform.h>
  28#include <mach/stmp3xxx.h>
  29#include <mach/regs-rtc.h>
  30
  31struct stmp3xxx_rtc_data {
  32        struct rtc_device *rtc;
  33        unsigned irq_count;
  34        void __iomem *io;
  35        int irq_alarm, irq_1msec;
  36};
  37
  38static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
  39{
  40        /*
  41         * The datasheet doesn't say which way round the
  42         * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0,
  43         * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS
  44         */
  45        while (__raw_readl(rtc_data->io + HW_RTC_STAT) &
  46                        BF(0x80, RTC_STAT_STALE_REGS))
  47                cpu_relax();
  48}
  49
  50/* Time read/write */
  51static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
  52{
  53        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
  54
  55        stmp3xxx_wait_time(rtc_data);
  56        rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_SECONDS), rtc_tm);
  57        return 0;
  58}
  59
  60static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)
  61{
  62        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
  63
  64        __raw_writel(t, rtc_data->io + HW_RTC_SECONDS);
  65        stmp3xxx_wait_time(rtc_data);
  66        return 0;
  67}
  68
  69/* interrupt(s) handler */
  70static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
  71{
  72        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id);
  73        u32 status;
  74        u32 events = 0;
  75
  76        status = __raw_readl(rtc_data->io + HW_RTC_CTRL) &
  77                        (BM_RTC_CTRL_ALARM_IRQ | BM_RTC_CTRL_ONEMSEC_IRQ);
  78
  79        if (status & BM_RTC_CTRL_ALARM_IRQ) {
  80                stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ,
  81                                rtc_data->io + HW_RTC_CTRL);
  82                events |= RTC_AF | RTC_IRQF;
  83        }
  84
  85        if (status & BM_RTC_CTRL_ONEMSEC_IRQ) {
  86                stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ,
  87                                rtc_data->io + HW_RTC_CTRL);
  88                if (++rtc_data->irq_count % 1000 == 0) {
  89                        events |= RTC_UF | RTC_IRQF;
  90                        rtc_data->irq_count = 0;
  91                }
  92        }
  93
  94        if (events)
  95                rtc_update_irq(rtc_data->rtc, 1, events);
  96
  97        return IRQ_HANDLED;
  98}
  99
 100static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
 101{
 102        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 103        void __iomem *p = rtc_data->io + HW_RTC_PERSISTENT0,
 104                     *ctl = rtc_data->io + HW_RTC_CTRL;
 105
 106        if (enabled) {
 107                stmp3xxx_setl(BM_RTC_PERSISTENT0_ALARM_EN |
 108                              BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p);
 109                stmp3xxx_setl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl);
 110        } else {
 111                stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN |
 112                              BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p);
 113                stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl);
 114        }
 115        return 0;
 116}
 117
 118static int stmp3xxx_update_irq_enable(struct device *dev, unsigned int enabled)
 119{
 120        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 121
 122        if (enabled)
 123                stmp3xxx_setl(BM_RTC_CTRL_ONEMSEC_IRQ_EN,
 124                                rtc_data->io + HW_RTC_CTRL);
 125        else
 126                stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN,
 127                                rtc_data->io + HW_RTC_CTRL);
 128        return 0;
 129}
 130
 131static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 132{
 133        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 134
 135        rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_ALARM), &alm->time);
 136        return 0;
 137}
 138
 139static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 140{
 141        unsigned long t;
 142        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 143
 144        rtc_tm_to_time(&alm->time, &t);
 145        __raw_writel(t, rtc_data->io + HW_RTC_ALARM);
 146        return 0;
 147}
 148
 149static struct rtc_class_ops stmp3xxx_rtc_ops = {
 150        .alarm_irq_enable =
 151                          stmp3xxx_alarm_irq_enable,
 152        .update_irq_enable =
 153                          stmp3xxx_update_irq_enable,
 154        .read_time      = stmp3xxx_rtc_gettime,
 155        .set_mmss       = stmp3xxx_rtc_set_mmss,
 156        .read_alarm     = stmp3xxx_rtc_read_alarm,
 157        .set_alarm      = stmp3xxx_rtc_set_alarm,
 158};
 159
 160static int stmp3xxx_rtc_remove(struct platform_device *pdev)
 161{
 162        struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(pdev);
 163
 164        if (!rtc_data)
 165                return 0;
 166
 167        stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN,
 168                        rtc_data->io + HW_RTC_CTRL);
 169        free_irq(rtc_data->irq_alarm, &pdev->dev);
 170        free_irq(rtc_data->irq_1msec, &pdev->dev);
 171        rtc_device_unregister(rtc_data->rtc);
 172        iounmap(rtc_data->io);
 173        kfree(rtc_data);
 174
 175        return 0;
 176}
 177
 178static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 179{
 180        struct stmp3xxx_rtc_data *rtc_data;
 181        struct resource *r;
 182        int err;
 183
 184        rtc_data = kzalloc(sizeof *rtc_data, GFP_KERNEL);
 185        if (!rtc_data)
 186                return -ENOMEM;
 187
 188        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 189        if (!r) {
 190                dev_err(&pdev->dev, "failed to get resource\n");
 191                err = -ENXIO;
 192                goto out_free;
 193        }
 194
 195        rtc_data->io = ioremap(r->start, resource_size(r));
 196        if (!rtc_data->io) {
 197                dev_err(&pdev->dev, "ioremap failed\n");
 198                err = -EIO;
 199                goto out_free;
 200        }
 201
 202        rtc_data->irq_alarm = platform_get_irq(pdev, 0);
 203        rtc_data->irq_1msec = platform_get_irq(pdev, 1);
 204
 205        if (!(__raw_readl(HW_RTC_STAT + rtc_data->io) &
 206                        BM_RTC_STAT_RTC_PRESENT)) {
 207                dev_err(&pdev->dev, "no device onboard\n");
 208                err = -ENODEV;
 209                goto out_remap;
 210        }
 211
 212        stmp3xxx_reset_block(rtc_data->io, true);
 213        stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN |
 214                        BM_RTC_PERSISTENT0_ALARM_WAKE_EN |
 215                        BM_RTC_PERSISTENT0_ALARM_WAKE,
 216                        rtc_data->io + HW_RTC_PERSISTENT0);
 217        rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev,
 218                                &stmp3xxx_rtc_ops, THIS_MODULE);
 219        if (IS_ERR(rtc_data->rtc)) {
 220                err = PTR_ERR(rtc_data->rtc);
 221                goto out_remap;
 222        }
 223
 224        rtc_data->irq_count = 0;
 225        err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt,
 226                        IRQF_DISABLED, "RTC alarm", &pdev->dev);
 227        if (err) {
 228                dev_err(&pdev->dev, "Cannot claim IRQ%d\n",
 229                        rtc_data->irq_alarm);
 230                goto out_irq_alarm;
 231        }
 232        err = request_irq(rtc_data->irq_1msec, stmp3xxx_rtc_interrupt,
 233                        IRQF_DISABLED, "RTC tick", &pdev->dev);
 234        if (err) {
 235                dev_err(&pdev->dev, "Cannot claim IRQ%d\n",
 236                        rtc_data->irq_1msec);
 237                goto out_irq1;
 238        }
 239
 240        platform_set_drvdata(pdev, rtc_data);
 241
 242        return 0;
 243
 244out_irq1:
 245        free_irq(rtc_data->irq_alarm, &pdev->dev);
 246out_irq_alarm:
 247        stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN,
 248                        rtc_data->io + HW_RTC_CTRL);
 249        rtc_device_unregister(rtc_data->rtc);
 250out_remap:
 251        iounmap(rtc_data->io);
 252out_free:
 253        kfree(rtc_data);
 254        return err;
 255}
 256
 257#ifdef CONFIG_PM
 258static int stmp3xxx_rtc_suspend(struct platform_device *dev, pm_message_t state)
 259{
 260        return 0;
 261}
 262
 263static int stmp3xxx_rtc_resume(struct platform_device *dev)
 264{
 265        struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev);
 266
 267        stmp3xxx_reset_block(rtc_data->io, true);
 268        stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN |
 269                        BM_RTC_PERSISTENT0_ALARM_WAKE_EN |
 270                        BM_RTC_PERSISTENT0_ALARM_WAKE,
 271                        rtc_data->io + HW_RTC_PERSISTENT0);
 272        return 0;
 273}
 274#else
 275#define stmp3xxx_rtc_suspend    NULL
 276#define stmp3xxx_rtc_resume     NULL
 277#endif
 278
 279static struct platform_driver stmp3xxx_rtcdrv = {
 280        .probe          = stmp3xxx_rtc_probe,
 281        .remove         = stmp3xxx_rtc_remove,
 282        .suspend        = stmp3xxx_rtc_suspend,
 283        .resume         = stmp3xxx_rtc_resume,
 284        .driver         = {
 285                .name   = "stmp3xxx-rtc",
 286                .owner  = THIS_MODULE,
 287        },
 288};
 289
 290static int __init stmp3xxx_rtc_init(void)
 291{
 292        return platform_driver_register(&stmp3xxx_rtcdrv);
 293}
 294
 295static void __exit stmp3xxx_rtc_exit(void)
 296{
 297        platform_driver_unregister(&stmp3xxx_rtcdrv);
 298}
 299
 300module_init(stmp3xxx_rtc_init);
 301module_exit(stmp3xxx_rtc_exit);
 302
 303MODULE_DESCRIPTION("STMP3xxx RTC Driver");
 304MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>");
 305MODULE_LICENSE("GPL");
 306