Lines Matching +full:write +full:- +full:to +full:- +full:write
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
21 * only simultaneous accesses we need to deal with is updating DryIce
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
48 #define DCAMR_UNSET 0xFFFFFFFF /* doomsday - 1 sec */
54 #define DSR_WBF (1 << 10) /* Write Busy Flag */
55 #define DSR_WNF (1 << 9) /* Write Next Flag */
56 #define DSR_WCF (1 << 8) /* Write Complete Flag */
57 #define DSR_WEF (1 << 7) /* Write Error Flag */
59 #define DSR_NVF (1 << 1) /* Non-Valid Flag */
63 #define DIER_WNIE (1 << 9) /* Write Next Interrupt Enable */
64 #define DIER_WCIE (1 << 8) /* Write Complete Interrupt Enable */
65 #define DIER_WEIE (1 << 7) /* Write Error Interrupt Enable */
69 * struct imxdi_dev - private imxdi rtc data
70 * @pdev: pionter to platform dev
71 * @rtc: pointer to rtc struct
77 * @write_wait: registers write complete queue
78 * @write_mutex: serialize registers write
101 spin_lock_irqsave(&imxdi->irq_lock, flags); in di_int_enable()
102 __raw_writel(__raw_readl(imxdi->ioaddr + DIER) | intr, in di_int_enable()
103 imxdi->ioaddr + DIER); in di_int_enable()
104 spin_unlock_irqrestore(&imxdi->irq_lock, flags); in di_int_enable()
114 spin_lock_irqsave(&imxdi->irq_lock, flags); in di_int_disable()
115 __raw_writel(__raw_readl(imxdi->ioaddr + DIER) & ~intr, in di_int_disable()
116 imxdi->ioaddr + DIER); in di_int_disable()
117 spin_unlock_irqrestore(&imxdi->irq_lock, flags); in di_int_disable()
121 * This function attempts to clear the dryice write-error flag.
123 * A dryice write error is similar to a bus fault and should not occur in
124 * normal operation. Clearing the flag requires another write, so the root
125 * cause of the problem may need to be fixed before the flag can be cleared.
131 dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n"); in clear_write_error()
133 /* clear the write error flag */ in clear_write_error()
134 __raw_writel(DSR_WEF, imxdi->ioaddr + DSR); in clear_write_error()
136 /* wait for it to take effect */ in clear_write_error()
138 if ((__raw_readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0) in clear_write_error()
142 dev_err(&imxdi->pdev->dev, in clear_write_error()
143 "ERROR: Cannot clear write-error flag!\n"); in clear_write_error()
147 * Write a dryice register and wait until it completes.
149 * This function uses interrupts to determine when the
150 * write has completed.
158 mutex_lock(&imxdi->write_mutex); in di_write_wait()
160 /* enable the write-complete interrupt */ in di_write_wait()
163 imxdi->dsr = 0; in di_write_wait()
165 /* do the register write */ in di_write_wait()
166 __raw_writel(val, imxdi->ioaddr + reg); in di_write_wait()
168 /* wait for the write to finish */ in di_write_wait()
169 ret = wait_event_interruptible_timeout(imxdi->write_wait, in di_write_wait()
170 imxdi->dsr & (DSR_WCF | DSR_WEF), msecs_to_jiffies(1)); in di_write_wait()
175 dev_warn(&imxdi->pdev->dev, in di_write_wait()
176 "Write-wait timeout " in di_write_wait()
180 /* check for write error */ in di_write_wait()
181 if (imxdi->dsr & DSR_WEF) { in di_write_wait()
183 rc = -EIO; in di_write_wait()
187 mutex_unlock(&imxdi->write_mutex); in di_write_wait()
200 now = __raw_readl(imxdi->ioaddr + DTCMR); in dryice_rtc_read_time()
245 dcamr = __raw_readl(imxdi->ioaddr + DCAMR); in dryice_rtc_read_alarm()
246 rtc_time_to_tm(dcamr, &alarm->time); in dryice_rtc_read_alarm()
249 alarm->enabled = (__raw_readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0; in dryice_rtc_read_alarm()
251 /* don't allow the DSR read to mess up DSR_WCF */ in dryice_rtc_read_alarm()
252 mutex_lock(&imxdi->write_mutex); in dryice_rtc_read_alarm()
255 alarm->pending = (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0; in dryice_rtc_read_alarm()
257 mutex_unlock(&imxdi->write_mutex); in dryice_rtc_read_alarm()
272 rc = rtc_tm_to_time(&alarm->time, &alarm_time); in dryice_rtc_set_alarm()
277 now = __raw_readl(imxdi->ioaddr + DTCMR); in dryice_rtc_set_alarm()
279 return -EINVAL; in dryice_rtc_set_alarm()
281 /* write the new alarm time */ in dryice_rtc_set_alarm()
286 if (alarm->enabled) in dryice_rtc_set_alarm()
311 dier = __raw_readl(imxdi->ioaddr + DIER); in dryice_norm_irq()
313 /* handle write complete and write error cases */ in dryice_norm_irq()
315 /*If the write wait queue is empty then there is no pending in dryice_norm_irq()
316 operations. It means the interrupt is for DryIce -Security. in dryice_norm_irq()
318 if (list_empty_careful(&imxdi->write_wait.task_list)) in dryice_norm_irq()
322 dsr = __raw_readl(imxdi->ioaddr + DSR); in dryice_norm_irq()
328 imxdi->dsr |= dsr; in dryice_norm_irq()
330 wake_up_interruptible(&imxdi->write_wait); in dryice_norm_irq()
338 dsr = __raw_readl(imxdi->ioaddr + DSR); in dryice_norm_irq()
344 schedule_work(&imxdi->work); in dryice_norm_irq()
353 * on the write completion.
363 /* pass the alarm event to the rtc framework. */ in dryice_work()
364 rtc_update_irq(imxdi->rtc, 1, RTC_AF | RTC_IRQF); in dryice_work()
378 return -ENODEV; in dryice_rtc_probe()
380 imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL); in dryice_rtc_probe()
382 return -ENOMEM; in dryice_rtc_probe()
384 imxdi->pdev = pdev; in dryice_rtc_probe()
386 if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), in dryice_rtc_probe()
387 pdev->name)) in dryice_rtc_probe()
388 return -EBUSY; in dryice_rtc_probe()
390 imxdi->ioaddr = devm_ioremap(&pdev->dev, res->start, in dryice_rtc_probe()
392 if (imxdi->ioaddr == NULL) in dryice_rtc_probe()
393 return -ENOMEM; in dryice_rtc_probe()
395 imxdi->irq = platform_get_irq(pdev, 0); in dryice_rtc_probe()
396 if (imxdi->irq < 0) in dryice_rtc_probe()
397 return imxdi->irq; in dryice_rtc_probe()
399 init_waitqueue_head(&imxdi->write_wait); in dryice_rtc_probe()
401 INIT_WORK(&imxdi->work, dryice_work); in dryice_rtc_probe()
403 mutex_init(&imxdi->write_mutex); in dryice_rtc_probe()
405 imxdi->clk = clk_get(&pdev->dev, NULL); in dryice_rtc_probe()
406 if (IS_ERR(imxdi->clk)) in dryice_rtc_probe()
407 return PTR_ERR(imxdi->clk); in dryice_rtc_probe()
408 clk_enable(imxdi->clk); in dryice_rtc_probe()
415 __raw_writel(0, imxdi->ioaddr + DIER); in dryice_rtc_probe()
417 rc = devm_request_irq(&pdev->dev, imxdi->irq, dryice_norm_irq, in dryice_rtc_probe()
418 IRQF_SHARED, pdev->name, imxdi); in dryice_rtc_probe()
420 dev_warn(&pdev->dev, "interrupt not available.\n"); in dryice_rtc_probe()
425 if (__raw_readl(imxdi->ioaddr + DSR) & DSR_NVF) { in dryice_rtc_probe()
440 if (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) { in dryice_rtc_probe()
446 /* the timer won't count if it has never been written to */ in dryice_rtc_probe()
447 if (__raw_readl(imxdi->ioaddr + DTCMR) == 0) { in dryice_rtc_probe()
454 if (!(__raw_readl(imxdi->ioaddr + DCR) & DCR_TCE)) { in dryice_rtc_probe()
456 __raw_readl(imxdi->ioaddr + DCR) | DCR_TCE, in dryice_rtc_probe()
463 imxdi->rtc = rtc_device_register(pdev->name, &pdev->dev, in dryice_rtc_probe()
465 if (IS_ERR(imxdi->rtc)) { in dryice_rtc_probe()
466 rc = PTR_ERR(imxdi->rtc); in dryice_rtc_probe()
473 clk_disable(imxdi->clk); in dryice_rtc_probe()
474 clk_put(imxdi->clk); in dryice_rtc_probe()
483 flush_work(&imxdi->work); in dryice_rtc_remove()
486 __raw_writel(0, imxdi->ioaddr + DIER); in dryice_rtc_remove()
488 rtc_device_unregister(imxdi->rtc); in dryice_rtc_remove()
490 clk_disable(imxdi->clk); in dryice_rtc_remove()
491 clk_put(imxdi->clk); in dryice_rtc_remove()