drivers/rtc/rtc-rtd119x.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-rtd119x.c
Extension
.c
Size
5754 bytes
Lines
238
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 rtd119x_rtc {
	void __iomem *base;
	struct clk *clk;
	struct rtc_device *rtcdev;
	unsigned int base_year;
};

static inline int rtd119x_rtc_days_in_year(int year)
{
	return 365 + (is_leap_year(year) ? 1 : 0);
}

static void rtd119x_rtc_reset(struct device *dev)
{
	struct rtd119x_rtc *data = dev_get_drvdata(dev);
	u32 val;

	val = readl_relaxed(data->base + RTD_RTCCR);
	val |= RTD_RTCCR_RTCRST;
	writel_relaxed(val, data->base + RTD_RTCCR);

	val &= ~RTD_RTCCR_RTCRST;
	writel(val, data->base + RTD_RTCCR);
}

static void rtd119x_rtc_set_enabled(struct device *dev, bool enable)
{
	struct rtd119x_rtc *data = dev_get_drvdata(dev);
	u32 val;

	val = readl_relaxed(data->base + RTD_RTCEN);
	if (enable) {
		if ((val & RTD_RTCEN_RTCEN_MASK) == 0x5a)
			return;
		writel_relaxed(0x5a, data->base + RTD_RTCEN);
	} else {
		writel_relaxed(0, data->base + RTD_RTCEN);
	}
}

static int rtd119x_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct rtd119x_rtc *data = dev_get_drvdata(dev);
	s32 day;
	u32 sec;
	unsigned int year;
	int tries = 0;

	while (true) {
		tm->tm_sec = (readl_relaxed(data->base + RTD_RTCSEC) & RTD_RTCSEC_RTCSEC_MASK) >> 1;
		tm->tm_min  = readl_relaxed(data->base + RTD_RTCMIN) & RTD_RTCMIN_RTCMIN_MASK;
		tm->tm_hour = readl_relaxed(data->base + RTD_RTCHR) & RTD_RTCHR_RTCHR_MASK;
		day  =  readl_relaxed(data->base + RTD_RTCDATE1) & RTD_RTCDATE1_RTCDATE1_MASK;
		day |= (readl_relaxed(data->base + RTD_RTCDATE2) & RTD_RTCDATE2_RTCDATE2_MASK) << 8;
		sec  = (readl_relaxed(data->base + RTD_RTCSEC) & RTD_RTCSEC_RTCSEC_MASK) >> 1;
		tries++;

		if (sec == tm->tm_sec)
			break;

		if (tries >= 3)
			return -EINVAL;
	}
	if (tries > 1)
		dev_dbg(dev, "%s: needed %i tries\n", __func__, tries);

	year = data->base_year;
	while (day >= rtd119x_rtc_days_in_year(year)) {
		day -= rtd119x_rtc_days_in_year(year);
		year++;
	}
	tm->tm_year = year - 1900;
	tm->tm_yday = day;

	tm->tm_mon = 0;
	while (day >= rtc_month_days(tm->tm_mon, year)) {
		day -= rtc_month_days(tm->tm_mon, year);
		tm->tm_mon++;
	}
	tm->tm_mday = day + 1;

	return 0;
}

static int rtd119x_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct rtd119x_rtc *data = dev_get_drvdata(dev);
	unsigned int day;
	int i;

Annotation

Implementation Notes