drivers/rtc/rtc-mxc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-mxc.c
Extension
.c
Size
10650 bytes
Lines
405
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 rtc_plat_data {
	struct rtc_device *rtc;
	void __iomem *ioaddr;
	int irq;
	struct clk *clk_ref;
	struct clk *clk_ipg;
	struct rtc_time g_rtc_alarm;
	enum imx_rtc_type devtype;
};

static const struct of_device_id imx_rtc_dt_ids[] = {
	{ .compatible = "fsl,imx1-rtc", .data = (const void *)IMX1_RTC },
	{ .compatible = "fsl,imx21-rtc", .data = (const void *)IMX21_RTC },
	{}
};
MODULE_DEVICE_TABLE(of, imx_rtc_dt_ids);

static inline int is_imx1_rtc(struct rtc_plat_data *data)
{
	return data->devtype == IMX1_RTC;
}

/*
 * This function is used to obtain the RTC time or the alarm value in
 * second.
 */
static time64_t get_alarm_or_time(struct device *dev, int time_alarm)
{
	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
	void __iomem *ioaddr = pdata->ioaddr;
	u32 day = 0, hr = 0, min = 0, sec = 0, hr_min = 0;

	switch (time_alarm) {
	case MXC_RTC_TIME:
		day = readw(ioaddr + RTC_DAYR);
		hr_min = readw(ioaddr + RTC_HOURMIN);
		sec = readw(ioaddr + RTC_SECOND);
		break;
	case MXC_RTC_ALARM:
		day = readw(ioaddr + RTC_DAYALARM);
		hr_min = readw(ioaddr + RTC_ALRM_HM) & 0xffff;
		sec = readw(ioaddr + RTC_ALRM_SEC);
		break;
	}

	hr = hr_min >> 8;
	min = hr_min & 0xff;

	return ((((time64_t)day * 24 + hr) * 60) + min) * 60 + sec;
}

/*
 * This function sets the RTC alarm value or the time value.
 */
static void set_alarm_or_time(struct device *dev, int time_alarm, time64_t time)
{
	u32 tod, day, hr, min, sec, temp;
	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
	void __iomem *ioaddr = pdata->ioaddr;

	day = div_s64_rem(time, 86400, &tod);

	/* time is within a day now */
	hr = tod / 3600;
	tod -= hr * 3600;

	/* time is within an hour now */
	min = tod / 60;
	sec = tod - min * 60;

	temp = (hr << 8) + min;

	switch (time_alarm) {
	case MXC_RTC_TIME:
		writew(day, ioaddr + RTC_DAYR);
		writew(sec, ioaddr + RTC_SECOND);
		writew(temp, ioaddr + RTC_HOURMIN);
		break;
	case MXC_RTC_ALARM:
		writew(day, ioaddr + RTC_DAYALARM);
		writew(sec, ioaddr + RTC_ALRM_SEC);
		writew(temp, ioaddr + RTC_ALRM_HM);
		break;
	}
}

/*
 * This function updates the RTC alarm registers and then clears all the
 * interrupt status bits.
 */

Annotation

Implementation Notes