linux/drivers/rtc/rtc-mxc_v2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Real Time Clock (RTC) Driver for i.MX53
   4 * Copyright (c) 2004-2011 Freescale Semiconductor, Inc.
   5 * Copyright (c) 2017 Beckhoff Automation GmbH & Co. KG
   6 */
   7
   8#include <linux/clk.h>
   9#include <linux/io.h>
  10#include <linux/module.h>
  11#include <linux/platform_device.h>
  12#include <linux/rtc.h>
  13
  14#define SRTC_LPPDR_INIT       0x41736166        /* init for glitch detect */
  15
  16#define SRTC_LPCR_EN_LP       BIT(3)    /* lp enable */
  17#define SRTC_LPCR_WAE         BIT(4)    /* lp wakeup alarm enable */
  18#define SRTC_LPCR_ALP         BIT(7)    /* lp alarm flag */
  19#define SRTC_LPCR_NSA         BIT(11)   /* lp non secure access */
  20#define SRTC_LPCR_NVE         BIT(14)   /* lp non valid state exit bit */
  21#define SRTC_LPCR_IE          BIT(15)   /* lp init state exit bit */
  22
  23#define SRTC_LPSR_ALP         BIT(3)    /* lp alarm flag */
  24#define SRTC_LPSR_NVES        BIT(14)   /* lp non-valid state exit status */
  25#define SRTC_LPSR_IES         BIT(15)   /* lp init state exit status */
  26
  27#define SRTC_LPSCMR     0x00    /* LP Secure Counter MSB Reg */
  28#define SRTC_LPSCLR     0x04    /* LP Secure Counter LSB Reg */
  29#define SRTC_LPSAR      0x08    /* LP Secure Alarm Reg */
  30#define SRTC_LPCR       0x10    /* LP Control Reg */
  31#define SRTC_LPSR       0x14    /* LP Status Reg */
  32#define SRTC_LPPDR      0x18    /* LP Power Supply Glitch Detector Reg */
  33
  34/* max. number of retries to read registers, 120 was max during test */
  35#define REG_READ_TIMEOUT 2000
  36
  37struct mxc_rtc_data {
  38        struct rtc_device *rtc;
  39        void __iomem *ioaddr;
  40        struct clk *clk;
  41        spinlock_t lock; /* protects register access */
  42        int irq;
  43};
  44
  45/*
  46 * This function does write synchronization for writes to the lp srtc block.
  47 * To take care of the asynchronous CKIL clock, all writes from the IP domain
  48 * will be synchronized to the CKIL domain.
  49 * The caller should hold the pdata->lock
  50 */
  51static void mxc_rtc_sync_lp_locked(struct device *dev, void __iomem *ioaddr)
  52{
  53        unsigned int i;
  54
  55        /* Wait for 3 CKIL cycles */
  56        for (i = 0; i < 3; i++) {
  57                const u32 count = readl(ioaddr + SRTC_LPSCLR);
  58                unsigned int timeout = REG_READ_TIMEOUT;
  59
  60                while ((readl(ioaddr + SRTC_LPSCLR)) == count) {
  61                        if (!--timeout) {
  62                                dev_err_once(dev, "SRTC_LPSCLR stuck! Check your hw.\n");
  63                                return;
  64                        }
  65                }
  66        }
  67}
  68
  69/* This function is the RTC interrupt service routine. */
  70static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
  71{
  72        struct device *dev = dev_id;
  73        struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
  74        void __iomem *ioaddr = pdata->ioaddr;
  75        unsigned long flags;
  76        u32 lp_status;
  77        u32 lp_cr;
  78
  79        spin_lock_irqsave(&pdata->lock, flags);
  80        if (clk_enable(pdata->clk)) {
  81                spin_unlock_irqrestore(&pdata->lock, flags);
  82                return IRQ_NONE;
  83        }
  84
  85        lp_status = readl(ioaddr + SRTC_LPSR);
  86        lp_cr = readl(ioaddr + SRTC_LPCR);
  87
  88        /* update irq data & counter */
  89        if (lp_status & SRTC_LPSR_ALP) {
  90                if (lp_cr & SRTC_LPCR_ALP)
  91                        rtc_update_irq(pdata->rtc, 1, RTC_AF | RTC_IRQF);
  92
  93                /* disable further lp alarm interrupts */
  94                lp_cr &= ~(SRTC_LPCR_ALP | SRTC_LPCR_WAE);
  95        }
  96
  97        /* Update interrupt enables */
  98        writel(lp_cr, ioaddr + SRTC_LPCR);
  99
 100        /* clear interrupt status */
 101        writel(lp_status, ioaddr + SRTC_LPSR);
 102
 103        mxc_rtc_sync_lp_locked(dev, ioaddr);
 104        clk_disable(pdata->clk);
 105        spin_unlock_irqrestore(&pdata->lock, flags);
 106        return IRQ_HANDLED;
 107}
 108
 109/*
 110 * Enable clk and aquire spinlock
 111 * @return  0 if successful; non-zero otherwise.
 112 */
 113static int mxc_rtc_lock(struct mxc_rtc_data *const pdata)
 114{
 115        int ret;
 116
 117        spin_lock_irq(&pdata->lock);
 118        ret = clk_enable(pdata->clk);
 119        if (ret) {
 120                spin_unlock_irq(&pdata->lock);
 121                return ret;
 122        }
 123        return 0;
 124}
 125
 126static int mxc_rtc_unlock(struct mxc_rtc_data *const pdata)
 127{
 128        clk_disable(pdata->clk);
 129        spin_unlock_irq(&pdata->lock);
 130        return 0;
 131}
 132
 133/*
 134 * This function reads the current RTC time into tm in Gregorian date.
 135 *
 136 * @param  tm           contains the RTC time value upon return
 137 *
 138 * @return  0 if successful; non-zero otherwise.
 139 */
 140static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
 141{
 142        struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
 143        const int clk_failed = clk_enable(pdata->clk);
 144
 145        if (!clk_failed) {
 146                const time64_t now = readl(pdata->ioaddr + SRTC_LPSCMR);
 147
 148                rtc_time64_to_tm(now, tm);
 149                clk_disable(pdata->clk);
 150                return 0;
 151        }
 152        return clk_failed;
 153}
 154
 155/*
 156 * This function sets the internal RTC time based on tm in Gregorian date.
 157 *
 158 * @param  tm           the time value to be set in the RTC
 159 *
 160 * @return  0 if successful; non-zero otherwise.
 161 */
 162static int mxc_rtc_set_time(struct device *dev, struct rtc_time *tm)
 163{
 164        struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
 165        time64_t time = rtc_tm_to_time64(tm);
 166        int ret;
 167
 168        if (time > U32_MAX) {
 169                dev_err(dev, "RTC exceeded by %llus\n", time - U32_MAX);
 170                return -EINVAL;
 171        }
 172
 173        ret = mxc_rtc_lock(pdata);
 174        if (ret)
 175                return ret;
 176
 177        writel(time, pdata->ioaddr + SRTC_LPSCMR);
 178        mxc_rtc_sync_lp_locked(dev, pdata->ioaddr);
 179        return mxc_rtc_unlock(pdata);
 180}
 181
 182/*
 183 * This function reads the current alarm value into the passed in \b alrm
 184 * argument. It updates the \b alrm's pending field value based on the whether
 185 * an alarm interrupt occurs or not.
 186 *
 187 * @param  alrm         contains the RTC alarm value upon return
 188 *
 189 * @return  0 if successful; non-zero otherwise.
 190 */
 191static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 192{
 193        struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
 194        void __iomem *ioaddr = pdata->ioaddr;
 195        int ret;
 196
 197        ret = mxc_rtc_lock(pdata);
 198        if (ret)
 199                return ret;
 200
 201        rtc_time_to_tm(readl(ioaddr + SRTC_LPSAR), &alrm->time);
 202        alrm->pending = !!(readl(ioaddr + SRTC_LPSR) & SRTC_LPSR_ALP);
 203        return mxc_rtc_unlock(pdata);
 204}
 205
 206/*
 207 * Enable/Disable alarm interrupt
 208 * The caller should hold the pdata->lock
 209 */
 210static void mxc_rtc_alarm_irq_enable_locked(struct mxc_rtc_data *pdata,
 211                                            unsigned int enable)
 212{
 213        u32 lp_cr = readl(pdata->ioaddr + SRTC_LPCR);
 214
 215        if (enable)
 216                lp_cr |= (SRTC_LPCR_ALP | SRTC_LPCR_WAE);
 217        else
 218                lp_cr &= ~(SRTC_LPCR_ALP | SRTC_LPCR_WAE);
 219
 220        writel(lp_cr, pdata->ioaddr + SRTC_LPCR);
 221}
 222
 223static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
 224{
 225        struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
 226        int ret = mxc_rtc_lock(pdata);
 227
 228        if (ret)
 229                return ret;
 230
 231        mxc_rtc_alarm_irq_enable_locked(pdata, enable);
 232        return mxc_rtc_unlock(pdata);
 233}
 234
 235/*
 236 * This function sets the RTC alarm based on passed in alrm.
 237 *
 238 * @param  alrm         the alarm value to be set in the RTC
 239 *
 240 * @return  0 if successful; non-zero otherwise.
 241 */
 242static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 243{
 244        const time64_t time = rtc_tm_to_time64(&alrm->time);
 245        struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
 246        int ret = mxc_rtc_lock(pdata);
 247
 248        if (ret)
 249                return ret;
 250
 251        if (time > U32_MAX) {
 252                dev_err(dev, "Hopefully I am out of service by then :-(\n");
 253                return -EINVAL;
 254        }
 255
 256        writel((u32)time, pdata->ioaddr + SRTC_LPSAR);
 257
 258        /* clear alarm interrupt status bit */
 259        writel(SRTC_LPSR_ALP, pdata->ioaddr + SRTC_LPSR);
 260        mxc_rtc_sync_lp_locked(dev, pdata->ioaddr);
 261
 262        mxc_rtc_alarm_irq_enable_locked(pdata, alrm->enabled);
 263        mxc_rtc_sync_lp_locked(dev, pdata->ioaddr);
 264        mxc_rtc_unlock(pdata);
 265        return ret;
 266}
 267
 268static const struct rtc_class_ops mxc_rtc_ops = {
 269        .read_time = mxc_rtc_read_time,
 270        .set_time = mxc_rtc_set_time,
 271        .read_alarm = mxc_rtc_read_alarm,
 272        .set_alarm = mxc_rtc_set_alarm,
 273        .alarm_irq_enable = mxc_rtc_alarm_irq_enable,
 274};
 275
 276static int mxc_rtc_wait_for_flag(void __iomem *ioaddr, int flag)
 277{
 278        unsigned int timeout = REG_READ_TIMEOUT;
 279
 280        while (!(readl(ioaddr) & flag)) {
 281                if (!--timeout)
 282                        return -EBUSY;
 283        }
 284        return 0;
 285}
 286
 287static int mxc_rtc_probe(struct platform_device *pdev)
 288{
 289        struct mxc_rtc_data *pdata;
 290        struct resource *res;
 291        void __iomem *ioaddr;
 292        int ret = 0;
 293
 294        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 295        if (!pdata)
 296                return -ENOMEM;
 297
 298        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 299        pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res);
 300        if (IS_ERR(pdata->ioaddr))
 301                return PTR_ERR(pdata->ioaddr);
 302
 303        ioaddr = pdata->ioaddr;
 304
 305        pdata->clk = devm_clk_get(&pdev->dev, NULL);
 306        if (IS_ERR(pdata->clk)) {
 307                dev_err(&pdev->dev, "unable to get rtc clock!\n");
 308                return PTR_ERR(pdata->clk);
 309        }
 310
 311        spin_lock_init(&pdata->lock);
 312        pdata->irq = platform_get_irq(pdev, 0);
 313        if (pdata->irq < 0)
 314                return pdata->irq;
 315
 316        device_init_wakeup(&pdev->dev, 1);
 317
 318        ret = clk_prepare_enable(pdata->clk);
 319        if (ret)
 320                return ret;
 321        /* initialize glitch detect */
 322        writel(SRTC_LPPDR_INIT, ioaddr + SRTC_LPPDR);
 323
 324        /* clear lp interrupt status */
 325        writel(0xFFFFFFFF, ioaddr + SRTC_LPSR);
 326
 327        /* move out of init state */
 328        writel((SRTC_LPCR_IE | SRTC_LPCR_NSA), ioaddr + SRTC_LPCR);
 329        ret = mxc_rtc_wait_for_flag(ioaddr + SRTC_LPSR, SRTC_LPSR_IES);
 330        if (ret) {
 331                dev_err(&pdev->dev, "Timeout waiting for SRTC_LPSR_IES\n");
 332                clk_disable_unprepare(pdata->clk);
 333                return ret;
 334        }
 335
 336        /* move out of non-valid state */
 337        writel((SRTC_LPCR_IE | SRTC_LPCR_NVE | SRTC_LPCR_NSA |
 338                SRTC_LPCR_EN_LP), ioaddr + SRTC_LPCR);
 339        ret = mxc_rtc_wait_for_flag(ioaddr + SRTC_LPSR, SRTC_LPSR_NVES);
 340        if (ret) {
 341                dev_err(&pdev->dev, "Timeout waiting for SRTC_LPSR_NVES\n");
 342                clk_disable_unprepare(pdata->clk);
 343                return ret;
 344        }
 345
 346        clk_disable(pdata->clk);
 347        platform_set_drvdata(pdev, pdata);
 348        ret =
 349            devm_request_irq(&pdev->dev, pdata->irq, mxc_rtc_interrupt, 0,
 350                             pdev->name, &pdev->dev);
 351        if (ret < 0) {
 352                dev_err(&pdev->dev, "interrupt not available.\n");
 353                clk_unprepare(pdata->clk);
 354                return ret;
 355        }
 356
 357        pdata->rtc =
 358            devm_rtc_device_register(&pdev->dev, pdev->name, &mxc_rtc_ops,
 359                                     THIS_MODULE);
 360        if (IS_ERR(pdata->rtc)) {
 361                clk_unprepare(pdata->clk);
 362                return PTR_ERR(pdata->rtc);
 363        }
 364
 365        return 0;
 366}
 367
 368static int mxc_rtc_remove(struct platform_device *pdev)
 369{
 370        struct mxc_rtc_data *pdata = platform_get_drvdata(pdev);
 371
 372        clk_disable_unprepare(pdata->clk);
 373        return 0;
 374}
 375
 376#ifdef CONFIG_PM_SLEEP
 377static int mxc_rtc_suspend(struct device *dev)
 378{
 379        struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
 380
 381        if (device_may_wakeup(dev))
 382                enable_irq_wake(pdata->irq);
 383
 384        return 0;
 385}
 386
 387static int mxc_rtc_resume(struct device *dev)
 388{
 389        struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
 390
 391        if (device_may_wakeup(dev))
 392                disable_irq_wake(pdata->irq);
 393
 394        return 0;
 395}
 396#endif
 397
 398static SIMPLE_DEV_PM_OPS(mxc_rtc_pm_ops, mxc_rtc_suspend, mxc_rtc_resume);
 399
 400static const struct of_device_id mxc_ids[] = {
 401        { .compatible = "fsl,imx53-rtc", },
 402        {}
 403};
 404
 405static struct platform_driver mxc_rtc_driver = {
 406        .driver = {
 407                .name = "mxc_rtc_v2",
 408                .of_match_table = mxc_ids,
 409                .pm = &mxc_rtc_pm_ops,
 410        },
 411        .probe = mxc_rtc_probe,
 412        .remove = mxc_rtc_remove,
 413};
 414
 415module_platform_driver(mxc_rtc_driver);
 416
 417MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 418MODULE_DESCRIPTION("Real Time Clock (RTC) Driver for i.MX53");
 419MODULE_LICENSE("GPL");
 420