drivers/rtc/rtc-sh.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-sh.c
Extension
.c
Size
13521 bytes
Lines
508
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 sh_rtc {
	void __iomem		*regbase;
	int			alarm_irq;
	struct clk		*clk;
	struct rtc_device	*rtc_dev;
	spinlock_t		lock;		/* protecting register access */
	unsigned long		capabilities;	/* See asm/rtc.h for cap bits */
};

static irqreturn_t sh_rtc_alarm(int irq, void *dev_id)
{
	struct sh_rtc *rtc = dev_id;
	unsigned int tmp, pending;

	spin_lock(&rtc->lock);

	tmp = readb(rtc->regbase + RCR1);
	pending = tmp & RCR1_AF;
	tmp &= ~(RCR1_AF | RCR1_AIE);
	writeb(tmp, rtc->regbase + RCR1);

	if (pending)
		rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);

	spin_unlock(&rtc->lock);

	return IRQ_RETVAL(pending);
}

static int sh_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
{
	struct sh_rtc *rtc = dev_get_drvdata(dev);
	unsigned int tmp;

	spin_lock_irq(&rtc->lock);

	tmp = readb(rtc->regbase + RCR1);

	if (enable)
		tmp |= RCR1_AIE;
	else
		tmp &= ~RCR1_AIE;

	writeb(tmp, rtc->regbase + RCR1);

	spin_unlock_irq(&rtc->lock);

	return 0;
}

static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct sh_rtc *rtc = dev_get_drvdata(dev);
	unsigned int sec128, sec2, yr, yr100, cf_bit;

	if (!(readb(rtc->regbase + RCR2) & RCR2_RTCEN))
		return -EINVAL;

	do {
		unsigned int tmp;

		spin_lock_irq(&rtc->lock);

		tmp = readb(rtc->regbase + RCR1);
		tmp &= ~RCR1_CF; /* Clear CF-bit */
		tmp |= RCR1_CIE;
		writeb(tmp, rtc->regbase + RCR1);

		sec128 = readb(rtc->regbase + R64CNT);

		tm->tm_sec	= bcd2bin(readb(rtc->regbase + RSECCNT));
		tm->tm_min	= bcd2bin(readb(rtc->regbase + RMINCNT));
		tm->tm_hour	= bcd2bin(readb(rtc->regbase + RHRCNT));
		tm->tm_wday	= bcd2bin(readb(rtc->regbase + RWKCNT));
		tm->tm_mday	= bcd2bin(readb(rtc->regbase + RDAYCNT));
		tm->tm_mon	= bcd2bin(readb(rtc->regbase + RMONCNT)) - 1;

		if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
			yr  = readw(rtc->regbase + RYRCNT);
			yr100 = bcd2bin(yr >> 8);
			yr &= 0xff;
		} else {
			yr  = readb(rtc->regbase + RYRCNT);
			yr100 = bcd2bin((yr == 0x99) ? 0x19 : 0x20);
		}

		tm->tm_year = (yr100 * 100 + bcd2bin(yr)) - 1900;

		sec2 = readb(rtc->regbase + R64CNT);
		cf_bit = readb(rtc->regbase + RCR1) & RCR1_CF;

Annotation

Implementation Notes