drivers/rtc/rtc-ma35d1.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-ma35d1.c
Extension
.c
Size
7758 bytes
Lines
305
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 ma35_rtc {
	int irq_num;
	void __iomem *rtc_reg;
	struct rtc_device *rtcdev;
};

static u32 rtc_reg_read(struct ma35_rtc *p, u32 offset)
{
	return __raw_readl(p->rtc_reg + offset);
}

static inline void rtc_reg_write(struct ma35_rtc *p, u32 offset, u32 value)
{
	__raw_writel(value, p->rtc_reg + offset);
}

static irqreturn_t ma35d1_rtc_interrupt(int irq, void *data)
{
	struct ma35_rtc *rtc = (struct ma35_rtc *)data;
	unsigned long events = 0, rtc_irq;

	rtc_irq = rtc_reg_read(rtc, MA35_REG_RTC_INTSTS);

	if (rtc_irq & RTC_INTSTS_ALMIF) {
		rtc_reg_write(rtc, MA35_REG_RTC_INTSTS, RTC_INTSTS_ALMIF);
		events |= RTC_AF | RTC_IRQF;
	}

	rtc_update_irq(rtc->rtcdev, 1, events);

	return IRQ_HANDLED;
}

static int ma35d1_rtc_init(struct ma35_rtc *rtc, u32 ms_timeout)
{
	const unsigned long timeout = jiffies + msecs_to_jiffies(ms_timeout);

	do {
		if (rtc_reg_read(rtc, MA35_REG_RTC_INIT) & RTC_INIT_ACTIVE)
			return 0;

		rtc_reg_write(rtc, MA35_REG_RTC_INIT, RTC_INIT_MAGIC_CODE);

		mdelay(1);

	} while (time_before(jiffies, timeout));

	return -ETIMEDOUT;
}

static int ma35d1_alarm_irq_enable(struct device *dev, u32 enabled)
{
	struct ma35_rtc *rtc = dev_get_drvdata(dev);
	u32 reg_ien;

	reg_ien = rtc_reg_read(rtc, MA35_REG_RTC_INTEN);

	if (enabled)
		rtc_reg_write(rtc, MA35_REG_RTC_INTEN, reg_ien | RTC_INTEN_ALMIEN);
	else
		rtc_reg_write(rtc, MA35_REG_RTC_INTEN, reg_ien & ~RTC_INTEN_ALMIEN);

	return 0;
}

static int ma35d1_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct ma35_rtc *rtc = dev_get_drvdata(dev);
	u32 time, cal, wday;

	do {
		time = rtc_reg_read(rtc, MA35_REG_RTC_TIME);
		cal  = rtc_reg_read(rtc, MA35_REG_RTC_CAL);
		wday = rtc_reg_read(rtc, MA35_REG_RTC_WEEKDAY);
	} while (time != rtc_reg_read(rtc, MA35_REG_RTC_TIME) ||
		 cal != rtc_reg_read(rtc, MA35_REG_RTC_CAL));

	tm->tm_mday = bcd2bin(cal >> 0);
	tm->tm_wday = wday;
	tm->tm_mon = bcd2bin(cal >> 8);
	tm->tm_mon = tm->tm_mon - 1;
	tm->tm_year = bcd2bin(cal >> 16) + 100;

	tm->tm_sec = bcd2bin(time >> 0);
	tm->tm_min = bcd2bin(time >> 8);
	tm->tm_hour = bcd2bin(time >> 16);

	return rtc_valid_tm(tm);
}

Annotation

Implementation Notes