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