0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <linux/io.h>
0023 #include <linux/clk.h>
0024 #include <linux/delay.h>
0025 #include <linux/module.h>
0026 #include <linux/platform_device.h>
0027 #include <linux/pm_wakeirq.h>
0028 #include <linux/rtc.h>
0029 #include <linux/sched.h>
0030 #include <linux/spinlock.h>
0031 #include <linux/workqueue.h>
0032 #include <linux/of.h>
0033
0034
0035
0036 #define DTCMR 0x00
0037 #define DTCLR 0x04
0038
0039 #define DCAMR 0x08
0040 #define DCALR 0x0c
0041 #define DCAMR_UNSET 0xFFFFFFFF
0042
0043 #define DCR 0x10
0044 #define DCR_TDCHL (1 << 30)
0045 #define DCR_TDCSL (1 << 29)
0046 #define DCR_KSSL (1 << 27)
0047 #define DCR_MCHL (1 << 20)
0048 #define DCR_MCSL (1 << 19)
0049 #define DCR_TCHL (1 << 18)
0050 #define DCR_TCSL (1 << 17)
0051 #define DCR_FSHL (1 << 16)
0052 #define DCR_TCE (1 << 3)
0053 #define DCR_MCE (1 << 2)
0054
0055 #define DSR 0x14
0056 #define DSR_WTD (1 << 23)
0057 #define DSR_ETBD (1 << 22)
0058 #define DSR_ETAD (1 << 21)
0059 #define DSR_EBD (1 << 20)
0060 #define DSR_SAD (1 << 19)
0061 #define DSR_TTD (1 << 18)
0062 #define DSR_CTD (1 << 17)
0063 #define DSR_VTD (1 << 16)
0064 #define DSR_WBF (1 << 10)
0065 #define DSR_WNF (1 << 9)
0066 #define DSR_WCF (1 << 8)
0067 #define DSR_WEF (1 << 7)
0068 #define DSR_CAF (1 << 4)
0069 #define DSR_MCO (1 << 3)
0070 #define DSR_TCO (1 << 2)
0071 #define DSR_NVF (1 << 1)
0072 #define DSR_SVF (1 << 0)
0073
0074 #define DIER 0x18
0075 #define DIER_WNIE (1 << 9)
0076 #define DIER_WCIE (1 << 8)
0077 #define DIER_WEIE (1 << 7)
0078 #define DIER_CAIE (1 << 4)
0079 #define DIER_SVIE (1 << 0)
0080
0081 #define DMCR 0x1c
0082
0083 #define DTCR 0x28
0084 #define DTCR_MOE (1 << 9)
0085 #define DTCR_TOE (1 << 8)
0086 #define DTCR_WTE (1 << 7)
0087 #define DTCR_ETBE (1 << 6)
0088 #define DTCR_ETAE (1 << 5)
0089 #define DTCR_EBE (1 << 4)
0090 #define DTCR_SAIE (1 << 3)
0091 #define DTCR_TTE (1 << 2)
0092 #define DTCR_CTE (1 << 1)
0093 #define DTCR_VTE (1 << 0)
0094
0095 #define DGPR 0x3c
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 struct imxdi_dev {
0110 struct platform_device *pdev;
0111 struct rtc_device *rtc;
0112 void __iomem *ioaddr;
0113 struct clk *clk;
0114 u32 dsr;
0115 spinlock_t irq_lock;
0116 wait_queue_head_t write_wait;
0117 struct mutex write_mutex;
0118 struct work_struct work;
0119 };
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 static void di_write_busy_wait(const struct imxdi_dev *imxdi, u32 val,
0172 unsigned reg)
0173 {
0174
0175 writel(val, imxdi->ioaddr + reg);
0176
0177
0178
0179
0180
0181 usleep_range(130, 200);
0182 }
0183
0184 static void di_report_tamper_info(struct imxdi_dev *imxdi, u32 dsr)
0185 {
0186 u32 dtcr;
0187
0188 dtcr = readl(imxdi->ioaddr + DTCR);
0189
0190 dev_emerg(&imxdi->pdev->dev, "DryIce tamper event detected\n");
0191
0192 if (dsr & DSR_VTD)
0193 dev_emerg(&imxdi->pdev->dev, "%sVoltage Tamper Event\n",
0194 dtcr & DTCR_VTE ? "" : "Spurious ");
0195
0196 if (dsr & DSR_CTD)
0197 dev_emerg(&imxdi->pdev->dev, "%s32768 Hz Clock Tamper Event\n",
0198 dtcr & DTCR_CTE ? "" : "Spurious ");
0199
0200 if (dsr & DSR_TTD)
0201 dev_emerg(&imxdi->pdev->dev, "%sTemperature Tamper Event\n",
0202 dtcr & DTCR_TTE ? "" : "Spurious ");
0203
0204 if (dsr & DSR_SAD)
0205 dev_emerg(&imxdi->pdev->dev,
0206 "%sSecure Controller Alarm Event\n",
0207 dtcr & DTCR_SAIE ? "" : "Spurious ");
0208
0209 if (dsr & DSR_EBD)
0210 dev_emerg(&imxdi->pdev->dev, "%sExternal Boot Tamper Event\n",
0211 dtcr & DTCR_EBE ? "" : "Spurious ");
0212
0213 if (dsr & DSR_ETAD)
0214 dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper A Event\n",
0215 dtcr & DTCR_ETAE ? "" : "Spurious ");
0216
0217 if (dsr & DSR_ETBD)
0218 dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper B Event\n",
0219 dtcr & DTCR_ETBE ? "" : "Spurious ");
0220
0221 if (dsr & DSR_WTD)
0222 dev_emerg(&imxdi->pdev->dev, "%sWire-mesh Tamper Event\n",
0223 dtcr & DTCR_WTE ? "" : "Spurious ");
0224
0225 if (dsr & DSR_MCO)
0226 dev_emerg(&imxdi->pdev->dev,
0227 "%sMonotonic-counter Overflow Event\n",
0228 dtcr & DTCR_MOE ? "" : "Spurious ");
0229
0230 if (dsr & DSR_TCO)
0231 dev_emerg(&imxdi->pdev->dev, "%sTimer-counter Overflow Event\n",
0232 dtcr & DTCR_TOE ? "" : "Spurious ");
0233 }
0234
0235 static void di_what_is_to_be_done(struct imxdi_dev *imxdi,
0236 const char *power_supply)
0237 {
0238 dev_emerg(&imxdi->pdev->dev, "Please cycle the %s power supply in order to get the DryIce/RTC unit working again\n",
0239 power_supply);
0240 }
0241
0242 static int di_handle_failure_state(struct imxdi_dev *imxdi, u32 dsr)
0243 {
0244 u32 dcr;
0245
0246 dev_dbg(&imxdi->pdev->dev, "DSR register reports: %08X\n", dsr);
0247
0248
0249 di_report_tamper_info(imxdi, dsr);
0250
0251 dcr = readl(imxdi->ioaddr + DCR);
0252
0253 if (dcr & DCR_FSHL) {
0254
0255 di_what_is_to_be_done(imxdi, "battery");
0256 return -ENODEV;
0257 }
0258
0259
0260
0261
0262 di_what_is_to_be_done(imxdi, "main");
0263
0264 return -ENODEV;
0265 }
0266
0267 static int di_handle_valid_state(struct imxdi_dev *imxdi, u32 dsr)
0268 {
0269
0270 di_write_busy_wait(imxdi, DCAMR_UNSET, DCAMR);
0271 di_write_busy_wait(imxdi, 0, DCALR);
0272
0273
0274 if (dsr & DSR_CAF)
0275 di_write_busy_wait(imxdi, DSR_CAF, DSR);
0276
0277 return 0;
0278 }
0279
0280 static int di_handle_invalid_state(struct imxdi_dev *imxdi, u32 dsr)
0281 {
0282 u32 dcr, sec;
0283
0284
0285
0286
0287
0288 di_write_busy_wait(imxdi, 0x00000000, DTCR);
0289
0290 di_write_busy_wait(imxdi, DCR_TDCSL, DCR);
0291
0292 sec = readl(imxdi->ioaddr + DTCMR);
0293 if (sec != 0)
0294 dev_warn(&imxdi->pdev->dev,
0295 "The security violation has happened at %u seconds\n",
0296 sec);
0297
0298
0299
0300
0301 dcr = readl(imxdi->ioaddr + DCR);
0302 if (!(dcr & DCR_TCE)) {
0303 if (dcr & DCR_TCHL) {
0304
0305 di_what_is_to_be_done(imxdi, "battery");
0306 return -ENODEV;
0307 }
0308 if (dcr & DCR_TCSL) {
0309 di_what_is_to_be_done(imxdi, "main");
0310 return -ENODEV;
0311 }
0312 }
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325 di_write_busy_wait(imxdi, DSR_NVF, DSR);
0326
0327 di_write_busy_wait(imxdi, DSR_TCO, DSR);
0328
0329 di_write_busy_wait(imxdi, dcr | DCR_TCE, DCR);
0330
0331 di_write_busy_wait(imxdi, sec, DTCMR);
0332
0333
0334 return di_handle_valid_state(imxdi, __raw_readl(imxdi->ioaddr + DSR));
0335 }
0336
0337 static int di_handle_invalid_and_failure_state(struct imxdi_dev *imxdi, u32 dsr)
0338 {
0339 u32 dcr;
0340
0341
0342
0343
0344
0345
0346 if (dsr & (DSR_WTD | DSR_ETBD | DSR_ETAD | DSR_EBD | DSR_SAD |
0347 DSR_TTD | DSR_CTD | DSR_VTD | DSR_MCO | DSR_TCO)) {
0348 dcr = __raw_readl(imxdi->ioaddr + DCR);
0349 if (dcr & DCR_TDCHL) {
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361 di_what_is_to_be_done(imxdi, "battery");
0362 return -ENODEV;
0363 }
0364 if (dcr & DCR_TDCSL) {
0365
0366 di_what_is_to_be_done(imxdi, "main");
0367 return -ENODEV;
0368 }
0369 }
0370
0371
0372 di_write_busy_wait(imxdi, 0x00000000, DTCR);
0373
0374
0375 di_write_busy_wait(imxdi, dsr & (DSR_WTD | DSR_ETBD | DSR_ETAD |
0376 DSR_EBD | DSR_SAD | DSR_TTD | DSR_CTD | DSR_VTD |
0377 DSR_MCO | DSR_TCO), DSR);
0378
0379 dsr = readl(imxdi->ioaddr + DSR);
0380 if ((dsr & ~(DSR_NVF | DSR_SVF | DSR_WBF | DSR_WNF |
0381 DSR_WCF | DSR_WEF)) != 0)
0382 dev_warn(&imxdi->pdev->dev,
0383 "There are still some sources of pain in DSR: %08x!\n",
0384 dsr & ~(DSR_NVF | DSR_SVF | DSR_WBF | DSR_WNF |
0385 DSR_WCF | DSR_WEF));
0386
0387
0388
0389
0390
0391 di_write_busy_wait(imxdi, DSR_SVF, DSR);
0392
0393
0394 dsr = readl(imxdi->ioaddr + DSR);
0395 if (dsr & DSR_SVF) {
0396 dev_crit(&imxdi->pdev->dev,
0397 "Cannot clear the security violation flag. We are ending up in an endless loop!\n");
0398
0399 di_what_is_to_be_done(imxdi, "battery");
0400 return -ENODEV;
0401 }
0402
0403
0404
0405
0406
0407 return di_handle_invalid_state(imxdi, dsr);
0408 }
0409
0410 static int di_handle_state(struct imxdi_dev *imxdi)
0411 {
0412 int rc;
0413 u32 dsr;
0414
0415 dsr = readl(imxdi->ioaddr + DSR);
0416
0417 switch (dsr & (DSR_NVF | DSR_SVF)) {
0418 case DSR_NVF:
0419 dev_warn(&imxdi->pdev->dev, "Invalid stated unit detected\n");
0420 rc = di_handle_invalid_state(imxdi, dsr);
0421 break;
0422 case DSR_SVF:
0423 dev_warn(&imxdi->pdev->dev, "Failure stated unit detected\n");
0424 rc = di_handle_failure_state(imxdi, dsr);
0425 break;
0426 case DSR_NVF | DSR_SVF:
0427 dev_warn(&imxdi->pdev->dev,
0428 "Failure+Invalid stated unit detected\n");
0429 rc = di_handle_invalid_and_failure_state(imxdi, dsr);
0430 break;
0431 default:
0432 dev_notice(&imxdi->pdev->dev, "Unlocked unit detected\n");
0433 rc = di_handle_valid_state(imxdi, dsr);
0434 }
0435
0436 return rc;
0437 }
0438
0439
0440
0441
0442 static void di_int_enable(struct imxdi_dev *imxdi, u32 intr)
0443 {
0444 unsigned long flags;
0445
0446 spin_lock_irqsave(&imxdi->irq_lock, flags);
0447 writel(readl(imxdi->ioaddr + DIER) | intr,
0448 imxdi->ioaddr + DIER);
0449 spin_unlock_irqrestore(&imxdi->irq_lock, flags);
0450 }
0451
0452
0453
0454
0455 static void di_int_disable(struct imxdi_dev *imxdi, u32 intr)
0456 {
0457 unsigned long flags;
0458
0459 spin_lock_irqsave(&imxdi->irq_lock, flags);
0460 writel(readl(imxdi->ioaddr + DIER) & ~intr,
0461 imxdi->ioaddr + DIER);
0462 spin_unlock_irqrestore(&imxdi->irq_lock, flags);
0463 }
0464
0465
0466
0467
0468
0469
0470
0471
0472 static void clear_write_error(struct imxdi_dev *imxdi)
0473 {
0474 int cnt;
0475
0476 dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n");
0477
0478
0479 writel(DSR_WEF, imxdi->ioaddr + DSR);
0480
0481
0482 for (cnt = 0; cnt < 1000; cnt++) {
0483 if ((readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0)
0484 return;
0485 udelay(10);
0486 }
0487 dev_err(&imxdi->pdev->dev,
0488 "ERROR: Cannot clear write-error flag!\n");
0489 }
0490
0491
0492
0493
0494
0495
0496
0497 static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg)
0498 {
0499 int ret;
0500 int rc = 0;
0501
0502
0503 mutex_lock(&imxdi->write_mutex);
0504
0505
0506 di_int_enable(imxdi, DIER_WCIE);
0507
0508 imxdi->dsr = 0;
0509
0510
0511 writel(val, imxdi->ioaddr + reg);
0512
0513
0514 ret = wait_event_interruptible_timeout(imxdi->write_wait,
0515 imxdi->dsr & (DSR_WCF | DSR_WEF), msecs_to_jiffies(1));
0516 if (ret < 0) {
0517 rc = ret;
0518 goto out;
0519 } else if (ret == 0) {
0520 dev_warn(&imxdi->pdev->dev,
0521 "Write-wait timeout "
0522 "val = 0x%08x reg = 0x%08x\n", val, reg);
0523 }
0524
0525
0526 if (imxdi->dsr & DSR_WEF) {
0527 clear_write_error(imxdi);
0528 rc = -EIO;
0529 }
0530
0531 out:
0532 mutex_unlock(&imxdi->write_mutex);
0533
0534 return rc;
0535 }
0536
0537
0538
0539
0540 static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm)
0541 {
0542 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
0543 unsigned long now;
0544
0545 now = readl(imxdi->ioaddr + DTCMR);
0546 rtc_time64_to_tm(now, tm);
0547
0548 return 0;
0549 }
0550
0551
0552
0553
0554
0555 static int dryice_rtc_set_time(struct device *dev, struct rtc_time *tm)
0556 {
0557 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
0558 u32 dcr, dsr;
0559 int rc;
0560
0561 dcr = readl(imxdi->ioaddr + DCR);
0562 dsr = readl(imxdi->ioaddr + DSR);
0563
0564 if (!(dcr & DCR_TCE) || (dsr & DSR_SVF)) {
0565 if (dcr & DCR_TCHL) {
0566
0567 di_what_is_to_be_done(imxdi, "battery");
0568 return -EPERM;
0569 }
0570 if ((dcr & DCR_TCSL) || (dsr & DSR_SVF)) {
0571
0572 di_what_is_to_be_done(imxdi, "main");
0573 return -EPERM;
0574 }
0575 }
0576
0577
0578 rc = di_write_wait(imxdi, 0, DTCLR);
0579 if (rc != 0)
0580 return rc;
0581
0582 rc = di_write_wait(imxdi, rtc_tm_to_time64(tm), DTCMR);
0583 if (rc != 0)
0584 return rc;
0585
0586 return di_write_wait(imxdi, readl(imxdi->ioaddr + DCR) | DCR_TCE, DCR);
0587 }
0588
0589 static int dryice_rtc_alarm_irq_enable(struct device *dev,
0590 unsigned int enabled)
0591 {
0592 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
0593
0594 if (enabled)
0595 di_int_enable(imxdi, DIER_CAIE);
0596 else
0597 di_int_disable(imxdi, DIER_CAIE);
0598
0599 return 0;
0600 }
0601
0602
0603
0604
0605
0606 static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
0607 {
0608 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
0609 u32 dcamr;
0610
0611 dcamr = readl(imxdi->ioaddr + DCAMR);
0612 rtc_time64_to_tm(dcamr, &alarm->time);
0613
0614
0615 alarm->enabled = (readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0;
0616
0617
0618 mutex_lock(&imxdi->write_mutex);
0619
0620
0621 alarm->pending = (readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0;
0622
0623 mutex_unlock(&imxdi->write_mutex);
0624
0625 return 0;
0626 }
0627
0628
0629
0630
0631 static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
0632 {
0633 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
0634 int rc;
0635
0636
0637 rc = di_write_wait(imxdi, rtc_tm_to_time64(&alarm->time), DCAMR);
0638 if (rc)
0639 return rc;
0640
0641 if (alarm->enabled)
0642 di_int_enable(imxdi, DIER_CAIE);
0643 else
0644 di_int_disable(imxdi, DIER_CAIE);
0645
0646 return 0;
0647 }
0648
0649 static const struct rtc_class_ops dryice_rtc_ops = {
0650 .read_time = dryice_rtc_read_time,
0651 .set_time = dryice_rtc_set_time,
0652 .alarm_irq_enable = dryice_rtc_alarm_irq_enable,
0653 .read_alarm = dryice_rtc_read_alarm,
0654 .set_alarm = dryice_rtc_set_alarm,
0655 };
0656
0657
0658
0659
0660 static irqreturn_t dryice_irq(int irq, void *dev_id)
0661 {
0662 struct imxdi_dev *imxdi = dev_id;
0663 u32 dsr, dier;
0664 irqreturn_t rc = IRQ_NONE;
0665
0666 dier = readl(imxdi->ioaddr + DIER);
0667 dsr = readl(imxdi->ioaddr + DSR);
0668
0669
0670 if (dier & DIER_SVIE) {
0671 if (dsr & DSR_SVF) {
0672
0673
0674
0675
0676
0677
0678
0679
0680 di_int_disable(imxdi, DIER_SVIE);
0681
0682 di_report_tamper_info(imxdi, dsr);
0683 rc = IRQ_HANDLED;
0684 }
0685 }
0686
0687
0688 if (dier & DIER_WCIE) {
0689
0690
0691
0692 if (list_empty_careful(&imxdi->write_wait.head))
0693 return rc;
0694
0695
0696 if (dsr & (DSR_WCF | DSR_WEF)) {
0697
0698 di_int_disable(imxdi, DIER_WCIE);
0699
0700
0701 imxdi->dsr |= dsr;
0702
0703 wake_up_interruptible(&imxdi->write_wait);
0704 rc = IRQ_HANDLED;
0705 }
0706 }
0707
0708
0709 if (dier & DIER_CAIE) {
0710
0711 if (dsr & DSR_CAF) {
0712
0713 di_int_disable(imxdi, DIER_CAIE);
0714
0715
0716 schedule_work(&imxdi->work);
0717 rc = IRQ_HANDLED;
0718 }
0719 }
0720 return rc;
0721 }
0722
0723
0724
0725
0726
0727 static void dryice_work(struct work_struct *work)
0728 {
0729 struct imxdi_dev *imxdi = container_of(work,
0730 struct imxdi_dev, work);
0731
0732
0733 di_write_wait(imxdi, DSR_CAF, DSR);
0734
0735
0736 rtc_update_irq(imxdi->rtc, 1, RTC_AF | RTC_IRQF);
0737 }
0738
0739
0740
0741
0742 static int __init dryice_rtc_probe(struct platform_device *pdev)
0743 {
0744 struct imxdi_dev *imxdi;
0745 int norm_irq, sec_irq;
0746 int rc;
0747
0748 imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL);
0749 if (!imxdi)
0750 return -ENOMEM;
0751
0752 imxdi->pdev = pdev;
0753
0754 imxdi->ioaddr = devm_platform_ioremap_resource(pdev, 0);
0755 if (IS_ERR(imxdi->ioaddr))
0756 return PTR_ERR(imxdi->ioaddr);
0757
0758 spin_lock_init(&imxdi->irq_lock);
0759
0760 norm_irq = platform_get_irq(pdev, 0);
0761 if (norm_irq < 0)
0762 return norm_irq;
0763
0764
0765
0766
0767 sec_irq = platform_get_irq(pdev, 1);
0768 if (sec_irq <= 0)
0769 sec_irq = IRQ_NOTCONNECTED;
0770
0771 init_waitqueue_head(&imxdi->write_wait);
0772
0773 INIT_WORK(&imxdi->work, dryice_work);
0774
0775 mutex_init(&imxdi->write_mutex);
0776
0777 imxdi->rtc = devm_rtc_allocate_device(&pdev->dev);
0778 if (IS_ERR(imxdi->rtc))
0779 return PTR_ERR(imxdi->rtc);
0780
0781 imxdi->clk = devm_clk_get(&pdev->dev, NULL);
0782 if (IS_ERR(imxdi->clk))
0783 return PTR_ERR(imxdi->clk);
0784 rc = clk_prepare_enable(imxdi->clk);
0785 if (rc)
0786 return rc;
0787
0788
0789
0790
0791
0792
0793 writel(0, imxdi->ioaddr + DIER);
0794
0795 rc = di_handle_state(imxdi);
0796 if (rc != 0)
0797 goto err;
0798
0799 rc = devm_request_irq(&pdev->dev, norm_irq, dryice_irq,
0800 IRQF_SHARED, pdev->name, imxdi);
0801 if (rc) {
0802 dev_warn(&pdev->dev, "interrupt not available.\n");
0803 goto err;
0804 }
0805
0806 rc = devm_request_irq(&pdev->dev, sec_irq, dryice_irq,
0807 IRQF_SHARED, pdev->name, imxdi);
0808 if (rc) {
0809 dev_warn(&pdev->dev, "security violation interrupt not available.\n");
0810
0811 }
0812
0813 platform_set_drvdata(pdev, imxdi);
0814
0815 device_init_wakeup(&pdev->dev, true);
0816 dev_pm_set_wake_irq(&pdev->dev, norm_irq);
0817
0818 imxdi->rtc->ops = &dryice_rtc_ops;
0819 imxdi->rtc->range_max = U32_MAX;
0820
0821 rc = devm_rtc_register_device(imxdi->rtc);
0822 if (rc)
0823 goto err;
0824
0825 return 0;
0826
0827 err:
0828 clk_disable_unprepare(imxdi->clk);
0829
0830 return rc;
0831 }
0832
0833 static int __exit dryice_rtc_remove(struct platform_device *pdev)
0834 {
0835 struct imxdi_dev *imxdi = platform_get_drvdata(pdev);
0836
0837 flush_work(&imxdi->work);
0838
0839
0840 writel(0, imxdi->ioaddr + DIER);
0841
0842 clk_disable_unprepare(imxdi->clk);
0843
0844 return 0;
0845 }
0846
0847 static const struct of_device_id dryice_dt_ids[] = {
0848 { .compatible = "fsl,imx25-rtc" },
0849 { }
0850 };
0851
0852 MODULE_DEVICE_TABLE(of, dryice_dt_ids);
0853
0854 static struct platform_driver dryice_rtc_driver = {
0855 .driver = {
0856 .name = "imxdi_rtc",
0857 .of_match_table = dryice_dt_ids,
0858 },
0859 .remove = __exit_p(dryice_rtc_remove),
0860 };
0861
0862 module_platform_driver_probe(dryice_rtc_driver, dryice_rtc_probe);
0863
0864 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
0865 MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
0866 MODULE_DESCRIPTION("IMX DryIce Realtime Clock Driver (RTC)");
0867 MODULE_LICENSE("GPL");