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