drivers/rtc/rtc-vt8500.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-vt8500.c
Extension
.c
Size
7575 bytes
Lines
267
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 vt8500_rtc {
	void __iomem		*regbase;
	int			irq_alarm;
	struct rtc_device	*rtc;
	spinlock_t		lock;		/* Protects this structure */
};

static irqreturn_t vt8500_rtc_irq(int irq, void *dev_id)
{
	struct vt8500_rtc *vt8500_rtc = dev_id;
	u32 isr;
	unsigned long events = 0;

	spin_lock(&vt8500_rtc->lock);

	/* clear interrupt sources */
	isr = readl(vt8500_rtc->regbase + VT8500_RTC_IS);
	writel(isr, vt8500_rtc->regbase + VT8500_RTC_IS);

	spin_unlock(&vt8500_rtc->lock);

	if (isr & VT8500_RTC_IS_ALARM)
		events |= RTC_AF | RTC_IRQF;

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

	return IRQ_HANDLED;
}

static int vt8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);
	u32 date, time;

	date = readl(vt8500_rtc->regbase + VT8500_RTC_DR);
	time = readl(vt8500_rtc->regbase + VT8500_RTC_TR);

	tm->tm_sec = bcd2bin(time & TIME_SEC_MASK);
	tm->tm_min = bcd2bin((time & TIME_MIN_MASK) >> TIME_MIN_S);
	tm->tm_hour = bcd2bin((time & TIME_HOUR_MASK) >> TIME_HOUR_S);
	tm->tm_mday = bcd2bin(date & DATE_DAY_MASK);
	tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S) - 1;
	tm->tm_year = bcd2bin((date & DATE_YEAR_MASK) >> DATE_YEAR_S)
			+ ((date >> DATE_CENTURY_S) & 1 ? 200 : 100);
	tm->tm_wday = (time & TIME_DOW_MASK) >> TIME_DOW_S;

	return 0;
}

static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);

	writel((bin2bcd(tm->tm_year % 100) << DATE_YEAR_S)
		| (bin2bcd(tm->tm_mon + 1) << DATE_MONTH_S)
		| (bin2bcd(tm->tm_mday))
		| ((tm->tm_year >= 200) << DATE_CENTURY_S),
		vt8500_rtc->regbase + VT8500_RTC_DS);
	writel((bin2bcd(tm->tm_wday) << TIME_DOW_S)
		| (bin2bcd(tm->tm_hour) << TIME_HOUR_S)
		| (bin2bcd(tm->tm_min) << TIME_MIN_S)
		| (bin2bcd(tm->tm_sec)),
		vt8500_rtc->regbase + VT8500_RTC_TS);

	return 0;
}

static int vt8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);
	u32 isr, alarm;

	alarm = readl(vt8500_rtc->regbase + VT8500_RTC_AS);
	isr = readl(vt8500_rtc->regbase + VT8500_RTC_IS);

	alrm->time.tm_mday = bcd2bin((alarm & ALARM_DAY_MASK) >> ALARM_DAY_S);
	alrm->time.tm_hour = bcd2bin((alarm & TIME_HOUR_MASK) >> TIME_HOUR_S);
	alrm->time.tm_min = bcd2bin((alarm & TIME_MIN_MASK) >> TIME_MIN_S);
	alrm->time.tm_sec = bcd2bin((alarm & TIME_SEC_MASK));

	alrm->enabled = (alarm & ALARM_ENABLE_MASK) ? 1 : 0;
	alrm->pending = (isr & VT8500_RTC_IS_ALARM) ? 1 : 0;

	return rtc_valid_tm(&alrm->time);
}

static int vt8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);

Annotation

Implementation Notes