1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/io.h>
23#include <linux/clk.h>
24#include <linux/delay.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27#include <linux/rtc.h>
28#include <linux/sched.h>
29#include <linux/spinlock.h>
30#include <linux/workqueue.h>
31#include <linux/of.h>
32
33
34
35#define DTCMR 0x00
36#define DTCLR 0x04
37
38#define DCAMR 0x08
39#define DCALR 0x0c
40#define DCAMR_UNSET 0xFFFFFFFF
41
42#define DCR 0x10
43#define DCR_TDCHL (1 << 30)
44#define DCR_TDCSL (1 << 29)
45#define DCR_KSSL (1 << 27)
46#define DCR_MCHL (1 << 20)
47#define DCR_MCSL (1 << 19)
48#define DCR_TCHL (1 << 18)
49#define DCR_TCSL (1 << 17)
50#define DCR_FSHL (1 << 16)
51#define DCR_TCE (1 << 3)
52#define DCR_MCE (1 << 2)
53
54#define DSR 0x14
55#define DSR_WTD (1 << 23)
56#define DSR_ETBD (1 << 22)
57#define DSR_ETAD (1 << 21)
58#define DSR_EBD (1 << 20)
59#define DSR_SAD (1 << 19)
60#define DSR_TTD (1 << 18)
61#define DSR_CTD (1 << 17)
62#define DSR_VTD (1 << 16)
63#define DSR_WBF (1 << 10)
64#define DSR_WNF (1 << 9)
65#define DSR_WCF (1 << 8)
66#define DSR_WEF (1 << 7)
67#define DSR_CAF (1 << 4)
68#define DSR_MCO (1 << 3)
69#define DSR_TCO (1 << 2)
70#define DSR_NVF (1 << 1)
71#define DSR_SVF (1 << 0)
72
73#define DIER 0x18
74#define DIER_WNIE (1 << 9)
75#define DIER_WCIE (1 << 8)
76#define DIER_WEIE (1 << 7)
77#define DIER_CAIE (1 << 4)
78#define DIER_SVIE (1 << 0)
79
80#define DMCR 0x1c
81
82#define DTCR 0x28
83#define DTCR_MOE (1 << 9)
84#define DTCR_TOE (1 << 8)
85#define DTCR_WTE (1 << 7)
86#define DTCR_ETBE (1 << 6)
87#define DTCR_ETAE (1 << 5)
88#define DTCR_EBE (1 << 4)
89#define DTCR_SAIE (1 << 3)
90#define DTCR_TTE (1 << 2)
91#define DTCR_CTE (1 << 1)
92#define DTCR_VTE (1 << 0)
93
94#define DGPR 0x3c
95
96
97
98
99
100
101
102
103
104
105
106
107
108struct imxdi_dev {
109 struct platform_device *pdev;
110 struct rtc_device *rtc;
111 void __iomem *ioaddr;
112 struct clk *clk;
113 u32 dsr;
114 spinlock_t irq_lock;
115 wait_queue_head_t write_wait;
116 struct mutex write_mutex;
117 struct work_struct work;
118};
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170static void di_write_busy_wait(const struct imxdi_dev *imxdi, u32 val,
171 unsigned reg)
172{
173
174 writel(val, imxdi->ioaddr + reg);
175
176
177
178
179
180 usleep_range(130, 200);
181}
182
183static void di_report_tamper_info(struct imxdi_dev *imxdi, u32 dsr)
184{
185 u32 dtcr;
186
187 dtcr = readl(imxdi->ioaddr + DTCR);
188
189 dev_emerg(&imxdi->pdev->dev, "DryIce tamper event detected\n");
190
191 if (dsr & DSR_VTD)
192 dev_emerg(&imxdi->pdev->dev, "%sVoltage Tamper Event\n",
193 dtcr & DTCR_VTE ? "" : "Spurious ");
194
195 if (dsr & DSR_CTD)
196 dev_emerg(&imxdi->pdev->dev, "%s32768 Hz Clock Tamper Event\n",
197 dtcr & DTCR_CTE ? "" : "Spurious ");
198
199 if (dsr & DSR_TTD)
200 dev_emerg(&imxdi->pdev->dev, "%sTemperature Tamper Event\n",
201 dtcr & DTCR_TTE ? "" : "Spurious ");
202
203 if (dsr & DSR_SAD)
204 dev_emerg(&imxdi->pdev->dev,
205 "%sSecure Controller Alarm Event\n",
206 dtcr & DTCR_SAIE ? "" : "Spurious ");
207
208 if (dsr & DSR_EBD)
209 dev_emerg(&imxdi->pdev->dev, "%sExternal Boot Tamper Event\n",
210 dtcr & DTCR_EBE ? "" : "Spurious ");
211
212 if (dsr & DSR_ETAD)
213 dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper A Event\n",
214 dtcr & DTCR_ETAE ? "" : "Spurious ");
215
216 if (dsr & DSR_ETBD)
217 dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper B Event\n",
218 dtcr & DTCR_ETBE ? "" : "Spurious ");
219
220 if (dsr & DSR_WTD)
221 dev_emerg(&imxdi->pdev->dev, "%sWire-mesh Tamper Event\n",
222 dtcr & DTCR_WTE ? "" : "Spurious ");
223
224 if (dsr & DSR_MCO)
225 dev_emerg(&imxdi->pdev->dev,
226 "%sMonotonic-counter Overflow Event\n",
227 dtcr & DTCR_MOE ? "" : "Spurious ");
228
229 if (dsr & DSR_TCO)
230 dev_emerg(&imxdi->pdev->dev, "%sTimer-counter Overflow Event\n",
231 dtcr & DTCR_TOE ? "" : "Spurious ");
232}
233
234static void di_what_is_to_be_done(struct imxdi_dev *imxdi,
235 const char *power_supply)
236{
237 dev_emerg(&imxdi->pdev->dev, "Please cycle the %s power supply in order to get the DryIce/RTC unit working again\n",
238 power_supply);
239}
240
241static int di_handle_failure_state(struct imxdi_dev *imxdi, u32 dsr)
242{
243 u32 dcr;
244
245 dev_dbg(&imxdi->pdev->dev, "DSR register reports: %08X\n", dsr);
246
247
248 di_report_tamper_info(imxdi, dsr);
249
250 dcr = readl(imxdi->ioaddr + DCR);
251
252 if (dcr & DCR_FSHL) {
253
254 di_what_is_to_be_done(imxdi, "battery");
255 return -ENODEV;
256 }
257
258
259
260
261 di_what_is_to_be_done(imxdi, "main");
262
263 return -ENODEV;
264}
265
266static int di_handle_valid_state(struct imxdi_dev *imxdi, u32 dsr)
267{
268
269 di_write_busy_wait(imxdi, DCAMR_UNSET, DCAMR);
270 di_write_busy_wait(imxdi, 0, DCALR);
271
272
273 if (dsr & DSR_CAF)
274 di_write_busy_wait(imxdi, DSR_CAF, DSR);
275
276 return 0;
277}
278
279static int di_handle_invalid_state(struct imxdi_dev *imxdi, u32 dsr)
280{
281 u32 dcr, sec;
282
283
284
285
286
287 di_write_busy_wait(imxdi, 0x00000000, DTCR);
288
289 di_write_busy_wait(imxdi, DCR_TDCSL, DCR);
290
291 sec = readl(imxdi->ioaddr + DTCMR);
292 if (sec != 0)
293 dev_warn(&imxdi->pdev->dev,
294 "The security violation has happened at %u seconds\n",
295 sec);
296
297
298
299
300 dcr = readl(imxdi->ioaddr + DCR);
301 if (!(dcr & DCR_TCE)) {
302 if (dcr & DCR_TCHL) {
303
304 di_what_is_to_be_done(imxdi, "battery");
305 return -ENODEV;
306 }
307 if (dcr & DCR_TCSL) {
308 di_what_is_to_be_done(imxdi, "main");
309 return -ENODEV;
310 }
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324 di_write_busy_wait(imxdi, DSR_NVF, DSR);
325
326 di_write_busy_wait(imxdi, DSR_TCO, DSR);
327
328 di_write_busy_wait(imxdi, dcr | DCR_TCE, DCR);
329
330 di_write_busy_wait(imxdi, sec, DTCMR);
331
332
333 return di_handle_valid_state(imxdi, __raw_readl(imxdi->ioaddr + DSR));
334}
335
336static int di_handle_invalid_and_failure_state(struct imxdi_dev *imxdi, u32 dsr)
337{
338 u32 dcr;
339
340
341
342
343
344
345 if (dsr & (DSR_WTD | DSR_ETBD | DSR_ETAD | DSR_EBD | DSR_SAD |
346 DSR_TTD | DSR_CTD | DSR_VTD | DSR_MCO | DSR_TCO)) {
347 dcr = __raw_readl(imxdi->ioaddr + DCR);
348 if (dcr & DCR_TDCHL) {
349
350
351
352
353
354
355
356
357
358
359
360 di_what_is_to_be_done(imxdi, "battery");
361 return -ENODEV;
362 }
363 if (dcr & DCR_TDCSL) {
364
365 di_what_is_to_be_done(imxdi, "main");
366 return -ENODEV;
367 }
368 }
369
370
371 di_write_busy_wait(imxdi, 0x00000000, DTCR);
372
373
374 di_write_busy_wait(imxdi, dsr & (DSR_WTD | DSR_ETBD | DSR_ETAD |
375 DSR_EBD | DSR_SAD | DSR_TTD | DSR_CTD | DSR_VTD |
376 DSR_MCO | DSR_TCO), DSR);
377
378 dsr = readl(imxdi->ioaddr + DSR);
379 if ((dsr & ~(DSR_NVF | DSR_SVF | DSR_WBF | DSR_WNF |
380 DSR_WCF | DSR_WEF)) != 0)
381 dev_warn(&imxdi->pdev->dev,
382 "There are still some sources of pain in DSR: %08x!\n",
383 dsr & ~(DSR_NVF | DSR_SVF | DSR_WBF | DSR_WNF |
384 DSR_WCF | DSR_WEF));
385
386
387
388
389
390 di_write_busy_wait(imxdi, DSR_SVF, DSR);
391
392
393 dsr = readl(imxdi->ioaddr + DSR);
394 if (dsr & DSR_SVF) {
395 dev_crit(&imxdi->pdev->dev,
396 "Cannot clear the security violation flag. We are ending up in an endless loop!\n");
397
398 di_what_is_to_be_done(imxdi, "battery");
399 return -ENODEV;
400 }
401
402
403
404
405
406 return di_handle_invalid_state(imxdi, dsr);
407}
408
409static int di_handle_state(struct imxdi_dev *imxdi)
410{
411 int rc;
412 u32 dsr;
413
414 dsr = readl(imxdi->ioaddr + DSR);
415
416 switch (dsr & (DSR_NVF | DSR_SVF)) {
417 case DSR_NVF:
418 dev_warn(&imxdi->pdev->dev, "Invalid stated unit detected\n");
419 rc = di_handle_invalid_state(imxdi, dsr);
420 break;
421 case DSR_SVF:
422 dev_warn(&imxdi->pdev->dev, "Failure stated unit detected\n");
423 rc = di_handle_failure_state(imxdi, dsr);
424 break;
425 case DSR_NVF | DSR_SVF:
426 dev_warn(&imxdi->pdev->dev,
427 "Failure+Invalid stated unit detected\n");
428 rc = di_handle_invalid_and_failure_state(imxdi, dsr);
429 break;
430 default:
431 dev_notice(&imxdi->pdev->dev, "Unlocked unit detected\n");
432 rc = di_handle_valid_state(imxdi, dsr);
433 }
434
435 return rc;
436}
437
438
439
440
441static void di_int_enable(struct imxdi_dev *imxdi, u32 intr)
442{
443 unsigned long flags;
444
445 spin_lock_irqsave(&imxdi->irq_lock, flags);
446 writel(readl(imxdi->ioaddr + DIER) | intr,
447 imxdi->ioaddr + DIER);
448 spin_unlock_irqrestore(&imxdi->irq_lock, flags);
449}
450
451
452
453
454static void di_int_disable(struct imxdi_dev *imxdi, u32 intr)
455{
456 unsigned long flags;
457
458 spin_lock_irqsave(&imxdi->irq_lock, flags);
459 writel(readl(imxdi->ioaddr + DIER) & ~intr,
460 imxdi->ioaddr + DIER);
461 spin_unlock_irqrestore(&imxdi->irq_lock, flags);
462}
463
464
465
466
467
468
469
470
471static void clear_write_error(struct imxdi_dev *imxdi)
472{
473 int cnt;
474
475 dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n");
476
477
478 writel(DSR_WEF, imxdi->ioaddr + DSR);
479
480
481 for (cnt = 0; cnt < 1000; cnt++) {
482 if ((readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0)
483 return;
484 udelay(10);
485 }
486 dev_err(&imxdi->pdev->dev,
487 "ERROR: Cannot clear write-error flag!\n");
488}
489
490
491
492
493
494
495
496static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg)
497{
498 int ret;
499 int rc = 0;
500
501
502 mutex_lock(&imxdi->write_mutex);
503
504
505 di_int_enable(imxdi, DIER_WCIE);
506
507 imxdi->dsr = 0;
508
509
510 writel(val, imxdi->ioaddr + reg);
511
512
513 ret = wait_event_interruptible_timeout(imxdi->write_wait,
514 imxdi->dsr & (DSR_WCF | DSR_WEF), msecs_to_jiffies(1));
515 if (ret < 0) {
516 rc = ret;
517 goto out;
518 } else if (ret == 0) {
519 dev_warn(&imxdi->pdev->dev,
520 "Write-wait timeout "
521 "val = 0x%08x reg = 0x%08x\n", val, reg);
522 }
523
524
525 if (imxdi->dsr & DSR_WEF) {
526 clear_write_error(imxdi);
527 rc = -EIO;
528 }
529
530out:
531 mutex_unlock(&imxdi->write_mutex);
532
533 return rc;
534}
535
536
537
538
539static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm)
540{
541 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
542 unsigned long now;
543
544 now = readl(imxdi->ioaddr + DTCMR);
545 rtc_time64_to_tm(now, tm);
546
547 return 0;
548}
549
550
551
552
553
554static int dryice_rtc_set_time(struct device *dev, struct rtc_time *tm)
555{
556 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
557 u32 dcr, dsr;
558 int rc;
559
560 dcr = readl(imxdi->ioaddr + DCR);
561 dsr = readl(imxdi->ioaddr + DSR);
562
563 if (!(dcr & DCR_TCE) || (dsr & DSR_SVF)) {
564 if (dcr & DCR_TCHL) {
565
566 di_what_is_to_be_done(imxdi, "battery");
567 return -EPERM;
568 }
569 if ((dcr & DCR_TCSL) || (dsr & DSR_SVF)) {
570
571 di_what_is_to_be_done(imxdi, "main");
572 return -EPERM;
573 }
574 }
575
576
577 rc = di_write_wait(imxdi, 0, DTCLR);
578 if (rc != 0)
579 return rc;
580
581 rc = di_write_wait(imxdi, rtc_tm_to_time64(tm), DTCMR);
582 if (rc != 0)
583 return rc;
584
585 return di_write_wait(imxdi, readl(imxdi->ioaddr + DCR) | DCR_TCE, DCR);
586}
587
588static int dryice_rtc_alarm_irq_enable(struct device *dev,
589 unsigned int enabled)
590{
591 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
592
593 if (enabled)
594 di_int_enable(imxdi, DIER_CAIE);
595 else
596 di_int_disable(imxdi, DIER_CAIE);
597
598 return 0;
599}
600
601
602
603
604
605static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
606{
607 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
608 u32 dcamr;
609
610 dcamr = readl(imxdi->ioaddr + DCAMR);
611 rtc_time64_to_tm(dcamr, &alarm->time);
612
613
614 alarm->enabled = (readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0;
615
616
617 mutex_lock(&imxdi->write_mutex);
618
619
620 alarm->pending = (readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0;
621
622 mutex_unlock(&imxdi->write_mutex);
623
624 return 0;
625}
626
627
628
629
630static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
631{
632 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
633 int rc;
634
635
636 rc = di_write_wait(imxdi, rtc_tm_to_time64(&alarm->time), DCAMR);
637 if (rc)
638 return rc;
639
640 if (alarm->enabled)
641 di_int_enable(imxdi, DIER_CAIE);
642 else
643 di_int_disable(imxdi, DIER_CAIE);
644
645 return 0;
646}
647
648static const struct rtc_class_ops dryice_rtc_ops = {
649 .read_time = dryice_rtc_read_time,
650 .set_time = dryice_rtc_set_time,
651 .alarm_irq_enable = dryice_rtc_alarm_irq_enable,
652 .read_alarm = dryice_rtc_read_alarm,
653 .set_alarm = dryice_rtc_set_alarm,
654};
655
656
657
658
659static irqreturn_t dryice_irq(int irq, void *dev_id)
660{
661 struct imxdi_dev *imxdi = dev_id;
662 u32 dsr, dier;
663 irqreturn_t rc = IRQ_NONE;
664
665 dier = readl(imxdi->ioaddr + DIER);
666 dsr = readl(imxdi->ioaddr + DSR);
667
668
669 if (dier & DIER_SVIE) {
670 if (dsr & DSR_SVF) {
671
672
673
674
675
676
677
678
679 di_int_disable(imxdi, DIER_SVIE);
680
681 di_report_tamper_info(imxdi, dsr);
682 rc = IRQ_HANDLED;
683 }
684 }
685
686
687 if (dier & DIER_WCIE) {
688
689
690
691 if (list_empty_careful(&imxdi->write_wait.head))
692 return rc;
693
694
695 if (dsr & (DSR_WCF | DSR_WEF)) {
696
697 di_int_disable(imxdi, DIER_WCIE);
698
699
700 imxdi->dsr |= dsr;
701
702 wake_up_interruptible(&imxdi->write_wait);
703 rc = IRQ_HANDLED;
704 }
705 }
706
707
708 if (dier & DIER_CAIE) {
709
710 if (dsr & DSR_CAF) {
711
712 di_int_disable(imxdi, DIER_CAIE);
713
714
715 schedule_work(&imxdi->work);
716 rc = IRQ_HANDLED;
717 }
718 }
719 return rc;
720}
721
722
723
724
725
726static void dryice_work(struct work_struct *work)
727{
728 struct imxdi_dev *imxdi = container_of(work,
729 struct imxdi_dev, work);
730
731
732 di_write_wait(imxdi, DSR_CAF, DSR);
733
734
735 rtc_update_irq(imxdi->rtc, 1, RTC_AF | RTC_IRQF);
736}
737
738
739
740
741static int __init dryice_rtc_probe(struct platform_device *pdev)
742{
743 struct resource *res;
744 struct imxdi_dev *imxdi;
745 int norm_irq, sec_irq;
746 int rc;
747
748 imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL);
749 if (!imxdi)
750 return -ENOMEM;
751
752 imxdi->pdev = pdev;
753
754 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
755 imxdi->ioaddr = devm_ioremap_resource(&pdev->dev, res);
756 if (IS_ERR(imxdi->ioaddr))
757 return PTR_ERR(imxdi->ioaddr);
758
759 spin_lock_init(&imxdi->irq_lock);
760
761 norm_irq = platform_get_irq(pdev, 0);
762 if (norm_irq < 0)
763 return norm_irq;
764
765
766
767
768 sec_irq = platform_get_irq(pdev, 1);
769 if (sec_irq <= 0)
770 sec_irq = IRQ_NOTCONNECTED;
771
772 init_waitqueue_head(&imxdi->write_wait);
773
774 INIT_WORK(&imxdi->work, dryice_work);
775
776 mutex_init(&imxdi->write_mutex);
777
778 imxdi->rtc = devm_rtc_allocate_device(&pdev->dev);
779 if (IS_ERR(imxdi->rtc))
780 return PTR_ERR(imxdi->rtc);
781
782 imxdi->clk = devm_clk_get(&pdev->dev, NULL);
783 if (IS_ERR(imxdi->clk))
784 return PTR_ERR(imxdi->clk);
785 rc = clk_prepare_enable(imxdi->clk);
786 if (rc)
787 return rc;
788
789
790
791
792
793
794 writel(0, imxdi->ioaddr + DIER);
795
796 rc = di_handle_state(imxdi);
797 if (rc != 0)
798 goto err;
799
800 rc = devm_request_irq(&pdev->dev, norm_irq, dryice_irq,
801 IRQF_SHARED, pdev->name, imxdi);
802 if (rc) {
803 dev_warn(&pdev->dev, "interrupt not available.\n");
804 goto err;
805 }
806
807 rc = devm_request_irq(&pdev->dev, sec_irq, dryice_irq,
808 IRQF_SHARED, pdev->name, imxdi);
809 if (rc) {
810 dev_warn(&pdev->dev, "security violation interrupt not available.\n");
811
812 }
813
814 platform_set_drvdata(pdev, imxdi);
815
816 imxdi->rtc->ops = &dryice_rtc_ops;
817 imxdi->rtc->range_max = U32_MAX;
818
819 rc = rtc_register_device(imxdi->rtc);
820 if (rc)
821 goto err;
822
823 return 0;
824
825err:
826 clk_disable_unprepare(imxdi->clk);
827
828 return rc;
829}
830
831static int __exit dryice_rtc_remove(struct platform_device *pdev)
832{
833 struct imxdi_dev *imxdi = platform_get_drvdata(pdev);
834
835 flush_work(&imxdi->work);
836
837
838 writel(0, imxdi->ioaddr + DIER);
839
840 clk_disable_unprepare(imxdi->clk);
841
842 return 0;
843}
844
845#ifdef CONFIG_OF
846static const struct of_device_id dryice_dt_ids[] = {
847 { .compatible = "fsl,imx25-rtc" },
848 { }
849};
850
851MODULE_DEVICE_TABLE(of, dryice_dt_ids);
852#endif
853
854static struct platform_driver dryice_rtc_driver = {
855 .driver = {
856 .name = "imxdi_rtc",
857 .of_match_table = of_match_ptr(dryice_dt_ids),
858 },
859 .remove = __exit_p(dryice_rtc_remove),
860};
861
862module_platform_driver_probe(dryice_rtc_driver, dryice_rtc_probe);
863
864MODULE_AUTHOR("Freescale Semiconductor, Inc.");
865MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
866MODULE_DESCRIPTION("IMX DryIce Realtime Clock Driver (RTC)");
867MODULE_LICENSE("GPL");
868