drivers/rtc/rtc-pl031.c
Source file repositories/reference/linux-study-clean/drivers/rtc/rtc-pl031.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/rtc/rtc-pl031.c- Extension
.c- Size
- 12342 bytes
- Lines
- 471
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/rtc.hlinux/init.hlinux/interrupt.hlinux/amba/bus.hlinux/io.hlinux/bcd.hlinux/delay.hlinux/pm_wakeirq.hlinux/slab.h
Detected Declarations
struct pl031_vendor_datastruct pl031_localfunction pl031_alarm_irq_enablefunction pl031_stv2_tm_to_timefunction pl031_stv2_time_to_tmfunction pl031_stv2_read_timefunction pl031_stv2_set_timefunction pl031_stv2_read_alarmfunction pl031_stv2_set_alarmfunction pl031_interruptfunction pl031_read_timefunction pl031_set_timefunction pl031_read_alarmfunction pl031_set_alarmfunction pl031_removefunction pl031_probe
Annotated Snippet
struct pl031_vendor_data {
struct rtc_class_ops ops;
bool clockwatch;
bool st_weekday;
unsigned long irqflags;
time64_t range_min;
timeu64_t range_max;
};
struct pl031_local {
struct pl031_vendor_data *vendor;
struct rtc_device *rtc;
void __iomem *base;
};
static int pl031_alarm_irq_enable(struct device *dev,
unsigned int enabled)
{
struct pl031_local *ldata = dev_get_drvdata(dev);
unsigned long imsc;
/* Clear any pending alarm interrupts. */
writel(RTC_BIT_AI, ldata->base + RTC_ICR);
imsc = readl(ldata->base + RTC_IMSC);
if (enabled == 1)
writel(imsc | RTC_BIT_AI, ldata->base + RTC_IMSC);
else
writel(imsc & ~RTC_BIT_AI, ldata->base + RTC_IMSC);
return 0;
}
/*
* Convert Gregorian date to ST v2 RTC format.
*/
static int pl031_stv2_tm_to_time(struct device *dev,
struct rtc_time *tm, unsigned long *st_time,
unsigned long *bcd_year)
{
int year = tm->tm_year + 1900;
int wday = tm->tm_wday;
/* wday masking is not working in hardware so wday must be valid */
if (wday < -1 || wday > 6) {
dev_err(dev, "invalid wday value %d\n", tm->tm_wday);
return -EINVAL;
} else if (wday == -1) {
/* wday is not provided, calculate it here */
struct rtc_time calc_tm;
rtc_time64_to_tm(rtc_tm_to_time64(tm), &calc_tm);
wday = calc_tm.tm_wday;
}
*bcd_year = (bin2bcd(year % 100) | bin2bcd(year / 100) << 8);
*st_time = ((tm->tm_mon + 1) << RTC_MON_SHIFT)
| (tm->tm_mday << RTC_MDAY_SHIFT)
| ((wday + 1) << RTC_WDAY_SHIFT)
| (tm->tm_hour << RTC_HOUR_SHIFT)
| (tm->tm_min << RTC_MIN_SHIFT)
| (tm->tm_sec << RTC_SEC_SHIFT);
return 0;
}
/*
* Convert ST v2 RTC format to Gregorian date.
*/
static int pl031_stv2_time_to_tm(unsigned long st_time, unsigned long bcd_year,
struct rtc_time *tm)
{
tm->tm_year = bcd2bin(bcd_year) + (bcd2bin(bcd_year >> 8) * 100);
tm->tm_mon = ((st_time & RTC_MON_MASK) >> RTC_MON_SHIFT) - 1;
tm->tm_mday = ((st_time & RTC_MDAY_MASK) >> RTC_MDAY_SHIFT);
tm->tm_wday = ((st_time & RTC_WDAY_MASK) >> RTC_WDAY_SHIFT) - 1;
tm->tm_hour = ((st_time & RTC_HOUR_MASK) >> RTC_HOUR_SHIFT);
tm->tm_min = ((st_time & RTC_MIN_MASK) >> RTC_MIN_SHIFT);
tm->tm_sec = ((st_time & RTC_SEC_MASK) >> RTC_SEC_SHIFT);
tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
tm->tm_year -= 1900;
return 0;
}
static int pl031_stv2_read_time(struct device *dev, struct rtc_time *tm)
{
Annotation
- Immediate include surface: `linux/module.h`, `linux/rtc.h`, `linux/init.h`, `linux/interrupt.h`, `linux/amba/bus.h`, `linux/io.h`, `linux/bcd.h`, `linux/delay.h`.
- Detected declarations: `struct pl031_vendor_data`, `struct pl031_local`, `function pl031_alarm_irq_enable`, `function pl031_stv2_tm_to_time`, `function pl031_stv2_time_to_tm`, `function pl031_stv2_read_time`, `function pl031_stv2_set_time`, `function pl031_stv2_read_alarm`, `function pl031_stv2_set_alarm`, `function pl031_interrupt`.
- Atlas domain: Driver Families / drivers/rtc.
- Implementation status: source implementation candidate.
- 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.