• Home
  • Raw
  • Download

Lines Matching +full:imx25 +full:- +full:rtc

2  * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
11 * http://www.opensource.org/licenses/gpl-license.html
15 /* based on rtc-mc13892.c */
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
37 #include <linux/rtc.h>
50 #define DCAMR_UNSET 0xFFFFFFFF /* doomsday - 1 sec */
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 */
65 #define DSR_WTD (1 << 23) /* Wire-mesh tamper detected */
80 #define DSR_NVF (1 << 1) /* Non-Valid Flag */
88 #define DIER_SVIE (1 << 0) /* Security-violation Interrupt Enable */
95 #define DTCR_WTE (1 << 7) /* wire-mesh tamper enabled */
107 * struct imxdi_dev - private imxdi rtc data
109 * @rtc: pointer to rtc struct
120 struct rtc_device *rtc; member
138 * - "NON-VALID STATE"
140 * - "FAILURE STATE"
142 * - "VALID STATE"
145 * Everything stops when the unit enters the failure state including the RTC
151 * - wire-mesh-tamper detect
152 * - external tamper B detect
153 * - external tamper A detect
154 * - temperature tamper detect
155 * - clock tamper detect
156 * - voltage tamper detect
157 * - RTC counter overflow
158 * - monotonic counter overflow
159 * - external boot
164 * "NON-VALID STATE" + "FAILURE STATE" where a recovery is possible.
168 * In the "NON-VALID STATE" + "FAILURE STATE" we can clear the "FAILURE STATE"
169 * and recover the DryIce unit. By clearing the "NON-VALID STATE" as the last
184 writel(val, imxdi->ioaddr + reg); in di_write_busy_wait()
197 dtcr = readl(imxdi->ioaddr + DTCR); in di_report_tamper_info()
199 dev_emerg(&imxdi->pdev->dev, "DryIce tamper event detected\n"); in di_report_tamper_info()
202 dev_emerg(&imxdi->pdev->dev, "%sVoltage Tamper Event\n", in di_report_tamper_info()
206 dev_emerg(&imxdi->pdev->dev, "%s32768 Hz Clock Tamper Event\n", in di_report_tamper_info()
210 dev_emerg(&imxdi->pdev->dev, "%sTemperature Tamper Event\n", in di_report_tamper_info()
214 dev_emerg(&imxdi->pdev->dev, in di_report_tamper_info()
219 dev_emerg(&imxdi->pdev->dev, "%sExternal Boot Tamper Event\n", in di_report_tamper_info()
223 dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper A Event\n", in di_report_tamper_info()
227 dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper B Event\n", in di_report_tamper_info()
231 dev_emerg(&imxdi->pdev->dev, "%sWire-mesh Tamper Event\n", in di_report_tamper_info()
235 dev_emerg(&imxdi->pdev->dev, in di_report_tamper_info()
236 "%sMonotonic-counter Overflow Event\n", in di_report_tamper_info()
240 dev_emerg(&imxdi->pdev->dev, "%sTimer-counter Overflow Event\n", in di_report_tamper_info()
247 …dev_emerg(&imxdi->pdev->dev, "Please cycle the %s power supply in order to get the DryIce/RTC unit… in di_what_is_to_be_done()
255 dev_dbg(&imxdi->pdev->dev, "DSR register reports: %08X\n", dsr); in di_handle_failure_state()
260 dcr = readl(imxdi->ioaddr + DCR); in di_handle_failure_state()
265 return -ENODEV; in di_handle_failure_state()
269 * into the "NON-VALID STATE" + "FAILURE STATE" in di_handle_failure_state()
273 return -ENODEV; in di_handle_failure_state()
301 sec = readl(imxdi->ioaddr + DTCMR); in di_handle_invalid_state()
303 dev_warn(&imxdi->pdev->dev, in di_handle_invalid_state()
308 * - the TCHL or TCSL bit is set in DCR in di_handle_invalid_state()
310 dcr = readl(imxdi->ioaddr + DCR); in di_handle_invalid_state()
315 return -ENODEV; in di_handle_invalid_state()
319 return -ENODEV; in di_handle_invalid_state()
323 * - the timer counter stops/is stopped if in di_handle_invalid_state()
324 * - its overflow flag is set (TCO in DSR) in di_handle_invalid_state()
325 * -> clear overflow bit to make it count again in di_handle_invalid_state()
326 * - NVF is set in DSR in di_handle_invalid_state()
327 * -> clear non-valid bit to make it count again in di_handle_invalid_state()
328 * - its TCE (DCR) is cleared in di_handle_invalid_state()
329 * -> set TCE to make it count in di_handle_invalid_state()
330 * - it was never set before in di_handle_invalid_state()
331 * -> write a time into it (required again if the NVF was set) in di_handle_invalid_state()
343 return di_handle_valid_state(imxdi, __raw_readl(imxdi->ioaddr + DSR)); in di_handle_invalid_state()
357 dcr = __raw_readl(imxdi->ioaddr + DCR); in di_handle_invalid_and_failure_state()
371 return -ENODEV; in di_handle_invalid_and_failure_state()
376 return -ENODEV; in di_handle_invalid_and_failure_state()
388 dsr = readl(imxdi->ioaddr + DSR); in di_handle_invalid_and_failure_state()
391 dev_warn(&imxdi->pdev->dev, in di_handle_invalid_and_failure_state()
397 * now we are trying to clear the "Security-violation flag" to in di_handle_invalid_and_failure_state()
403 dsr = readl(imxdi->ioaddr + DSR); in di_handle_invalid_and_failure_state()
405 dev_crit(&imxdi->pdev->dev, in di_handle_invalid_and_failure_state()
409 return -ENODEV; in di_handle_invalid_and_failure_state()
414 * "NON-VALID STATE" time to recover everything in di_handle_invalid_and_failure_state()
424 dsr = readl(imxdi->ioaddr + DSR); in di_handle_state()
428 dev_warn(&imxdi->pdev->dev, "Invalid stated unit detected\n"); in di_handle_state()
432 dev_warn(&imxdi->pdev->dev, "Failure stated unit detected\n"); in di_handle_state()
436 dev_warn(&imxdi->pdev->dev, in di_handle_state()
441 dev_notice(&imxdi->pdev->dev, "Unlocked unit detected\n"); in di_handle_state()
455 spin_lock_irqsave(&imxdi->irq_lock, flags); in di_int_enable()
456 writel(readl(imxdi->ioaddr + DIER) | intr, in di_int_enable()
457 imxdi->ioaddr + DIER); in di_int_enable()
458 spin_unlock_irqrestore(&imxdi->irq_lock, flags); in di_int_enable()
468 spin_lock_irqsave(&imxdi->irq_lock, flags); in di_int_disable()
469 writel(readl(imxdi->ioaddr + DIER) & ~intr, in di_int_disable()
470 imxdi->ioaddr + DIER); in di_int_disable()
471 spin_unlock_irqrestore(&imxdi->irq_lock, flags); in di_int_disable()
475 * This function attempts to clear the dryice write-error flag.
485 dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n"); in clear_write_error()
488 writel(DSR_WEF, imxdi->ioaddr + DSR); in clear_write_error()
492 if ((readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0) in clear_write_error()
496 dev_err(&imxdi->pdev->dev, in clear_write_error()
497 "ERROR: Cannot clear write-error flag!\n"); in clear_write_error()
512 mutex_lock(&imxdi->write_mutex); in di_write_wait()
514 /* enable the write-complete interrupt */ in di_write_wait()
517 imxdi->dsr = 0; in di_write_wait()
520 writel(val, imxdi->ioaddr + reg); in di_write_wait()
523 ret = wait_event_interruptible_timeout(imxdi->write_wait, in di_write_wait()
524 imxdi->dsr & (DSR_WCF | DSR_WEF), msecs_to_jiffies(1)); in di_write_wait()
529 dev_warn(&imxdi->pdev->dev, in di_write_wait()
530 "Write-wait timeout " in di_write_wait()
535 if (imxdi->dsr & DSR_WEF) { in di_write_wait()
537 rc = -EIO; in di_write_wait()
541 mutex_unlock(&imxdi->write_mutex); in di_write_wait()
554 now = readl(imxdi->ioaddr + DTCMR); in dryice_rtc_read_time()
570 dcr = readl(imxdi->ioaddr + DCR); in dryice_rtc_set_mmss()
571 dsr = readl(imxdi->ioaddr + DSR); in dryice_rtc_set_mmss()
577 return -EPERM; in dryice_rtc_set_mmss()
582 return -EPERM; in dryice_rtc_set_mmss()
595 return di_write_wait(imxdi, readl(imxdi->ioaddr + DCR) | DCR_TCE, DCR); in dryice_rtc_set_mmss()
620 dcamr = readl(imxdi->ioaddr + DCAMR); in dryice_rtc_read_alarm()
621 rtc_time_to_tm(dcamr, &alarm->time); in dryice_rtc_read_alarm()
624 alarm->enabled = (readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0; in dryice_rtc_read_alarm()
627 mutex_lock(&imxdi->write_mutex); in dryice_rtc_read_alarm()
630 alarm->pending = (readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0; in dryice_rtc_read_alarm()
632 mutex_unlock(&imxdi->write_mutex); in dryice_rtc_read_alarm()
647 rc = rtc_tm_to_time(&alarm->time, &alarm_time); in dryice_rtc_set_alarm()
652 now = readl(imxdi->ioaddr + DTCMR); in dryice_rtc_set_alarm()
654 return -EINVAL; in dryice_rtc_set_alarm()
661 if (alarm->enabled) in dryice_rtc_set_alarm()
686 dier = readl(imxdi->ioaddr + DIER); in dryice_irq()
687 dsr = readl(imxdi->ioaddr + DSR); in dryice_irq()
710 operations. It means the interrupt is for DryIce -Security. in dryice_irq()
712 if (list_empty_careful(&imxdi->write_wait.head)) in dryice_irq()
721 imxdi->dsr |= dsr; in dryice_irq()
723 wake_up_interruptible(&imxdi->write_wait); in dryice_irq()
736 schedule_work(&imxdi->work); in dryice_irq()
755 /* pass the alarm event to the rtc framework. */ in dryice_work()
756 rtc_update_irq(imxdi->rtc, 1, RTC_AF | RTC_IRQF); in dryice_work()
760 * probe for dryice rtc device
769 imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL); in dryice_rtc_probe()
771 return -ENOMEM; in dryice_rtc_probe()
773 imxdi->pdev = pdev; in dryice_rtc_probe()
776 imxdi->ioaddr = devm_ioremap_resource(&pdev->dev, res); in dryice_rtc_probe()
777 if (IS_ERR(imxdi->ioaddr)) in dryice_rtc_probe()
778 return PTR_ERR(imxdi->ioaddr); in dryice_rtc_probe()
780 spin_lock_init(&imxdi->irq_lock); in dryice_rtc_probe()
793 init_waitqueue_head(&imxdi->write_wait); in dryice_rtc_probe()
795 INIT_WORK(&imxdi->work, dryice_work); in dryice_rtc_probe()
797 mutex_init(&imxdi->write_mutex); in dryice_rtc_probe()
799 imxdi->clk = devm_clk_get(&pdev->dev, NULL); in dryice_rtc_probe()
800 if (IS_ERR(imxdi->clk)) in dryice_rtc_probe()
801 return PTR_ERR(imxdi->clk); in dryice_rtc_probe()
802 rc = clk_prepare_enable(imxdi->clk); in dryice_rtc_probe()
811 writel(0, imxdi->ioaddr + DIER); in dryice_rtc_probe()
817 rc = devm_request_irq(&pdev->dev, norm_irq, dryice_irq, in dryice_rtc_probe()
818 IRQF_SHARED, pdev->name, imxdi); in dryice_rtc_probe()
820 dev_warn(&pdev->dev, "interrupt not available.\n"); in dryice_rtc_probe()
824 rc = devm_request_irq(&pdev->dev, sec_irq, dryice_irq, in dryice_rtc_probe()
825 IRQF_SHARED, pdev->name, imxdi); in dryice_rtc_probe()
827 dev_warn(&pdev->dev, "security violation interrupt not available.\n"); in dryice_rtc_probe()
832 imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, in dryice_rtc_probe()
834 if (IS_ERR(imxdi->rtc)) { in dryice_rtc_probe()
835 rc = PTR_ERR(imxdi->rtc); in dryice_rtc_probe()
842 clk_disable_unprepare(imxdi->clk); in dryice_rtc_probe()
851 flush_work(&imxdi->work); in dryice_rtc_remove()
854 writel(0, imxdi->ioaddr + DIER); in dryice_rtc_remove()
856 clk_disable_unprepare(imxdi->clk); in dryice_rtc_remove()
863 { .compatible = "fsl,imx25-rtc" },
882 MODULE_DESCRIPTION("IMX DryIce Realtime Clock Driver (RTC)");