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