// SPDX-License-Identifier: GPL-2.0-or-later /* * Real Time Clock interface for StrongARM SA1x00 and XScale PXA2xx * * Copyright (c) 2000 Nils Faerber * * Based on rtc.c by Paul Gortmaker * * Original Driver by Nils Faerber <nils@kernelconcepts.de> * * Modifications from: * CIH <cih@coventive.com> * Nicolas Pitre <nico@fluxnic.net> * Andrew Christian <andrew.christian@hp.com> * * Converted to the RTC subsystem and Driver Model * by Richard Purdie <rpurdie@rpsys.net>
*/
rtsr = readl_relaxed(info->rtsr); /* clear interrupt sources */
writel_relaxed(0, info->rtsr); /* Fix for a nasty initialization problem the in SA11xx RTSR register.
* See also the comments in sa1100_rtc_probe(). */ if (rtsr & (RTSR_ALE | RTSR_HZE)) { /* This is the original code, before there was the if test * above. This code does not clear interrupts that were not
* enabled. */
writel_relaxed((RTSR_AL | RTSR_HZ) & (rtsr >> 2), info->rtsr);
} else { /* For some reason, it is possible to enter this routine * without interruptions enabled, it has been tested with * several units (Bug in SA11xx chip?). * * This situation leads to an infinite "loop" of interrupt * routine calling and as a result the processor seems to
* lock on its first call to open(). */
writel_relaxed(RTSR_AL | RTSR_HZ, info->rtsr);
}
/* clear alarm interrupt if it has occurred */ if (rtsr & RTSR_AL)
rtsr &= ~RTSR_ALE;
writel_relaxed(rtsr & (RTSR_ALE | RTSR_HZE), info->rtsr);
/* update irq data & counter */ if (rtsr & RTSR_AL)
events |= RTC_AF | RTC_IRQF; if (rtsr & RTSR_HZ)
events |= RTC_UF | RTC_IRQF;
int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
{ int ret;
spin_lock_init(&info->lock);
info->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(info->clk)) {
dev_err(&pdev->dev, "failed to find rtc clock source\n"); return PTR_ERR(info->clk);
}
ret = clk_prepare_enable(info->clk); if (ret) return ret; /* * According to the manual we should be able to let RTTR be zero * and then a default diviser for a 32.768KHz clock is used. * Apparently this doesn't work, at least for my SA1110 rev 5. * If the clock divider is uninitialized then reset it to the * default value to get the 1Hz clock.
*/ if (readl_relaxed(info->rttr) == 0) {
writel_relaxed(RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16), info->rttr);
dev_warn(&pdev->dev, "warning: " "initializing default clock divider/trim value\n"); /* The current RTC value probably doesn't make sense either */
writel_relaxed(0, info->rcnr);
}
ret = devm_rtc_register_device(info->rtc); if (ret) {
clk_disable_unprepare(info->clk); return ret;
}
/* Fix for a nasty initialization problem the in SA11xx RTSR register. * See also the comments in sa1100_rtc_interrupt(). * * Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an * interrupt pending, even though interrupts were never enabled. * In this case, this bit it must be reset before enabling * interruptions to avoid a nonexistent interrupt to occur. * * In principle, the same problem would apply to bit 0, although it has * never been observed to happen. * * This issue is addressed both here and in sa1100_rtc_interrupt(). * If the issue is not addressed here, in the times when the processor * wakes up with the bit set there will be one spurious interrupt. * * The issue is also dealt with in sa1100_rtc_interrupt() to be on the * safe side, once the condition that lead to this strange * initialization is unknown and could in principle happen during * normal processing. * * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
* the corresponding bits in RTSR. */
writel_relaxed(RTSR_AL | RTSR_HZ, info->rtsr);
return 0;
}
EXPORT_SYMBOL_GPL(sa1100_rtc_init);
staticint sa1100_rtc_probe(struct platform_device *pdev)
{ struct sa1100_rtc *info; void __iomem *base; int irq_1hz, irq_alarm; int ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.