drivers/rtc/rtc-at91rm9200.c
Source file repositories/reference/linux-study-clean/drivers/rtc/rtc-at91rm9200.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/rtc/rtc-at91rm9200.c- Extension
.c- Size
- 17648 bytes
- Lines
- 657
- Domain
- Driver Families
- Bucket
- drivers/rtc
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bcd.hlinux/bitfield.hlinux/clk.hlinux/completion.hlinux/interrupt.hlinux/ioctl.hlinux/io.hlinux/kernel.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/rtc.hlinux/spinlock.hlinux/suspend.hlinux/time.hlinux/uaccess.h
Detected Declarations
struct at91_rtc_configfunction at91_rtc_write_ierfunction at91_rtc_write_idrfunction at91_rtc_read_imrfunction at91_rtc_decodetimefunction at91_rtc_readtimefunction at91_rtc_settimefunction at91_rtc_readalarmfunction at91_rtc_setalarmfunction at91_rtc_alarm_irq_enablefunction at91_rtc_readoffsetfunction at91_rtc_setoffsetfunction at91_rtc_interruptfunction at91_rtc_probefunction at91_rtc_removefunction at91_rtc_shutdownfunction at91_rtc_suspendfunction at91_rtc_resume
Annotated Snippet
struct at91_rtc_config {
bool use_shadow_imr;
bool has_correction;
};
static const struct at91_rtc_config *at91_rtc_config;
static DECLARE_COMPLETION(at91_rtc_updated);
static DECLARE_COMPLETION(at91_rtc_upd_rdy);
static void __iomem *at91_rtc_regs;
static int irq;
static DEFINE_SPINLOCK(at91_rtc_lock);
static u32 at91_rtc_shadow_imr;
static bool suspended;
static DEFINE_SPINLOCK(suspended_lock);
static unsigned long cached_events;
static u32 at91_rtc_imr;
static struct clk *sclk;
static void at91_rtc_write_ier(u32 mask)
{
unsigned long flags;
spin_lock_irqsave(&at91_rtc_lock, flags);
at91_rtc_shadow_imr |= mask;
at91_rtc_write(AT91_RTC_IER, mask);
spin_unlock_irqrestore(&at91_rtc_lock, flags);
}
static void at91_rtc_write_idr(u32 mask)
{
unsigned long flags;
spin_lock_irqsave(&at91_rtc_lock, flags);
at91_rtc_write(AT91_RTC_IDR, mask);
/*
* Register read back (of any RTC-register) needed to make sure
* IDR-register write has reached the peripheral before updating
* shadow mask.
*
* Note that there is still a possibility that the mask is updated
* before interrupts have actually been disabled in hardware. The only
* way to be certain would be to poll the IMR-register, which is
* the very register we are trying to emulate. The register read back
* is a reasonable heuristic.
*/
at91_rtc_read(AT91_RTC_SR);
at91_rtc_shadow_imr &= ~mask;
spin_unlock_irqrestore(&at91_rtc_lock, flags);
}
static u32 at91_rtc_read_imr(void)
{
unsigned long flags;
u32 mask;
if (at91_rtc_config->use_shadow_imr) {
spin_lock_irqsave(&at91_rtc_lock, flags);
mask = at91_rtc_shadow_imr;
spin_unlock_irqrestore(&at91_rtc_lock, flags);
} else {
mask = at91_rtc_read(AT91_RTC_IMR);
}
return mask;
}
/*
* Decode time/date into rtc_time structure
*/
static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg,
struct rtc_time *tm)
{
unsigned int time, date;
/* must read twice in case it changes */
do {
time = at91_rtc_read(timereg);
date = at91_rtc_read(calreg);
} while ((time != at91_rtc_read(timereg)) ||
(date != at91_rtc_read(calreg)));
tm->tm_sec = bcd2bin(FIELD_GET(AT91_RTC_SEC, time));
tm->tm_min = bcd2bin(FIELD_GET(AT91_RTC_MIN, time));
tm->tm_hour = bcd2bin(FIELD_GET(AT91_RTC_HOUR, time));
/*
* The Calendar Alarm register does not have a field for
* the year - so these will return an invalid value.
*/
tm->tm_year = bcd2bin(date & AT91_RTC_CENT) * 100; /* century */
Annotation
- Immediate include surface: `linux/bcd.h`, `linux/bitfield.h`, `linux/clk.h`, `linux/completion.h`, `linux/interrupt.h`, `linux/ioctl.h`, `linux/io.h`, `linux/kernel.h`.
- Detected declarations: `struct at91_rtc_config`, `function at91_rtc_write_ier`, `function at91_rtc_write_idr`, `function at91_rtc_read_imr`, `function at91_rtc_decodetime`, `function at91_rtc_readtime`, `function at91_rtc_settime`, `function at91_rtc_readalarm`, `function at91_rtc_setalarm`, `function at91_rtc_alarm_irq_enable`.
- Atlas domain: Driver Families / drivers/rtc.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.