drivers/rtc/rtc-cpcap.c

Source file repositories/reference/linux-study-clean/drivers/rtc/rtc-cpcap.c

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-cpcap.c
Extension
.c
Size
8226 bytes
Lines
326
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct cpcap_time {
	int day;
	int tod1;
	int tod2;
};

struct cpcap_rtc {
	struct regmap *regmap;
	struct rtc_device *rtc_dev;
	u16 vendor;
	int alarm_irq;
	bool alarm_enabled;
	int update_irq;
	bool update_enabled;
};

static void cpcap2rtc_time(struct rtc_time *rtc, struct cpcap_time *cpcap)
{
	unsigned long int tod;
	unsigned long int time;

	tod = (cpcap->tod1 & TOD1_MASK) | ((cpcap->tod2 & TOD2_MASK) << 8);
	time = tod + ((cpcap->day & DAY_MASK) * SECS_PER_DAY);

	rtc_time64_to_tm(time, rtc);
}

static void rtc2cpcap_time(struct cpcap_time *cpcap, struct rtc_time *rtc)
{
	unsigned long time;

	time = rtc_tm_to_time64(rtc);

	cpcap->day = time / SECS_PER_DAY;
	time %= SECS_PER_DAY;
	cpcap->tod2 = (time >> 8) & TOD2_MASK;
	cpcap->tod1 = time & TOD1_MASK;
}

static int cpcap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
	struct cpcap_rtc *rtc = dev_get_drvdata(dev);

	if (rtc->alarm_enabled == enabled)
		return 0;

	if (enabled)
		enable_irq(rtc->alarm_irq);
	else
		disable_irq(rtc->alarm_irq);

	rtc->alarm_enabled = !!enabled;

	return 0;
}

static int cpcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct cpcap_rtc *rtc;
	struct cpcap_time cpcap_tm;
	int temp_tod2;
	int ret;

	rtc = dev_get_drvdata(dev);

	ret = regmap_read(rtc->regmap, CPCAP_REG_TOD2, &temp_tod2);
	ret |= regmap_read(rtc->regmap, CPCAP_REG_DAY, &cpcap_tm.day);
	ret |= regmap_read(rtc->regmap, CPCAP_REG_TOD1, &cpcap_tm.tod1);
	ret |= regmap_read(rtc->regmap, CPCAP_REG_TOD2, &cpcap_tm.tod2);

	if (temp_tod2 > cpcap_tm.tod2)
		ret |= regmap_read(rtc->regmap, CPCAP_REG_DAY, &cpcap_tm.day);

	if (ret) {
		dev_err(dev, "Failed to read time\n");
		return -EIO;
	}

	cpcap2rtc_time(tm, &cpcap_tm);

	return 0;
}

static int cpcap_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct cpcap_rtc *rtc;
	struct cpcap_time cpcap_tm;
	int ret = 0;

	rtc = dev_get_drvdata(dev);

Annotation

Implementation Notes