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 * Copyright 2011 Wolfram Sang, Pengutronix e.K.
  10 */
  11
  12/*
  13 * The code contained herein is licensed under the GNU General Public
  14 * License. You may obtain a copy of the GNU General Public License
  15 * Version 2 or later at the following locations:
  16 *
  17 * http://www.opensource.org/licenses/gpl-license.html
  18 * http://www.gnu.org/copyleft/gpl.html
  19 */
  20#include <linux/kernel.h>
  21#include <linux/module.h>
  22#include <linux/io.h>
  23#include <linux/init.h>
  24#include <linux/platform_device.h>
  25#include <linux/interrupt.h>
  26#include <linux/rtc.h>
  27#include <linux/slab.h>
  28#include <linux/of_device.h>
  29#include <linux/of.h>
  30#include <linux/stmp_device.h>
  31#include <linux/stmp3xxx_rtc_wdt.h>
  32
  33#include <mach/common.h>
  34
  35#define STMP3XXX_RTC_CTRL                       0x0
  36#define STMP3XXX_RTC_CTRL_SET                   0x4
  37#define STMP3XXX_RTC_CTRL_CLR                   0x8
  38#define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN          0x00000001
  39#define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN        0x00000002
  40#define STMP3XXX_RTC_CTRL_ALARM_IRQ             0x00000004
  41#define STMP3XXX_RTC_CTRL_WATCHDOGEN            0x00000010
  42
  43#define STMP3XXX_RTC_STAT                       0x10
  44#define STMP3XXX_RTC_STAT_STALE_SHIFT           16
  45#define STMP3XXX_RTC_STAT_RTC_PRESENT           0x80000000
  46
  47#define STMP3XXX_RTC_SECONDS                    0x30
  48
  49#define STMP3XXX_RTC_ALARM                      0x40
  50
  51#define STMP3XXX_RTC_WATCHDOG                   0x50
  52
  53#define STMP3XXX_RTC_PERSISTENT0                0x60
  54#define STMP3XXX_RTC_PERSISTENT0_SET            0x64
  55#define STMP3XXX_RTC_PERSISTENT0_CLR            0x68
  56#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN  0x00000002
  57#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN       0x00000004
  58#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE     0x00000080
  59
  60#define STMP3XXX_RTC_PERSISTENT1                0x70
  61/* missing bitmask in headers */
  62#define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER  0x80000000
  63
  64struct stmp3xxx_rtc_data {
  65        struct rtc_device *rtc;
  66        void __iomem *io;
  67        int irq_alarm;
  68};
  69
  70#if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG)
  71/**
  72 * stmp3xxx_wdt_set_timeout - configure the watchdog inside the STMP3xxx RTC
  73 * @dev: the parent device of the watchdog (= the RTC)
  74 * @timeout: the desired value for the timeout register of the watchdog.
  75 *           0 disables the watchdog
  76 *
  77 * The watchdog needs one register and two bits which are in the RTC domain.
  78 * To handle the resource conflict, the RTC driver will create another
  79 * platform_device for the watchdog driver as a child of the RTC device.
  80 * The watchdog driver is passed the below accessor function via platform_data
  81 * to configure the watchdog. Locking is not needed because accessing SET/CLR
  82 * registers is atomic.
  83 */
  84
  85static void stmp3xxx_wdt_set_timeout(struct device *dev, u32 timeout)
  86{
  87        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
  88
  89        if (timeout) {
  90                writel(timeout, rtc_data->io + STMP3XXX_RTC_WATCHDOG);
  91                writel(STMP3XXX_RTC_CTRL_WATCHDOGEN,
  92                       rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET);
  93                writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER,
  94                       rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_SET);
  95        } else {
  96                writel(STMP3XXX_RTC_CTRL_WATCHDOGEN,
  97                       rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
  98                writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER,
  99                       rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_CLR);
 100        }
 101}
 102
 103static struct stmp3xxx_wdt_pdata wdt_pdata = {
 104        .wdt_set_timeout = stmp3xxx_wdt_set_timeout,
 105};
 106
 107static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
 108{
 109        struct platform_device *wdt_pdev =
 110                platform_device_alloc("stmp3xxx_rtc_wdt", rtc_pdev->id);
 111
 112        if (wdt_pdev) {
 113                wdt_pdev->dev.parent = &rtc_pdev->dev;
 114                wdt_pdev->dev.platform_data = &wdt_pdata;
 115                platform_device_add(wdt_pdev);
 116        }
 117}
 118#else
 119static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
 120{
 121}
 122#endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */
 123
 124static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
 125{
 126        /*
 127         * The datasheet doesn't say which way round the
 128         * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0,
 129         * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS
 130         */
 131        while (readl(rtc_data->io + STMP3XXX_RTC_STAT) &
 132                        (0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT))
 133                cpu_relax();
 134}
 135
 136/* Time read/write */
 137static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 138{
 139        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 140
 141        stmp3xxx_wait_time(rtc_data);
 142        rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm);
 143        return 0;
 144}
 145
 146static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)
 147{
 148        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 149
 150        writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS);
 151        stmp3xxx_wait_time(rtc_data);
 152        return 0;
 153}
 154
 155/* interrupt(s) handler */
 156static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
 157{
 158        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id);
 159        u32 status = readl(rtc_data->io + STMP3XXX_RTC_CTRL);
 160
 161        if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) {
 162                writel(STMP3XXX_RTC_CTRL_ALARM_IRQ,
 163                                rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
 164                rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF);
 165                return IRQ_HANDLED;
 166        }
 167
 168        return IRQ_NONE;
 169}
 170
 171static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
 172{
 173        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 174
 175        if (enabled) {
 176                writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 177                                STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
 178                                rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
 179                writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
 180                                rtc_data->io + STMP3XXX_RTC_CTRL_SET);
 181        } else {
 182                writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 183                                STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
 184                                rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
 185                writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
 186                                rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
 187        }
 188        return 0;
 189}
 190
 191static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 192{
 193        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 194
 195        rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_ALARM), &alm->time);
 196        return 0;
 197}
 198
 199static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 200{
 201        unsigned long t;
 202        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 203
 204        rtc_tm_to_time(&alm->time, &t);
 205        writel(t, rtc_data->io + STMP3XXX_RTC_ALARM);
 206
 207        stmp3xxx_alarm_irq_enable(dev, alm->enabled);
 208
 209        return 0;
 210}
 211
 212static struct rtc_class_ops stmp3xxx_rtc_ops = {
 213        .alarm_irq_enable =
 214                          stmp3xxx_alarm_irq_enable,
 215        .read_time      = stmp3xxx_rtc_gettime,
 216        .set_mmss       = stmp3xxx_rtc_set_mmss,
 217        .read_alarm     = stmp3xxx_rtc_read_alarm,
 218        .set_alarm      = stmp3xxx_rtc_set_alarm,
 219};
 220
 221static int stmp3xxx_rtc_remove(struct platform_device *pdev)
 222{
 223        struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(pdev);
 224
 225        if (!rtc_data)
 226                return 0;
 227
 228        writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
 229                        rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
 230        free_irq(rtc_data->irq_alarm, &pdev->dev);
 231        rtc_device_unregister(rtc_data->rtc);
 232        platform_set_drvdata(pdev, NULL);
 233        iounmap(rtc_data->io);
 234        kfree(rtc_data);
 235
 236        return 0;
 237}
 238
 239static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 240{
 241        struct stmp3xxx_rtc_data *rtc_data;
 242        struct resource *r;
 243        int err;
 244
 245        rtc_data = kzalloc(sizeof *rtc_data, GFP_KERNEL);
 246        if (!rtc_data)
 247                return -ENOMEM;
 248
 249        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 250        if (!r) {
 251                dev_err(&pdev->dev, "failed to get resource\n");
 252                err = -ENXIO;
 253                goto out_free;
 254        }
 255
 256        rtc_data->io = ioremap(r->start, resource_size(r));
 257        if (!rtc_data->io) {
 258                dev_err(&pdev->dev, "ioremap failed\n");
 259                err = -EIO;
 260                goto out_free;
 261        }
 262
 263        rtc_data->irq_alarm = platform_get_irq(pdev, 0);
 264
 265        if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) &
 266                        STMP3XXX_RTC_STAT_RTC_PRESENT)) {
 267                dev_err(&pdev->dev, "no device onboard\n");
 268                err = -ENODEV;
 269                goto out_remap;
 270        }
 271
 272        platform_set_drvdata(pdev, rtc_data);
 273
 274        mxs_reset_block(rtc_data->io);
 275        writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 276                        STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
 277                        STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
 278                        rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
 279
 280        writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN |
 281                        STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
 282                        rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
 283
 284        rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev,
 285                                &stmp3xxx_rtc_ops, THIS_MODULE);
 286        if (IS_ERR(rtc_data->rtc)) {
 287                err = PTR_ERR(rtc_data->rtc);
 288                goto out_remap;
 289        }
 290
 291        err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, 0,
 292                        "RTC alarm", &pdev->dev);
 293        if (err) {
 294                dev_err(&pdev->dev, "Cannot claim IRQ%d\n",
 295                        rtc_data->irq_alarm);
 296                goto out_irq_alarm;
 297        }
 298
 299        stmp3xxx_wdt_register(pdev);
 300        return 0;
 301
 302out_irq_alarm:
 303        rtc_device_unregister(rtc_data->rtc);
 304out_remap:
 305        platform_set_drvdata(pdev, NULL);
 306        iounmap(rtc_data->io);
 307out_free:
 308        kfree(rtc_data);
 309        return err;
 310}
 311
 312#ifdef CONFIG_PM
 313static int stmp3xxx_rtc_suspend(struct platform_device *dev, pm_message_t state)
 314{
 315        return 0;
 316}
 317
 318static int stmp3xxx_rtc_resume(struct platform_device *dev)
 319{
 320        struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev);
 321
 322        mxs_reset_block(rtc_data->io);
 323        writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 324                        STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
 325                        STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
 326                        rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
 327        return 0;
 328}
 329#else
 330#define stmp3xxx_rtc_suspend    NULL
 331#define stmp3xxx_rtc_resume     NULL
 332#endif
 333
 334static const struct of_device_id rtc_dt_ids[] = {
 335        { .compatible = "fsl,stmp3xxx-rtc", },
 336        { /* sentinel */ }
 337};
 338MODULE_DEVICE_TABLE(of, rtc_dt_ids);
 339
 340static struct platform_driver stmp3xxx_rtcdrv = {
 341        .probe          = stmp3xxx_rtc_probe,
 342        .remove         = stmp3xxx_rtc_remove,
 343        .suspend        = stmp3xxx_rtc_suspend,
 344        .resume         = stmp3xxx_rtc_resume,
 345        .driver         = {
 346                .name   = "stmp3xxx-rtc",
 347                .owner  = THIS_MODULE,
 348                .of_match_table = of_match_ptr(rtc_dt_ids),
 349        },
 350};
 351
 352module_platform_driver(stmp3xxx_rtcdrv);
 353
 354MODULE_DESCRIPTION("STMP3xxx RTC Driver");
 355MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and "
 356                "Wolfram Sang <w.sang@pengutronix.de>");
 357MODULE_LICENSE("GPL");
 358
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.