drivers/rtc/rtc-lpc24xx.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-lpc24xx.c
Extension
.c
Size
8165 bytes
Lines
299
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 lpc24xx_rtc {
	void __iomem *rtc_base;
	struct rtc_device *rtc;
	struct clk *clk_rtc;
	struct clk *clk_reg;
};

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

	/* Disable RTC during update */
	rtc_writel(rtc, LPC24XX_CCR, LPC178X_CCALEN);

	rtc_writel(rtc, LPC24XX_SEC,	tm->tm_sec);
	rtc_writel(rtc, LPC24XX_MIN,	tm->tm_min);
	rtc_writel(rtc, LPC24XX_HOUR,	tm->tm_hour);
	rtc_writel(rtc, LPC24XX_DOW,	tm->tm_wday);
	rtc_writel(rtc, LPC24XX_DOM,	tm->tm_mday);
	rtc_writel(rtc, LPC24XX_DOY,	tm->tm_yday);
	rtc_writel(rtc, LPC24XX_MONTH,	tm->tm_mon);
	rtc_writel(rtc, LPC24XX_YEAR,	tm->tm_year);

	rtc_writel(rtc, LPC24XX_CCR, LPC24XX_CLKEN | LPC178X_CCALEN);

	return 0;
}

static int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
	u32 ct0, ct1, ct2;

	ct0 = rtc_readl(rtc, LPC24XX_CTIME0);
	ct1 = rtc_readl(rtc, LPC24XX_CTIME1);
	ct2 = rtc_readl(rtc, LPC24XX_CTIME2);

	tm->tm_sec  = CT0_SECS(ct0);
	tm->tm_min  = CT0_MINS(ct0);
	tm->tm_hour = CT0_HOURS(ct0);
	tm->tm_wday = CT0_DOW(ct0);
	tm->tm_mon  = CT1_MONTH(ct1);
	tm->tm_mday = CT1_DOM(ct1);
	tm->tm_year = CT1_YEAR(ct1);
	tm->tm_yday = CT2_DOY(ct2);

	return 0;
}

static int lpc24xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
	struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
	struct rtc_time *tm = &wkalrm->time;

	tm->tm_sec  = rtc_readl(rtc, LPC24XX_ALSEC);
	tm->tm_min  = rtc_readl(rtc, LPC24XX_ALMIN);
	tm->tm_hour = rtc_readl(rtc, LPC24XX_ALHOUR);
	tm->tm_mday = rtc_readl(rtc, LPC24XX_ALDOM);
	tm->tm_wday = rtc_readl(rtc, LPC24XX_ALDOW);
	tm->tm_yday = rtc_readl(rtc, LPC24XX_ALDOY);
	tm->tm_mon  = rtc_readl(rtc, LPC24XX_ALMON);
	tm->tm_year = rtc_readl(rtc, LPC24XX_ALYEAR);

	wkalrm->enabled = rtc_readl(rtc, LPC24XX_AMR) == 0;
	wkalrm->pending = !!(rtc_readl(rtc, LPC24XX_ILR) & LPC24XX_RTCCIF);

	return rtc_valid_tm(&wkalrm->time);
}

static int lpc24xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
	struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
	struct rtc_time *tm = &wkalrm->time;

	/* Disable alarm irq during update */
	rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE);

	rtc_writel(rtc, LPC24XX_ALSEC,  tm->tm_sec);
	rtc_writel(rtc, LPC24XX_ALMIN,  tm->tm_min);
	rtc_writel(rtc, LPC24XX_ALHOUR, tm->tm_hour);
	rtc_writel(rtc, LPC24XX_ALDOM,  tm->tm_mday);
	rtc_writel(rtc, LPC24XX_ALDOW,  tm->tm_wday);
	rtc_writel(rtc, LPC24XX_ALDOY,  tm->tm_yday);
	rtc_writel(rtc, LPC24XX_ALMON,  tm->tm_mon);
	rtc_writel(rtc, LPC24XX_ALYEAR, tm->tm_year);

	if (wkalrm->enabled)
		rtc_writel(rtc, LPC24XX_AMR, 0);

	return 0;

Annotation

Implementation Notes