linux/drivers/rtc/rtc-snvs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2//
   3// Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
   4
   5#include <linux/init.h>
   6#include <linux/io.h>
   7#include <linux/kernel.h>
   8#include <linux/module.h>
   9#include <linux/of.h>
  10#include <linux/of_device.h>
  11#include <linux/platform_device.h>
  12#include <linux/pm_wakeirq.h>
  13#include <linux/rtc.h>
  14#include <linux/clk.h>
  15#include <linux/mfd/syscon.h>
  16#include <linux/regmap.h>
  17
  18#define SNVS_LPREGISTER_OFFSET  0x34
  19
  20/* These register offsets are relative to LP (Low Power) range */
  21#define SNVS_LPCR               0x04
  22#define SNVS_LPSR               0x18
  23#define SNVS_LPSRTCMR           0x1c
  24#define SNVS_LPSRTCLR           0x20
  25#define SNVS_LPTAR              0x24
  26#define SNVS_LPPGDR             0x30
  27
  28#define SNVS_LPCR_SRTC_ENV      (1 << 0)
  29#define SNVS_LPCR_LPTA_EN       (1 << 1)
  30#define SNVS_LPCR_LPWUI_EN      (1 << 3)
  31#define SNVS_LPSR_LPTA          (1 << 0)
  32
  33#define SNVS_LPPGDR_INIT        0x41736166
  34#define CNTR_TO_SECS_SH         15
  35
  36struct snvs_rtc_data {
  37        struct rtc_device *rtc;
  38        struct regmap *regmap;
  39        int offset;
  40        int irq;
  41        struct clk *clk;
  42};
  43
  44/* Read 64 bit timer register, which could be in inconsistent state */
  45static u64 rtc_read_lpsrt(struct snvs_rtc_data *data)
  46{
  47        u32 msb, lsb;
  48
  49        regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &msb);
  50        regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &lsb);
  51        return (u64)msb << 32 | lsb;
  52}
  53
  54/* Read the secure real time counter, taking care to deal with the cases of the
  55 * counter updating while being read.
  56 */
  57static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
  58{
  59        u64 read1, read2;
  60        unsigned int timeout = 100;
  61
  62        /* As expected, the registers might update between the read of the LSB
  63         * reg and the MSB reg.  It's also possible that one register might be
  64         * in partially modified state as well.
  65         */
  66        read1 = rtc_read_lpsrt(data);
  67        do {
  68                read2 = read1;
  69                read1 = rtc_read_lpsrt(data);
  70        } while (read1 != read2 && --timeout);
  71        if (!timeout)
  72                dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
  73
  74        /* Convert 47-bit counter to 32-bit raw second count */
  75        return (u32) (read1 >> CNTR_TO_SECS_SH);
  76}
  77
  78/* Just read the lsb from the counter, dealing with inconsistent state */
  79static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb)
  80{
  81        u32 count1, count2;
  82        unsigned int timeout = 100;
  83
  84        regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
  85        do {
  86                count2 = count1;
  87                regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
  88        } while (count1 != count2 && --timeout);
  89        if (!timeout) {
  90                dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
  91                return -ETIMEDOUT;
  92        }
  93
  94        *lsb = count1;
  95        return 0;
  96}
  97
  98static int rtc_write_sync_lp(struct snvs_rtc_data *data)
  99{
 100        u32 count1, count2;
 101        u32 elapsed;
 102        unsigned int timeout = 1000;
 103        int ret;
 104
 105        ret = rtc_read_lp_counter_lsb(data, &count1);
 106        if (ret)
 107                return ret;
 108
 109        /* Wait for 3 CKIL cycles, about 61.0-91.5 µs */
 110        do {
 111                ret = rtc_read_lp_counter_lsb(data, &count2);
 112                if (ret)
 113                        return ret;
 114                elapsed = count2 - count1; /* wrap around _is_ handled! */
 115        } while (elapsed < 3 && --timeout);
 116        if (!timeout) {
 117                dev_err(&data->rtc->dev, "Timeout waiting for LPSRT Counter to change\n");
 118                return -ETIMEDOUT;
 119        }
 120        return 0;
 121}
 122
 123static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
 124{
 125        int timeout = 1000;
 126        u32 lpcr;
 127
 128        regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_SRTC_ENV,
 129                           enable ? SNVS_LPCR_SRTC_ENV : 0);
 130
 131        while (--timeout) {
 132                regmap_read(data->regmap, data->offset + SNVS_LPCR, &lpcr);
 133
 134                if (enable) {
 135                        if (lpcr & SNVS_LPCR_SRTC_ENV)
 136                                break;
 137                } else {
 138                        if (!(lpcr & SNVS_LPCR_SRTC_ENV))
 139                                break;
 140                }
 141        }
 142
 143        if (!timeout)
 144                return -ETIMEDOUT;
 145
 146        return 0;
 147}
 148
 149static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
 150{
 151        struct snvs_rtc_data *data = dev_get_drvdata(dev);
 152        unsigned long time = rtc_read_lp_counter(data);
 153
 154        rtc_time64_to_tm(time, tm);
 155
 156        return 0;
 157}
 158
 159static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
 160{
 161        struct snvs_rtc_data *data = dev_get_drvdata(dev);
 162        unsigned long time = rtc_tm_to_time64(tm);
 163        int ret;
 164
 165        /* Disable RTC first */
 166        ret = snvs_rtc_enable(data, false);
 167        if (ret)
 168                return ret;
 169
 170        /* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
 171        regmap_write(data->regmap, data->offset + SNVS_LPSRTCLR, time << CNTR_TO_SECS_SH);
 172        regmap_write(data->regmap, data->offset + SNVS_LPSRTCMR, time >> (32 - CNTR_TO_SECS_SH));
 173
 174        /* Enable RTC again */
 175        ret = snvs_rtc_enable(data, true);
 176
 177        return ret;
 178}
 179
 180static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 181{
 182        struct snvs_rtc_data *data = dev_get_drvdata(dev);
 183        u32 lptar, lpsr;
 184
 185        regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar);
 186        rtc_time64_to_tm(lptar, &alrm->time);
 187
 188        regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
 189        alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
 190
 191        return 0;
 192}
 193
 194static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
 195{
 196        struct snvs_rtc_data *data = dev_get_drvdata(dev);
 197
 198        regmap_update_bits(data->regmap, data->offset + SNVS_LPCR,
 199                           (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
 200                           enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
 201
 202        return rtc_write_sync_lp(data);
 203}
 204
 205static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 206{
 207        struct snvs_rtc_data *data = dev_get_drvdata(dev);
 208        unsigned long time = rtc_tm_to_time64(&alrm->time);
 209        int ret;
 210
 211        regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
 212        ret = rtc_write_sync_lp(data);
 213        if (ret)
 214                return ret;
 215        regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
 216
 217        /* Clear alarm interrupt status bit */
 218        regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA);
 219
 220        return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
 221}
 222
 223static const struct rtc_class_ops snvs_rtc_ops = {
 224        .read_time = snvs_rtc_read_time,
 225        .set_time = snvs_rtc_set_time,
 226        .read_alarm = snvs_rtc_read_alarm,
 227        .set_alarm = snvs_rtc_set_alarm,
 228        .alarm_irq_enable = snvs_rtc_alarm_irq_enable,
 229};
 230
 231static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)
 232{
 233        struct device *dev = dev_id;
 234        struct snvs_rtc_data *data = dev_get_drvdata(dev);
 235        u32 lpsr;
 236        u32 events = 0;
 237
 238        if (data->clk)
 239                clk_enable(data->clk);
 240
 241        regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
 242
 243        if (lpsr & SNVS_LPSR_LPTA) {
 244                events |= (RTC_AF | RTC_IRQF);
 245
 246                /* RTC alarm should be one-shot */
 247                snvs_rtc_alarm_irq_enable(dev, 0);
 248
 249                rtc_update_irq(data->rtc, 1, events);
 250        }
 251
 252        /* clear interrupt status */
 253        regmap_write(data->regmap, data->offset + SNVS_LPSR, lpsr);
 254
 255        if (data->clk)
 256                clk_disable(data->clk);
 257
 258        return events ? IRQ_HANDLED : IRQ_NONE;
 259}
 260
 261static const struct regmap_config snvs_rtc_config = {
 262        .reg_bits = 32,
 263        .val_bits = 32,
 264        .reg_stride = 4,
 265};
 266
 267static int snvs_rtc_probe(struct platform_device *pdev)
 268{
 269        struct snvs_rtc_data *data;
 270        int ret;
 271        void __iomem *mmio;
 272
 273        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 274        if (!data)
 275                return -ENOMEM;
 276
 277        data->rtc = devm_rtc_allocate_device(&pdev->dev);
 278        if (IS_ERR(data->rtc))
 279                return PTR_ERR(data->rtc);
 280
 281        data->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap");
 282
 283        if (IS_ERR(data->regmap)) {
 284                dev_warn(&pdev->dev, "snvs rtc: you use old dts file, please update it\n");
 285
 286                mmio = devm_platform_ioremap_resource(pdev, 0);
 287                if (IS_ERR(mmio))
 288                        return PTR_ERR(mmio);
 289
 290                data->regmap = devm_regmap_init_mmio(&pdev->dev, mmio, &snvs_rtc_config);
 291        } else {
 292                data->offset = SNVS_LPREGISTER_OFFSET;
 293                of_property_read_u32(pdev->dev.of_node, "offset", &data->offset);
 294        }
 295
 296        if (IS_ERR(data->regmap)) {
 297                dev_err(&pdev->dev, "Can't find snvs syscon\n");
 298                return -ENODEV;
 299        }
 300
 301        data->irq = platform_get_irq(pdev, 0);
 302        if (data->irq < 0)
 303                return data->irq;
 304
 305        data->clk = devm_clk_get(&pdev->dev, "snvs-rtc");
 306        if (IS_ERR(data->clk)) {
 307                data->clk = NULL;
 308        } else {
 309                ret = clk_prepare_enable(data->clk);
 310                if (ret) {
 311                        dev_err(&pdev->dev,
 312                                "Could not prepare or enable the snvs clock\n");
 313                        return ret;
 314                }
 315        }
 316
 317        platform_set_drvdata(pdev, data);
 318
 319        /* Initialize glitch detect */
 320        regmap_write(data->regmap, data->offset + SNVS_LPPGDR, SNVS_LPPGDR_INIT);
 321
 322        /* Clear interrupt status */
 323        regmap_write(data->regmap, data->offset + SNVS_LPSR, 0xffffffff);
 324
 325        /* Enable RTC */
 326        ret = snvs_rtc_enable(data, true);
 327        if (ret) {
 328                dev_err(&pdev->dev, "failed to enable rtc %d\n", ret);
 329                goto error_rtc_device_register;
 330        }
 331
 332        device_init_wakeup(&pdev->dev, true);
 333        ret = dev_pm_set_wake_irq(&pdev->dev, data->irq);
 334        if (ret)
 335                dev_err(&pdev->dev, "failed to enable irq wake\n");
 336
 337        ret = devm_request_irq(&pdev->dev, data->irq, snvs_rtc_irq_handler,
 338                               IRQF_SHARED, "rtc alarm", &pdev->dev);
 339        if (ret) {
 340                dev_err(&pdev->dev, "failed to request irq %d: %d\n",
 341                        data->irq, ret);
 342                goto error_rtc_device_register;
 343        }
 344
 345        data->rtc->ops = &snvs_rtc_ops;
 346        data->rtc->range_max = U32_MAX;
 347        ret = rtc_register_device(data->rtc);
 348        if (ret) {
 349                dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);
 350                goto error_rtc_device_register;
 351        }
 352
 353        return 0;
 354
 355error_rtc_device_register:
 356        if (data->clk)
 357                clk_disable_unprepare(data->clk);
 358
 359        return ret;
 360}
 361
 362static int __maybe_unused snvs_rtc_suspend_noirq(struct device *dev)
 363{
 364        struct snvs_rtc_data *data = dev_get_drvdata(dev);
 365
 366        if (data->clk)
 367                clk_disable_unprepare(data->clk);
 368
 369        return 0;
 370}
 371
 372static int __maybe_unused snvs_rtc_resume_noirq(struct device *dev)
 373{
 374        struct snvs_rtc_data *data = dev_get_drvdata(dev);
 375
 376        if (data->clk)
 377                return clk_prepare_enable(data->clk);
 378
 379        return 0;
 380}
 381
 382static const struct dev_pm_ops snvs_rtc_pm_ops = {
 383        SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(snvs_rtc_suspend_noirq, snvs_rtc_resume_noirq)
 384};
 385
 386static const struct of_device_id snvs_dt_ids[] = {
 387        { .compatible = "fsl,sec-v4.0-mon-rtc-lp", },
 388        { /* sentinel */ }
 389};
 390MODULE_DEVICE_TABLE(of, snvs_dt_ids);
 391
 392static struct platform_driver snvs_rtc_driver = {
 393        .driver = {
 394                .name   = "snvs_rtc",
 395                .pm     = &snvs_rtc_pm_ops,
 396                .of_match_table = snvs_dt_ids,
 397        },
 398        .probe          = snvs_rtc_probe,
 399};
 400module_platform_driver(snvs_rtc_driver);
 401
 402MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 403MODULE_DESCRIPTION("Freescale SNVS RTC Driver");
 404MODULE_LICENSE("GPL");
 405