root/drivers/rtc/rtc-cadence.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cdns_rtc_set_enabled
  2. cdns_rtc_get_enabled
  3. cdns_rtc_irq_handler
  4. cdns_rtc_time2reg
  5. cdns_rtc_reg2time
  6. cdns_rtc_read_time
  7. cdns_rtc_set_time
  8. cdns_rtc_alarm_irq_enable
  9. cdns_rtc_read_alarm
  10. cdns_rtc_set_alarm
  11. cdns_rtc_probe
  12. cdns_rtc_remove
  13. cdns_rtc_suspend
  14. cdns_rtc_resume

   1 // SPDX-License-Identifier: GPL-2.0
   2 
   3 /*
   4  * Copyright 2019 Cadence
   5  *
   6  * Authors:
   7  *  Jan Kotas <jank@cadence.com>
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/platform_device.h>
  12 #include <linux/of.h>
  13 #include <linux/io.h>
  14 #include <linux/rtc.h>
  15 #include <linux/clk.h>
  16 #include <linux/bcd.h>
  17 #include <linux/bitfield.h>
  18 #include <linux/interrupt.h>
  19 #include <linux/pm_wakeirq.h>
  20 
  21 /* Registers */
  22 #define CDNS_RTC_CTLR           0x00
  23 #define CDNS_RTC_HMR            0x04
  24 #define CDNS_RTC_TIMR           0x08
  25 #define CDNS_RTC_CALR           0x0C
  26 #define CDNS_RTC_TIMAR          0x10
  27 #define CDNS_RTC_CALAR          0x14
  28 #define CDNS_RTC_AENR           0x18
  29 #define CDNS_RTC_EFLR           0x1C
  30 #define CDNS_RTC_IENR           0x20
  31 #define CDNS_RTC_IDISR          0x24
  32 #define CDNS_RTC_IMSKR          0x28
  33 #define CDNS_RTC_STSR           0x2C
  34 #define CDNS_RTC_KRTCR          0x30
  35 
  36 /* Control */
  37 #define CDNS_RTC_CTLR_TIME      BIT(0)
  38 #define CDNS_RTC_CTLR_CAL       BIT(1)
  39 #define CDNS_RTC_CTLR_TIME_CAL  (CDNS_RTC_CTLR_TIME | CDNS_RTC_CTLR_CAL)
  40 
  41 /* Status */
  42 #define CDNS_RTC_STSR_VT        BIT(0)
  43 #define CDNS_RTC_STSR_VC        BIT(1)
  44 #define CDNS_RTC_STSR_VTA       BIT(2)
  45 #define CDNS_RTC_STSR_VCA       BIT(3)
  46 #define CDNS_RTC_STSR_VT_VC     (CDNS_RTC_STSR_VT | CDNS_RTC_STSR_VC)
  47 #define CDNS_RTC_STSR_VTA_VCA   (CDNS_RTC_STSR_VTA | CDNS_RTC_STSR_VCA)
  48 
  49 /* Keep RTC */
  50 #define CDNS_RTC_KRTCR_KRTC     BIT(0)
  51 
  52 /* Alarm, Event, Interrupt */
  53 #define CDNS_RTC_AEI_HOS        BIT(0)
  54 #define CDNS_RTC_AEI_SEC        BIT(1)
  55 #define CDNS_RTC_AEI_MIN        BIT(2)
  56 #define CDNS_RTC_AEI_HOUR       BIT(3)
  57 #define CDNS_RTC_AEI_DATE       BIT(4)
  58 #define CDNS_RTC_AEI_MNTH       BIT(5)
  59 #define CDNS_RTC_AEI_ALRM       BIT(6)
  60 
  61 /* Time */
  62 #define CDNS_RTC_TIME_H         GENMASK(7, 0)
  63 #define CDNS_RTC_TIME_S         GENMASK(14, 8)
  64 #define CDNS_RTC_TIME_M         GENMASK(22, 16)
  65 #define CDNS_RTC_TIME_HR        GENMASK(29, 24)
  66 #define CDNS_RTC_TIME_PM        BIT(30)
  67 #define CDNS_RTC_TIME_CH        BIT(31)
  68 
  69 /* Calendar */
  70 #define CDNS_RTC_CAL_DAY        GENMASK(2, 0)
  71 #define CDNS_RTC_CAL_M          GENMASK(7, 3)
  72 #define CDNS_RTC_CAL_D          GENMASK(13, 8)
  73 #define CDNS_RTC_CAL_Y          GENMASK(23, 16)
  74 #define CDNS_RTC_CAL_C          GENMASK(29, 24)
  75 #define CDNS_RTC_CAL_CH         BIT(31)
  76 
  77 #define CDNS_RTC_MAX_REGS_TRIES 3
  78 
  79 struct cdns_rtc {
  80         struct rtc_device *rtc_dev;
  81         struct clk *pclk;
  82         struct clk *ref_clk;
  83         void __iomem *regs;
  84         int irq;
  85 };
  86 
  87 static void cdns_rtc_set_enabled(struct cdns_rtc *crtc, bool enabled)
  88 {
  89         u32 reg = enabled ? 0x0 : CDNS_RTC_CTLR_TIME_CAL;
  90 
  91         writel(reg, crtc->regs + CDNS_RTC_CTLR);
  92 }
  93 
  94 static bool cdns_rtc_get_enabled(struct cdns_rtc *crtc)
  95 {
  96         return !(readl(crtc->regs + CDNS_RTC_CTLR) & CDNS_RTC_CTLR_TIME_CAL);
  97 }
  98 
  99 static irqreturn_t cdns_rtc_irq_handler(int irq, void *id)
 100 {
 101         struct device *dev = id;
 102         struct cdns_rtc *crtc = dev_get_drvdata(dev);
 103 
 104         /* Reading the register clears it */
 105         if (!(readl(crtc->regs + CDNS_RTC_EFLR) & CDNS_RTC_AEI_ALRM))
 106                 return IRQ_NONE;
 107 
 108         rtc_update_irq(crtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
 109         return IRQ_HANDLED;
 110 }
 111 
 112 static u32 cdns_rtc_time2reg(struct rtc_time *tm)
 113 {
 114         return FIELD_PREP(CDNS_RTC_TIME_S,  bin2bcd(tm->tm_sec))
 115              | FIELD_PREP(CDNS_RTC_TIME_M,  bin2bcd(tm->tm_min))
 116              | FIELD_PREP(CDNS_RTC_TIME_HR, bin2bcd(tm->tm_hour));
 117 }
 118 
 119 static void cdns_rtc_reg2time(u32 reg, struct rtc_time *tm)
 120 {
 121         tm->tm_sec  = bcd2bin(FIELD_GET(CDNS_RTC_TIME_S, reg));
 122         tm->tm_min  = bcd2bin(FIELD_GET(CDNS_RTC_TIME_M, reg));
 123         tm->tm_hour = bcd2bin(FIELD_GET(CDNS_RTC_TIME_HR, reg));
 124 }
 125 
 126 static int cdns_rtc_read_time(struct device *dev, struct rtc_time *tm)
 127 {
 128         struct cdns_rtc *crtc = dev_get_drvdata(dev);
 129         u32 reg;
 130 
 131         /* If the RTC is disabled, assume the values are invalid */
 132         if (!cdns_rtc_get_enabled(crtc))
 133                 return -EINVAL;
 134 
 135         cdns_rtc_set_enabled(crtc, false);
 136 
 137         reg = readl(crtc->regs + CDNS_RTC_TIMR);
 138         cdns_rtc_reg2time(reg, tm);
 139 
 140         reg = readl(crtc->regs + CDNS_RTC_CALR);
 141         tm->tm_mday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_D, reg));
 142         tm->tm_mon  = bcd2bin(FIELD_GET(CDNS_RTC_CAL_M, reg)) - 1;
 143         tm->tm_year = bcd2bin(FIELD_GET(CDNS_RTC_CAL_Y, reg))
 144                     + bcd2bin(FIELD_GET(CDNS_RTC_CAL_C, reg)) * 100 - 1900;
 145         tm->tm_wday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_DAY, reg)) - 1;
 146 
 147         cdns_rtc_set_enabled(crtc, true);
 148         return 0;
 149 }
 150 
 151 static int cdns_rtc_set_time(struct device *dev, struct rtc_time *tm)
 152 {
 153         struct cdns_rtc *crtc = dev_get_drvdata(dev);
 154         u32 timr, calr, stsr;
 155         int ret = -EIO;
 156         int year = tm->tm_year + 1900;
 157         int tries;
 158 
 159         cdns_rtc_set_enabled(crtc, false);
 160 
 161         timr = cdns_rtc_time2reg(tm);
 162 
 163         calr = FIELD_PREP(CDNS_RTC_CAL_D, bin2bcd(tm->tm_mday))
 164              | FIELD_PREP(CDNS_RTC_CAL_M, bin2bcd(tm->tm_mon + 1))
 165              | FIELD_PREP(CDNS_RTC_CAL_Y, bin2bcd(year % 100))
 166              | FIELD_PREP(CDNS_RTC_CAL_C, bin2bcd(year / 100))
 167              | FIELD_PREP(CDNS_RTC_CAL_DAY, tm->tm_wday + 1);
 168 
 169         /* Update registers, check valid flags */
 170         for (tries = 0; tries < CDNS_RTC_MAX_REGS_TRIES; tries++) {
 171                 writel(timr, crtc->regs + CDNS_RTC_TIMR);
 172                 writel(calr, crtc->regs + CDNS_RTC_CALR);
 173                 stsr = readl(crtc->regs + CDNS_RTC_STSR);
 174 
 175                 if ((stsr & CDNS_RTC_STSR_VT_VC) == CDNS_RTC_STSR_VT_VC) {
 176                         ret = 0;
 177                         break;
 178                 }
 179         }
 180 
 181         cdns_rtc_set_enabled(crtc, true);
 182         return ret;
 183 }
 184 
 185 static int cdns_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 186 {
 187         struct cdns_rtc *crtc = dev_get_drvdata(dev);
 188 
 189         if (enabled) {
 190                 writel((CDNS_RTC_AEI_SEC | CDNS_RTC_AEI_MIN | CDNS_RTC_AEI_HOUR
 191                         | CDNS_RTC_AEI_DATE | CDNS_RTC_AEI_MNTH),
 192                        crtc->regs + CDNS_RTC_AENR);
 193                 writel(CDNS_RTC_AEI_ALRM, crtc->regs + CDNS_RTC_IENR);
 194         } else {
 195                 writel(0, crtc->regs + CDNS_RTC_AENR);
 196                 writel(CDNS_RTC_AEI_ALRM, crtc->regs + CDNS_RTC_IDISR);
 197         }
 198 
 199         return 0;
 200 }
 201 
 202 static int cdns_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 203 {
 204         struct cdns_rtc *crtc = dev_get_drvdata(dev);
 205         u32 reg;
 206 
 207         reg = readl(crtc->regs + CDNS_RTC_TIMAR);
 208         cdns_rtc_reg2time(reg, &alarm->time);
 209 
 210         reg = readl(crtc->regs + CDNS_RTC_CALAR);
 211         alarm->time.tm_mday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_D, reg));
 212         alarm->time.tm_mon  = bcd2bin(FIELD_GET(CDNS_RTC_CAL_M, reg)) - 1;
 213 
 214         return 0;
 215 }
 216 
 217 static int cdns_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 218 {
 219         struct cdns_rtc *crtc = dev_get_drvdata(dev);
 220         int ret = -EIO;
 221         int tries;
 222         u32 timar, calar, stsr;
 223 
 224         cdns_rtc_alarm_irq_enable(dev, 0);
 225 
 226         timar = cdns_rtc_time2reg(&alarm->time);
 227         calar = FIELD_PREP(CDNS_RTC_CAL_D, bin2bcd(alarm->time.tm_mday))
 228               | FIELD_PREP(CDNS_RTC_CAL_M, bin2bcd(alarm->time.tm_mon + 1));
 229 
 230         /* Update registers, check valid alarm flags */
 231         for (tries = 0; tries < CDNS_RTC_MAX_REGS_TRIES; tries++) {
 232                 writel(timar, crtc->regs + CDNS_RTC_TIMAR);
 233                 writel(calar, crtc->regs + CDNS_RTC_CALAR);
 234                 stsr = readl(crtc->regs + CDNS_RTC_STSR);
 235 
 236                 if ((stsr & CDNS_RTC_STSR_VTA_VCA) == CDNS_RTC_STSR_VTA_VCA) {
 237                         ret = 0;
 238                         break;
 239                 }
 240         }
 241 
 242         if (!ret)
 243                 cdns_rtc_alarm_irq_enable(dev, alarm->enabled);
 244         return ret;
 245 }
 246 
 247 static const struct rtc_class_ops cdns_rtc_ops = {
 248         .read_time      = cdns_rtc_read_time,
 249         .set_time       = cdns_rtc_set_time,
 250         .read_alarm     = cdns_rtc_read_alarm,
 251         .set_alarm      = cdns_rtc_set_alarm,
 252         .alarm_irq_enable = cdns_rtc_alarm_irq_enable,
 253 };
 254 
 255 static int cdns_rtc_probe(struct platform_device *pdev)
 256 {
 257         struct cdns_rtc *crtc;
 258         struct resource *res;
 259         int ret;
 260         unsigned long ref_clk_freq;
 261 
 262         crtc = devm_kzalloc(&pdev->dev, sizeof(*crtc), GFP_KERNEL);
 263         if (!crtc)
 264                 return -ENOMEM;
 265 
 266         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 267         crtc->regs = devm_ioremap_resource(&pdev->dev, res);
 268         if (IS_ERR(crtc->regs))
 269                 return PTR_ERR(crtc->regs);
 270 
 271         crtc->irq = platform_get_irq(pdev, 0);
 272         if (crtc->irq < 0)
 273                 return -EINVAL;
 274 
 275         crtc->pclk = devm_clk_get(&pdev->dev, "pclk");
 276         if (IS_ERR(crtc->pclk)) {
 277                 ret = PTR_ERR(crtc->pclk);
 278                 dev_err(&pdev->dev,
 279                         "Failed to retrieve the peripheral clock, %d\n", ret);
 280                 return ret;
 281         }
 282 
 283         crtc->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
 284         if (IS_ERR(crtc->ref_clk)) {
 285                 ret = PTR_ERR(crtc->ref_clk);
 286                 dev_err(&pdev->dev,
 287                         "Failed to retrieve the reference clock, %d\n", ret);
 288                 return ret;
 289         }
 290 
 291         crtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
 292         if (IS_ERR(crtc->rtc_dev))
 293                 return PTR_ERR(crtc->rtc_dev);
 294 
 295         platform_set_drvdata(pdev, crtc);
 296 
 297         ret = clk_prepare_enable(crtc->pclk);
 298         if (ret) {
 299                 dev_err(&pdev->dev,
 300                         "Failed to enable the peripheral clock, %d\n", ret);
 301                 return ret;
 302         }
 303 
 304         ret = clk_prepare_enable(crtc->ref_clk);
 305         if (ret) {
 306                 dev_err(&pdev->dev,
 307                         "Failed to enable the reference clock, %d\n", ret);
 308                 goto err_disable_pclk;
 309         }
 310 
 311         ref_clk_freq = clk_get_rate(crtc->ref_clk);
 312         if ((ref_clk_freq != 1) && (ref_clk_freq != 100)) {
 313                 dev_err(&pdev->dev,
 314                         "Invalid reference clock frequency %lu Hz.\n",
 315                         ref_clk_freq);
 316                 ret = -EINVAL;
 317                 goto err_disable_ref_clk;
 318         }
 319 
 320         ret = devm_request_irq(&pdev->dev, crtc->irq,
 321                                cdns_rtc_irq_handler, 0,
 322                                dev_name(&pdev->dev), &pdev->dev);
 323         if (ret) {
 324                 dev_err(&pdev->dev,
 325                         "Failed to request interrupt for the device, %d\n",
 326                         ret);
 327                 goto err_disable_ref_clk;
 328         }
 329 
 330         /* The RTC supports 01.01.1900 - 31.12.2999 */
 331         crtc->rtc_dev->range_min = mktime64(1900,  1,  1,  0,  0,  0);
 332         crtc->rtc_dev->range_max = mktime64(2999, 12, 31, 23, 59, 59);
 333 
 334         crtc->rtc_dev->ops = &cdns_rtc_ops;
 335         device_init_wakeup(&pdev->dev, true);
 336 
 337         /* Always use 24-hour mode and keep the RTC values */
 338         writel(0, crtc->regs + CDNS_RTC_HMR);
 339         writel(CDNS_RTC_KRTCR_KRTC, crtc->regs + CDNS_RTC_KRTCR);
 340 
 341         ret = rtc_register_device(crtc->rtc_dev);
 342         if (ret)
 343                 goto err_disable_wakeup;
 344 
 345         return 0;
 346 
 347 err_disable_wakeup:
 348         device_init_wakeup(&pdev->dev, false);
 349 
 350 err_disable_ref_clk:
 351         clk_disable_unprepare(crtc->ref_clk);
 352 
 353 err_disable_pclk:
 354         clk_disable_unprepare(crtc->pclk);
 355 
 356         return ret;
 357 }
 358 
 359 static int cdns_rtc_remove(struct platform_device *pdev)
 360 {
 361         struct cdns_rtc *crtc = platform_get_drvdata(pdev);
 362 
 363         cdns_rtc_alarm_irq_enable(&pdev->dev, 0);
 364         device_init_wakeup(&pdev->dev, 0);
 365 
 366         clk_disable_unprepare(crtc->pclk);
 367         clk_disable_unprepare(crtc->ref_clk);
 368 
 369         return 0;
 370 }
 371 
 372 #ifdef CONFIG_PM_SLEEP
 373 static int cdns_rtc_suspend(struct device *dev)
 374 {
 375         struct cdns_rtc *crtc = dev_get_drvdata(dev);
 376 
 377         if (device_may_wakeup(dev))
 378                 enable_irq_wake(crtc->irq);
 379 
 380         return 0;
 381 }
 382 
 383 static int cdns_rtc_resume(struct device *dev)
 384 {
 385         struct cdns_rtc *crtc = dev_get_drvdata(dev);
 386 
 387         if (device_may_wakeup(dev))
 388                 disable_irq_wake(crtc->irq);
 389 
 390         return 0;
 391 }
 392 #endif
 393 
 394 static SIMPLE_DEV_PM_OPS(cdns_rtc_pm_ops, cdns_rtc_suspend, cdns_rtc_resume);
 395 
 396 static const struct of_device_id cdns_rtc_of_match[] = {
 397         { .compatible = "cdns,rtc-r109v3" },
 398         { },
 399 };
 400 MODULE_DEVICE_TABLE(of, cdns_rtc_of_match);
 401 
 402 static struct platform_driver cdns_rtc_driver = {
 403         .driver = {
 404                 .name = "cdns-rtc",
 405                 .of_match_table = cdns_rtc_of_match,
 406                 .pm = &cdns_rtc_pm_ops,
 407         },
 408         .probe = cdns_rtc_probe,
 409         .remove = cdns_rtc_remove,
 410 };
 411 module_platform_driver(cdns_rtc_driver);
 412 
 413 MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
 414 MODULE_DESCRIPTION("Cadence RTC driver");
 415 MODULE_LICENSE("GPL v2");
 416 MODULE_ALIAS("platform:cdns-rtc");

/* [<][>][^][v][top][bottom][index][help] */