drivers/rtc/rtc-digicolor.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-digicolor.c
Extension
.c
Size
5281 bytes
Lines
225
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 dc_rtc {
	struct rtc_device	*rtc_dev;
	void __iomem		*regs;
};

static int dc_rtc_cmds(struct dc_rtc *rtc, const u8 *cmds, int len)
{
	u8 val;
	int i, ret;

	for (i = 0; i < len; i++) {
		writeb_relaxed((cmds[i] & DC_RTC_CMD_MASK) | DC_RTC_GO_BUSY,
			       rtc->regs + DC_RTC_CONTROL);
		ret = readb_relaxed_poll_timeout(
			rtc->regs + DC_RTC_CONTROL, val,
			!(val & DC_RTC_GO_BUSY), CMD_DELAY_US, CMD_TIMEOUT_US);
		if (ret < 0)
			return ret;
	}

	return 0;
}

static int dc_rtc_read(struct dc_rtc *rtc, unsigned long *val)
{
	static const u8 read_cmds[] = {CMD_READ, CMD_NOP};
	u32 reference, time1, time2;
	int ret;

	ret = dc_rtc_cmds(rtc, read_cmds, ARRAY_SIZE(read_cmds));
	if (ret < 0)
		return ret;

	reference = readl_relaxed(rtc->regs + DC_RTC_REFERENCE);
	time1 = readl_relaxed(rtc->regs + DC_RTC_TIME);
	/* Read twice to ensure consistency */
	while (1) {
		time2 = readl_relaxed(rtc->regs + DC_RTC_TIME);
		if (time1 == time2)
			break;
		time1 = time2;
	}

	*val = reference + time1;
	return 0;
}

static int dc_rtc_write(struct dc_rtc *rtc, u32 val)
{
	static const u8 write_cmds[] = {CMD_WRITE, CMD_NOP, CMD_RESET, CMD_NOP};

	writel_relaxed(val, rtc->regs + DC_RTC_REFERENCE);
	return dc_rtc_cmds(rtc, write_cmds, ARRAY_SIZE(write_cmds));
}

static int dc_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct dc_rtc *rtc = dev_get_drvdata(dev);
	unsigned long now;
	int ret;

	ret = dc_rtc_read(rtc, &now);
	if (ret < 0)
		return ret;
	rtc_time64_to_tm(now, tm);

	return 0;
}

static int dc_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct dc_rtc *rtc = dev_get_drvdata(dev);

	return dc_rtc_write(rtc, rtc_tm_to_time64(tm));
}

static int dc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
	struct dc_rtc *rtc = dev_get_drvdata(dev);
	u32 alarm_reg, reference;
	unsigned long now;
	int ret;

	alarm_reg = readl_relaxed(rtc->regs + DC_RTC_ALARM);
	reference = readl_relaxed(rtc->regs + DC_RTC_REFERENCE);
	rtc_time64_to_tm(reference + alarm_reg, &alarm->time);

	ret = dc_rtc_read(rtc, &now);
	if (ret < 0)
		return ret;

Annotation

Implementation Notes