drivers/rtc/rtc-mt7622.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-mt7622.c
Extension
.c
Size
10021 bytes
Lines
410
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 mtk_rtc {
	struct rtc_device *rtc;
	void __iomem *base;
	int irq;
	struct clk *clk;
};

static void mtk_w32(struct mtk_rtc *rtc, u32 reg, u32 val)
{
	writel_relaxed(val, rtc->base + reg);
}

static u32 mtk_r32(struct mtk_rtc *rtc, u32 reg)
{
	return readl_relaxed(rtc->base + reg);
}

static void mtk_rmw(struct mtk_rtc *rtc, u32 reg, u32 mask, u32 set)
{
	u32 val;

	val = mtk_r32(rtc, reg);
	val &= ~mask;
	val |= set;
	mtk_w32(rtc, reg, val);
}

static void mtk_set(struct mtk_rtc *rtc, u32 reg, u32 val)
{
	mtk_rmw(rtc, reg, 0, val);
}

static void mtk_clr(struct mtk_rtc *rtc, u32 reg, u32 val)
{
	mtk_rmw(rtc, reg, val, 0);
}

static void mtk_rtc_hw_init(struct mtk_rtc *hw)
{
	/* The setup of the init sequence is for allowing RTC got to work */
	mtk_w32(hw, MTK_RTC_PWRCHK1, RTC_PWRCHK1_MAGIC);
	mtk_w32(hw, MTK_RTC_PWRCHK2, RTC_PWRCHK2_MAGIC);
	mtk_w32(hw, MTK_RTC_KEY, RTC_KEY_MAGIC);
	mtk_w32(hw, MTK_RTC_PROT1, RTC_PROT1_MAGIC);
	mtk_w32(hw, MTK_RTC_PROT2, RTC_PROT2_MAGIC);
	mtk_w32(hw, MTK_RTC_PROT3, RTC_PROT3_MAGIC);
	mtk_w32(hw, MTK_RTC_PROT4, RTC_PROT4_MAGIC);
	mtk_rmw(hw, MTK_RTC_DEBNCE, RTC_DEBNCE_MASK, 0);
	mtk_clr(hw, MTK_RTC_CTL, RTC_RC_STOP);
}

static void mtk_rtc_get_alarm_or_time(struct mtk_rtc *hw, struct rtc_time *tm,
				      int time_alarm)
{
	u32 year, mon, mday, wday, hour, min, sec;

	/*
	 * Read again until the field of the second is not changed which
	 * ensures all fields in the consistent state. Note that MTK_SEC must
	 * be read first. In this way, it guarantees the others remain not
	 * changed when the results for two MTK_SEC consecutive reads are same.
	 */
	do {
		sec = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC));
		min = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_MIN));
		hour = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_HOU));
		wday = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_DOW));
		mday = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_DOM));
		mon = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_MON));
		year = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_YEA));
	} while (sec != mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC)));

	tm->tm_sec  = sec;
	tm->tm_min  = min;
	tm->tm_hour = hour;
	tm->tm_wday = wday;
	tm->tm_mday = mday;
	tm->tm_mon  = mon - 1;

	/* Rebase to the absolute year which userspace queries */
	tm->tm_year = year + MTK_RTC_TM_YR_OFFSET;
}

static void mtk_rtc_set_alarm_or_time(struct mtk_rtc *hw, struct rtc_time *tm,
				      int time_alarm)
{
	u32 year;

	/* Rebase to the relative year which RTC hardware requires */
	year = tm->tm_year - MTK_RTC_TM_YR_OFFSET;

Annotation

Implementation Notes