drivers/rtc/rtc-asm9260.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-asm9260.c
Extension
.c
Size
9134 bytes
Lines
340
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 asm9260_rtc_priv {
	struct device		*dev;
	void __iomem		*iobase;
	struct rtc_device	*rtc;
	struct clk		*clk;
};

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

	rtc_lock(priv->rtc);
	isr = ioread32(priv->iobase + HW_CIIR);
	if (!isr) {
		rtc_unlock(priv->rtc);
		return IRQ_NONE;
	}

	iowrite32(0, priv->iobase + HW_CIIR);
	rtc_unlock(priv->rtc);

	events |= RTC_AF | RTC_IRQF;

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

	return IRQ_HANDLED;
}

static int asm9260_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
	u32 ctime0, ctime1, ctime2;

	ctime0 = ioread32(priv->iobase + HW_CTIME0);
	ctime1 = ioread32(priv->iobase + HW_CTIME1);
	ctime2 = ioread32(priv->iobase + HW_CTIME2);

	if (ctime1 != ioread32(priv->iobase + HW_CTIME1)) {
		/*
		 * woops, counter flipped right now. Now we are safe
		 * to reread.
		 */
		ctime0 = ioread32(priv->iobase + HW_CTIME0);
		ctime1 = ioread32(priv->iobase + HW_CTIME1);
		ctime2 = ioread32(priv->iobase + HW_CTIME2);
	}

	tm->tm_sec  = (ctime0 >> BM_CTIME0_SEC_S)  & BM_CTIME0_SEC_M;
	tm->tm_min  = (ctime0 >> BM_CTIME0_MIN_S)  & BM_CTIME0_MIN_M;
	tm->tm_hour = (ctime0 >> BM_CTIME0_HOUR_S) & BM_CTIME0_HOUR_M;
	tm->tm_wday = (ctime0 >> BM_CTIME0_DOW_S)  & BM_CTIME0_DOW_M;

	tm->tm_mday = (ctime1 >> BM_CTIME1_DOM_S)  & BM_CTIME1_DOM_M;
	tm->tm_mon  = (ctime1 >> BM_CTIME1_MON_S)  & BM_CTIME1_MON_M;
	tm->tm_year = (ctime1 >> BM_CTIME1_YEAR_S) & BM_CTIME1_YEAR_M;

	tm->tm_yday = (ctime2 >> BM_CTIME2_DOY_S)  & BM_CTIME2_DOY_M;

	return 0;
}

static int asm9260_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);

	/*
	 * make sure SEC counter will not flip other counter on write time,
	 * real value will be written at the enf of sequence.
	 */
	iowrite32(0, priv->iobase + HW_SEC);

	iowrite32(tm->tm_year, priv->iobase + HW_YEAR);
	iowrite32(tm->tm_mon,  priv->iobase + HW_MONTH);
	iowrite32(tm->tm_mday, priv->iobase + HW_DOM);
	iowrite32(tm->tm_wday, priv->iobase + HW_DOW);
	iowrite32(tm->tm_yday, priv->iobase + HW_DOY);
	iowrite32(tm->tm_hour, priv->iobase + HW_HOUR);
	iowrite32(tm->tm_min,  priv->iobase + HW_MIN);
	iowrite32(tm->tm_sec,  priv->iobase + HW_SEC);

	return 0;
}

static int asm9260_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);

	alrm->time.tm_year = ioread32(priv->iobase + HW_ALYEAR);

Annotation

Implementation Notes