]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/rtc/rtc-imxdi.c
rtc: imxdi: add some background info about the states the machine can be in
[mirror_ubuntu-bionic-kernel.git] / drivers / rtc / rtc-imxdi.c
CommitLineData
eba54546
BS
1/*
2 * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2010 Orex Computed Radiography
4 */
5
6/*
7 * The code contained herein is licensed under the GNU General Public
8 * License. You may obtain a copy of the GNU General Public License
9 * Version 2 or later at the following locations:
10 *
11 * http://www.opensource.org/licenses/gpl-license.html
12 * http://www.gnu.org/copyleft/gpl.html
13 */
14
15/* based on rtc-mc13892.c */
16
17/*
18 * This driver uses the 47-bit 32 kHz counter in the Freescale DryIce block
19 * to implement a Linux RTC. Times and alarms are truncated to seconds.
20 * Since the RTC framework performs API locking via rtc->ops_lock the
21 * only simultaneous accesses we need to deal with is updating DryIce
22 * registers while servicing an alarm.
23 *
24 * Note that reading the DSR (DryIce Status Register) automatically clears
25 * the WCF (Write Complete Flag). All DryIce writes are synchronized to the
26 * LP (Low Power) domain and set the WCF upon completion. Writes to the
27 * DIER (DryIce Interrupt Enable Register) are the only exception. These
28 * occur at normal bus speeds and do not set WCF. Periodic interrupts are
29 * not supported by the hardware.
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>
d4c32f35 38#include <linux/sched.h>
ba3f7a17 39#include <linux/spinlock.h>
eba54546 40#include <linux/workqueue.h>
968d21c2 41#include <linux/of.h>
eba54546
BS
42
43/* DryIce Register Definitions */
44
45#define DTCMR 0x00 /* Time Counter MSB Reg */
46#define DTCLR 0x04 /* Time Counter LSB Reg */
47
48#define DCAMR 0x08 /* Clock Alarm MSB Reg */
49#define DCALR 0x0c /* Clock Alarm LSB Reg */
50#define DCAMR_UNSET 0xFFFFFFFF /* doomsday - 1 sec */
51
52#define DCR 0x10 /* Control Reg */
46edeffa
JB
53#define DCR_TDCHL (1 << 30) /* Tamper-detect configuration hard lock */
54#define DCR_TDCSL (1 << 29) /* Tamper-detect configuration soft lock */
55#define DCR_KSSL (1 << 27) /* Key-select soft lock */
56#define DCR_MCHL (1 << 20) /* Monotonic-counter hard lock */
57#define DCR_MCSL (1 << 19) /* Monotonic-counter soft lock */
58#define DCR_TCHL (1 << 18) /* Timer-counter hard lock */
59#define DCR_TCSL (1 << 17) /* Timer-counter soft lock */
60#define DCR_FSHL (1 << 16) /* Failure state hard lock */
eba54546 61#define DCR_TCE (1 << 3) /* Time Counter Enable */
46edeffa 62#define DCR_MCE (1 << 2) /* Monotonic Counter Enable */
eba54546
BS
63
64#define DSR 0x14 /* Status Reg */
46edeffa
JB
65#define DSR_WTD (1 << 23) /* Wire-mesh tamper detected */
66#define DSR_ETBD (1 << 22) /* External tamper B detected */
67#define DSR_ETAD (1 << 21) /* External tamper A detected */
68#define DSR_EBD (1 << 20) /* External boot detected */
69#define DSR_SAD (1 << 19) /* SCC alarm detected */
70#define DSR_TTD (1 << 18) /* Temperatur tamper detected */
71#define DSR_CTD (1 << 17) /* Clock tamper detected */
72#define DSR_VTD (1 << 16) /* Voltage tamper detected */
73#define DSR_WBF (1 << 10) /* Write Busy Flag (synchronous) */
74#define DSR_WNF (1 << 9) /* Write Next Flag (synchronous) */
75#define DSR_WCF (1 << 8) /* Write Complete Flag (synchronous)*/
eba54546
BS
76#define DSR_WEF (1 << 7) /* Write Error Flag */
77#define DSR_CAF (1 << 4) /* Clock Alarm Flag */
46edeffa
JB
78#define DSR_MCO (1 << 3) /* monotonic counter overflow */
79#define DSR_TCO (1 << 2) /* time counter overflow */
eba54546
BS
80#define DSR_NVF (1 << 1) /* Non-Valid Flag */
81#define DSR_SVF (1 << 0) /* Security Violation Flag */
82
46edeffa 83#define DIER 0x18 /* Interrupt Enable Reg (synchronous) */
eba54546
BS
84#define DIER_WNIE (1 << 9) /* Write Next Interrupt Enable */
85#define DIER_WCIE (1 << 8) /* Write Complete Interrupt Enable */
86#define DIER_WEIE (1 << 7) /* Write Error Interrupt Enable */
87#define DIER_CAIE (1 << 4) /* Clock Alarm Interrupt Enable */
46edeffa
JB
88#define DIER_SVIE (1 << 0) /* Security-violation Interrupt Enable */
89
90#define DMCR 0x1c /* DryIce Monotonic Counter Reg */
91
92#define DTCR 0x28 /* DryIce Tamper Configuration Reg */
93#define DTCR_MOE (1 << 9) /* monotonic overflow enabled */
94#define DTCR_TOE (1 << 8) /* time overflow enabled */
95#define DTCR_WTE (1 << 7) /* wire-mesh tamper enabled */
96#define DTCR_ETBE (1 << 6) /* external B tamper enabled */
97#define DTCR_ETAE (1 << 5) /* external A tamper enabled */
98#define DTCR_EBE (1 << 4) /* external boot tamper enabled */
99#define DTCR_SAIE (1 << 3) /* SCC enabled */
100#define DTCR_TTE (1 << 2) /* temperature tamper enabled */
101#define DTCR_CTE (1 << 1) /* clock tamper enabled */
102#define DTCR_VTE (1 << 0) /* voltage tamper enabled */
103
104#define DGPR 0x3c /* DryIce General Purpose Reg */
eba54546
BS
105
106/**
107 * struct imxdi_dev - private imxdi rtc data
108 * @pdev: pionter to platform dev
109 * @rtc: pointer to rtc struct
110 * @ioaddr: IO registers pointer
111 * @irq: dryice normal interrupt
112 * @clk: input reference clock
113 * @dsr: copy of the DSR register
114 * @irq_lock: interrupt enable register (DIER) lock
115 * @write_wait: registers write complete queue
116 * @write_mutex: serialize registers write
117 * @work: schedule alarm work
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
3ba3fab7
JB
132/* Some background:
133 *
134 * The DryIce unit is a complex security/tamper monitor device. To be able do
135 * its job in a useful manner it runs a bigger statemachine to bring it into
136 * security/tamper failure state and once again to bring it out of this state.
137 *
138 * This unit can be in one of three states:
139 *
140 * - "NON-VALID STATE"
141 * always after the battery power was removed
142 * - "FAILURE STATE"
143 * if one of the enabled security events has happened
144 * - "VALID STATE"
145 * if the unit works as expected
146 *
147 * Everything stops when the unit enters the failure state including the RTC
148 * counter (to be able to detect the time the security event happened).
149 *
150 * The following events (when enabled) let the DryIce unit enter the failure
151 * state:
152 *
153 * - wire-mesh-tamper detect
154 * - external tamper B detect
155 * - external tamper A detect
156 * - temperature tamper detect
157 * - clock tamper detect
158 * - voltage tamper detect
159 * - RTC counter overflow
160 * - monotonic counter overflow
161 * - external boot
162 *
163 * If we find the DryIce unit in "FAILURE STATE" and the TDCHL cleared, we
164 * can only detect this state. In this case the unit is completely locked and
165 * must force a second "SYSTEM POR" to bring the DryIce into the
166 * "NON-VALID STATE" + "FAILURE STATE" where a recovery is possible.
167 * If the TDCHL is set in the "FAILURE STATE" we are out of luck. In this case
168 * a battery power cycle is required.
169 *
170 * In the "NON-VALID STATE" + "FAILURE STATE" we can clear the "FAILURE STATE"
171 * and recover the DryIce unit. By clearing the "NON-VALID STATE" as the last
172 * task, we bring back this unit into life.
173 */
174
eba54546
BS
175/*
176 * enable a dryice interrupt
177 */
178static void di_int_enable(struct imxdi_dev *imxdi, u32 intr)
179{
180 unsigned long flags;
181
182 spin_lock_irqsave(&imxdi->irq_lock, flags);
e30d3131
JB
183 writel(readl(imxdi->ioaddr + DIER) | intr,
184 imxdi->ioaddr + DIER);
eba54546
BS
185 spin_unlock_irqrestore(&imxdi->irq_lock, flags);
186}
187
188/*
189 * disable a dryice interrupt
190 */
191static void di_int_disable(struct imxdi_dev *imxdi, u32 intr)
192{
193 unsigned long flags;
194
195 spin_lock_irqsave(&imxdi->irq_lock, flags);
e30d3131
JB
196 writel(readl(imxdi->ioaddr + DIER) & ~intr,
197 imxdi->ioaddr + DIER);
eba54546
BS
198 spin_unlock_irqrestore(&imxdi->irq_lock, flags);
199}
200
201/*
202 * This function attempts to clear the dryice write-error flag.
203 *
204 * A dryice write error is similar to a bus fault and should not occur in
205 * normal operation. Clearing the flag requires another write, so the root
206 * cause of the problem may need to be fixed before the flag can be cleared.
207 */
208static void clear_write_error(struct imxdi_dev *imxdi)
209{
210 int cnt;
211
212 dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n");
213
214 /* clear the write error flag */
e30d3131 215 writel(DSR_WEF, imxdi->ioaddr + DSR);
eba54546
BS
216
217 /* wait for it to take effect */
218 for (cnt = 0; cnt < 1000; cnt++) {
e30d3131 219 if ((readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0)
eba54546
BS
220 return;
221 udelay(10);
222 }
223 dev_err(&imxdi->pdev->dev,
224 "ERROR: Cannot clear write-error flag!\n");
225}
226
227/*
228 * Write a dryice register and wait until it completes.
229 *
230 * This function uses interrupts to determine when the
231 * write has completed.
232 */
233static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg)
234{
235 int ret;
236 int rc = 0;
237
238 /* serialize register writes */
239 mutex_lock(&imxdi->write_mutex);
240
241 /* enable the write-complete interrupt */
242 di_int_enable(imxdi, DIER_WCIE);
243
244 imxdi->dsr = 0;
245
246 /* do the register write */
e30d3131 247 writel(val, imxdi->ioaddr + reg);
eba54546
BS
248
249 /* wait for the write to finish */
250 ret = wait_event_interruptible_timeout(imxdi->write_wait,
251 imxdi->dsr & (DSR_WCF | DSR_WEF), msecs_to_jiffies(1));
252 if (ret < 0) {
253 rc = ret;
254 goto out;
255 } else if (ret == 0) {
256 dev_warn(&imxdi->pdev->dev,
257 "Write-wait timeout "
258 "val = 0x%08x reg = 0x%08x\n", val, reg);
259 }
260
261 /* check for write error */
262 if (imxdi->dsr & DSR_WEF) {
263 clear_write_error(imxdi);
264 rc = -EIO;
265 }
266
267out:
268 mutex_unlock(&imxdi->write_mutex);
269
270 return rc;
271}
272
273/*
274 * read the seconds portion of the current time from the dryice time counter
275 */
276static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm)
277{
278 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
279 unsigned long now;
280
e30d3131 281 now = readl(imxdi->ioaddr + DTCMR);
eba54546
BS
282 rtc_time_to_tm(now, tm);
283
284 return 0;
285}
286
287/*
288 * set the seconds portion of dryice time counter and clear the
289 * fractional part.
290 */
291static int dryice_rtc_set_mmss(struct device *dev, unsigned long secs)
292{
293 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
294 int rc;
295
296 /* zero the fractional part first */
297 rc = di_write_wait(imxdi, 0, DTCLR);
298 if (rc == 0)
299 rc = di_write_wait(imxdi, secs, DTCMR);
300
301 return rc;
302}
303
304static int dryice_rtc_alarm_irq_enable(struct device *dev,
305 unsigned int enabled)
306{
307 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
308
309 if (enabled)
310 di_int_enable(imxdi, DIER_CAIE);
311 else
312 di_int_disable(imxdi, DIER_CAIE);
313
314 return 0;
315}
316
317/*
318 * read the seconds portion of the alarm register.
319 * the fractional part of the alarm register is always zero.
320 */
321static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
322{
323 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
324 u32 dcamr;
325
e30d3131 326 dcamr = readl(imxdi->ioaddr + DCAMR);
eba54546
BS
327 rtc_time_to_tm(dcamr, &alarm->time);
328
329 /* alarm is enabled if the interrupt is enabled */
e30d3131 330 alarm->enabled = (readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0;
eba54546
BS
331
332 /* don't allow the DSR read to mess up DSR_WCF */
333 mutex_lock(&imxdi->write_mutex);
334
335 /* alarm is pending if the alarm flag is set */
e30d3131 336 alarm->pending = (readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0;
eba54546
BS
337
338 mutex_unlock(&imxdi->write_mutex);
339
340 return 0;
341}
342
343/*
344 * set the seconds portion of dryice alarm register
345 */
346static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
347{
348 struct imxdi_dev *imxdi = dev_get_drvdata(dev);
349 unsigned long now;
350 unsigned long alarm_time;
351 int rc;
352
353 rc = rtc_tm_to_time(&alarm->time, &alarm_time);
354 if (rc)
355 return rc;
356
357 /* don't allow setting alarm in the past */
e30d3131 358 now = readl(imxdi->ioaddr + DTCMR);
eba54546
BS
359 if (alarm_time < now)
360 return -EINVAL;
361
362 /* write the new alarm time */
363 rc = di_write_wait(imxdi, (u32)alarm_time, DCAMR);
364 if (rc)
365 return rc;
366
367 if (alarm->enabled)
368 di_int_enable(imxdi, DIER_CAIE); /* enable alarm intr */
369 else
370 di_int_disable(imxdi, DIER_CAIE); /* disable alarm intr */
371
372 return 0;
373}
374
375static struct rtc_class_ops dryice_rtc_ops = {
376 .read_time = dryice_rtc_read_time,
377 .set_mmss = dryice_rtc_set_mmss,
378 .alarm_irq_enable = dryice_rtc_alarm_irq_enable,
379 .read_alarm = dryice_rtc_read_alarm,
380 .set_alarm = dryice_rtc_set_alarm,
381};
382
383/*
384 * dryice "normal" interrupt handler
385 */
386static irqreturn_t dryice_norm_irq(int irq, void *dev_id)
387{
388 struct imxdi_dev *imxdi = dev_id;
389 u32 dsr, dier;
390 irqreturn_t rc = IRQ_NONE;
391
e30d3131 392 dier = readl(imxdi->ioaddr + DIER);
eba54546
BS
393
394 /* handle write complete and write error cases */
6df17a65 395 if (dier & DIER_WCIE) {
eba54546
BS
396 /*If the write wait queue is empty then there is no pending
397 operations. It means the interrupt is for DryIce -Security.
398 IRQ must be returned as none.*/
399 if (list_empty_careful(&imxdi->write_wait.task_list))
400 return rc;
401
402 /* DSR_WCF clears itself on DSR read */
e30d3131 403 dsr = readl(imxdi->ioaddr + DSR);
6df17a65 404 if (dsr & (DSR_WCF | DSR_WEF)) {
eba54546
BS
405 /* mask the interrupt */
406 di_int_disable(imxdi, DIER_WCIE);
407
408 /* save the dsr value for the wait queue */
409 imxdi->dsr |= dsr;
410
411 wake_up_interruptible(&imxdi->write_wait);
412 rc = IRQ_HANDLED;
413 }
414 }
415
416 /* handle the alarm case */
6df17a65 417 if (dier & DIER_CAIE) {
eba54546 418 /* DSR_WCF clears itself on DSR read */
e30d3131 419 dsr = readl(imxdi->ioaddr + DSR);
eba54546
BS
420 if (dsr & DSR_CAF) {
421 /* mask the interrupt */
422 di_int_disable(imxdi, DIER_CAIE);
423
424 /* finish alarm in user context */
425 schedule_work(&imxdi->work);
426 rc = IRQ_HANDLED;
427 }
428 }
429 return rc;
430}
431
432/*
433 * post the alarm event from user context so it can sleep
434 * on the write completion.
435 */
436static void dryice_work(struct work_struct *work)
437{
438 struct imxdi_dev *imxdi = container_of(work,
439 struct imxdi_dev, work);
440
441 /* dismiss the interrupt (ignore error) */
442 di_write_wait(imxdi, DSR_CAF, DSR);
443
444 /* pass the alarm event to the rtc framework. */
445 rtc_update_irq(imxdi->rtc, 1, RTC_AF | RTC_IRQF);
446}
447
448/*
449 * probe for dryice rtc device
450 */
5073cba6 451static int __init dryice_rtc_probe(struct platform_device *pdev)
eba54546
BS
452{
453 struct resource *res;
454 struct imxdi_dev *imxdi;
455 int rc;
456
eba54546
BS
457 imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL);
458 if (!imxdi)
459 return -ENOMEM;
460
461 imxdi->pdev = pdev;
462
7c1d69ee
JL
463 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
464 imxdi->ioaddr = devm_ioremap_resource(&pdev->dev, res);
465 if (IS_ERR(imxdi->ioaddr))
466 return PTR_ERR(imxdi->ioaddr);
eba54546 467
fee0de77
JL
468 spin_lock_init(&imxdi->irq_lock);
469
eba54546
BS
470 imxdi->irq = platform_get_irq(pdev, 0);
471 if (imxdi->irq < 0)
472 return imxdi->irq;
473
474 init_waitqueue_head(&imxdi->write_wait);
475
476 INIT_WORK(&imxdi->work, dryice_work);
477
478 mutex_init(&imxdi->write_mutex);
479
9510853c 480 imxdi->clk = devm_clk_get(&pdev->dev, NULL);
eba54546
BS
481 if (IS_ERR(imxdi->clk))
482 return PTR_ERR(imxdi->clk);
3378f73d
FE
483 rc = clk_prepare_enable(imxdi->clk);
484 if (rc)
485 return rc;
eba54546
BS
486
487 /*
488 * Initialize dryice hardware
489 */
490
491 /* mask all interrupts */
e30d3131 492 writel(0, imxdi->ioaddr + DIER);
eba54546
BS
493
494 rc = devm_request_irq(&pdev->dev, imxdi->irq, dryice_norm_irq,
495 IRQF_SHARED, pdev->name, imxdi);
496 if (rc) {
497 dev_warn(&pdev->dev, "interrupt not available.\n");
498 goto err;
499 }
500
501 /* put dryice into valid state */
e30d3131 502 if (readl(imxdi->ioaddr + DSR) & DSR_NVF) {
eba54546
BS
503 rc = di_write_wait(imxdi, DSR_NVF | DSR_SVF, DSR);
504 if (rc)
505 goto err;
506 }
507
508 /* initialize alarm */
509 rc = di_write_wait(imxdi, DCAMR_UNSET, DCAMR);
510 if (rc)
511 goto err;
512 rc = di_write_wait(imxdi, 0, DCALR);
513 if (rc)
514 goto err;
515
516 /* clear alarm flag */
e30d3131 517 if (readl(imxdi->ioaddr + DSR) & DSR_CAF) {
eba54546
BS
518 rc = di_write_wait(imxdi, DSR_CAF, DSR);
519 if (rc)
520 goto err;
521 }
522
523 /* the timer won't count if it has never been written to */
e30d3131 524 if (readl(imxdi->ioaddr + DTCMR) == 0) {
eba54546
BS
525 rc = di_write_wait(imxdi, 0, DTCMR);
526 if (rc)
527 goto err;
528 }
529
530 /* start keeping time */
e30d3131 531 if (!(readl(imxdi->ioaddr + DCR) & DCR_TCE)) {
eba54546 532 rc = di_write_wait(imxdi,
e30d3131 533 readl(imxdi->ioaddr + DCR) | DCR_TCE,
eba54546
BS
534 DCR);
535 if (rc)
536 goto err;
537 }
538
539 platform_set_drvdata(pdev, imxdi);
04f70e4c 540 imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
eba54546
BS
541 &dryice_rtc_ops, THIS_MODULE);
542 if (IS_ERR(imxdi->rtc)) {
543 rc = PTR_ERR(imxdi->rtc);
544 goto err;
545 }
546
547 return 0;
548
549err:
4ec8c7f5 550 clk_disable_unprepare(imxdi->clk);
eba54546
BS
551
552 return rc;
553}
554
5073cba6 555static int __exit dryice_rtc_remove(struct platform_device *pdev)
eba54546
BS
556{
557 struct imxdi_dev *imxdi = platform_get_drvdata(pdev);
558
559 flush_work(&imxdi->work);
560
561 /* mask all interrupts */
e30d3131 562 writel(0, imxdi->ioaddr + DIER);
eba54546 563
4ec8c7f5 564 clk_disable_unprepare(imxdi->clk);
eba54546
BS
565
566 return 0;
567}
568
968d21c2
RS
569#ifdef CONFIG_OF
570static const struct of_device_id dryice_dt_ids[] = {
571 { .compatible = "fsl,imx25-rtc" },
572 { /* sentinel */ }
573};
574
575MODULE_DEVICE_TABLE(of, dryice_dt_ids);
576#endif
577
eba54546
BS
578static struct platform_driver dryice_rtc_driver = {
579 .driver = {
580 .name = "imxdi_rtc",
968d21c2 581 .of_match_table = of_match_ptr(dryice_dt_ids),
eba54546 582 },
5073cba6 583 .remove = __exit_p(dryice_rtc_remove),
eba54546
BS
584};
585
61534342 586module_platform_driver_probe(dryice_rtc_driver, dryice_rtc_probe);
eba54546
BS
587
588MODULE_AUTHOR("Freescale Semiconductor, Inc.");
589MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
590MODULE_DESCRIPTION("IMX DryIce Realtime Clock Driver (RTC)");
591MODULE_LICENSE("GPL");