drivers/rtc/rtc-pcf2123.c
Source file repositories/reference/linux-study-clean/drivers/rtc/rtc-pcf2123.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/rtc/rtc-pcf2123.c- Extension
.c- Size
- 12943 bytes
- Lines
- 482
- 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/bcd.hlinux/delay.hlinux/device.hlinux/errno.hlinux/init.hlinux/kernel.hlinux/of.hlinux/string.hlinux/slab.hlinux/rtc.hlinux/spi/spi.hlinux/module.hlinux/regmap.h
Detected Declarations
struct pcf2123_datafunction pcf2123_read_offsetfunction pcf2123_set_offsetfunction pcf2123_rtc_read_timefunction pcf2123_rtc_set_timefunction pcf2123_rtc_alarm_irq_enablefunction pcf2123_rtc_read_alarmfunction pcf2123_rtc_set_alarmfunction pcf2123_rtc_irqfunction pcf2123_resetfunction pcf2123_probe
Annotated Snippet
struct pcf2123_data {
struct rtc_device *rtc;
struct regmap *map;
};
static const struct regmap_config pcf2123_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.read_flag_mask = PCF2123_READ,
.write_flag_mask = PCF2123_WRITE,
.max_register = PCF2123_REG_CTDWN_TMR,
};
static int pcf2123_read_offset(struct device *dev, long *offset)
{
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev);
int ret, val;
unsigned int reg;
ret = regmap_read(pcf2123->map, PCF2123_REG_OFFSET, ®);
if (ret)
return ret;
val = sign_extend32((reg & OFFSET_MASK), OFFSET_SIGN_BIT);
if (reg & OFFSET_COARSE)
val *= 2;
*offset = ((long)val) * OFFSET_STEP;
return 0;
}
/*
* The offset register is a 7 bit signed value with a coarse bit in bit 7.
* The main difference between the two is normal offset adjusts the first
* second of n minutes every other hour, with 61, 62 and 63 being shoved
* into the 60th minute.
* The coarse adjustment does the same, but every hour.
* the two overlap, with every even normal offset value corresponding
* to a coarse offset. Based on this algorithm, it seems that despite the
* name, coarse offset is a better fit for overlapping values.
*/
static int pcf2123_set_offset(struct device *dev, long offset)
{
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev);
s8 reg;
if (offset > OFFSET_STEP * 127)
reg = 127;
else if (offset < OFFSET_STEP * -128)
reg = -128;
else
reg = DIV_ROUND_CLOSEST(offset, OFFSET_STEP);
/* choose fine offset only for odd values in the normal range */
if (reg & 1 && reg <= 63 && reg >= -64) {
/* Normal offset. Clear the coarse bit */
reg &= ~OFFSET_COARSE;
} else {
/* Coarse offset. Divide by 2 and set the coarse bit */
reg >>= 1;
reg |= OFFSET_COARSE;
}
return regmap_write(pcf2123->map, PCF2123_REG_OFFSET, (unsigned int)reg);
}
static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev);
u8 rxbuf[7];
int ret;
ret = regmap_bulk_read(pcf2123->map, PCF2123_REG_SC, rxbuf,
sizeof(rxbuf));
if (ret)
return ret;
if (rxbuf[0] & OSC_HAS_STOPPED) {
dev_info(dev, "clock was stopped. Time is not valid\n");
return -EINVAL;
}
tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F);
tm->tm_min = bcd2bin(rxbuf[1] & 0x7F);
tm->tm_hour = bcd2bin(rxbuf[2] & 0x3F); /* rtc hr 0-23 */
tm->tm_mday = bcd2bin(rxbuf[3] & 0x3F);
tm->tm_wday = rxbuf[4] & 0x07;
tm->tm_mon = bcd2bin(rxbuf[5] & 0x1F) - 1; /* rtc mn 1-12 */
Annotation
- Immediate include surface: `linux/bcd.h`, `linux/delay.h`, `linux/device.h`, `linux/errno.h`, `linux/init.h`, `linux/kernel.h`, `linux/of.h`, `linux/string.h`.
- Detected declarations: `struct pcf2123_data`, `function pcf2123_read_offset`, `function pcf2123_set_offset`, `function pcf2123_rtc_read_time`, `function pcf2123_rtc_set_time`, `function pcf2123_rtc_alarm_irq_enable`, `function pcf2123_rtc_read_alarm`, `function pcf2123_rtc_set_alarm`, `function pcf2123_rtc_irq`, `function pcf2123_reset`.
- 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.