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