drivers/rtc/rtc-st-lpc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-st-lpc.c
Extension
.c
Size
7542 bytes
Lines
315
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 st_rtc {
	struct rtc_device *rtc_dev;
	struct rtc_wkalrm alarm;
	struct clk *clk;
	unsigned long clkrate;
	void __iomem *ioaddr;
	bool irq_enabled:1;
	spinlock_t lock;
	short irq;
};

static void st_rtc_set_hw_alarm(struct st_rtc *rtc,
				unsigned long msb, unsigned long  lsb)
{
	unsigned long flags;

	spin_lock_irqsave(&rtc->lock, flags);

	writel_relaxed(1, rtc->ioaddr + LPC_WDT_OFF);

	writel_relaxed(msb, rtc->ioaddr + LPC_LPA_MSB_OFF);
	writel_relaxed(lsb, rtc->ioaddr + LPC_LPA_LSB_OFF);
	writel_relaxed(1, rtc->ioaddr + LPC_LPA_START_OFF);

	writel_relaxed(0, rtc->ioaddr + LPC_WDT_OFF);

	spin_unlock_irqrestore(&rtc->lock, flags);
}

static irqreturn_t st_rtc_handler(int this_irq, void *data)
{
	struct st_rtc *rtc = (struct st_rtc *)data;

	rtc_update_irq(rtc->rtc_dev, 1, RTC_AF);

	return IRQ_HANDLED;
}

static int st_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct st_rtc *rtc = dev_get_drvdata(dev);
	unsigned long lpt_lsb, lpt_msb;
	unsigned long long lpt;
	unsigned long flags;

	spin_lock_irqsave(&rtc->lock, flags);

	do {
		lpt_msb = readl_relaxed(rtc->ioaddr + LPC_LPT_MSB_OFF);
		lpt_lsb = readl_relaxed(rtc->ioaddr + LPC_LPT_LSB_OFF);
	} while (readl_relaxed(rtc->ioaddr + LPC_LPT_MSB_OFF) != lpt_msb);

	spin_unlock_irqrestore(&rtc->lock, flags);

	lpt = ((unsigned long long)lpt_msb << 32) | lpt_lsb;
	do_div(lpt, rtc->clkrate);
	rtc_time64_to_tm(lpt, tm);

	return 0;
}

static int st_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct st_rtc *rtc = dev_get_drvdata(dev);
	unsigned long long lpt, secs;
	unsigned long flags;

	secs = rtc_tm_to_time64(tm);

	lpt = (unsigned long long)secs * rtc->clkrate;

	spin_lock_irqsave(&rtc->lock, flags);

	writel_relaxed(lpt >> 32, rtc->ioaddr + LPC_LPT_MSB_OFF);
	writel_relaxed(lpt, rtc->ioaddr + LPC_LPT_LSB_OFF);
	writel_relaxed(1, rtc->ioaddr + LPC_LPT_START_OFF);

	spin_unlock_irqrestore(&rtc->lock, flags);

	return 0;
}

static int st_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
	struct st_rtc *rtc = dev_get_drvdata(dev);
	unsigned long flags;

	spin_lock_irqsave(&rtc->lock, flags);

	memcpy(wkalrm, &rtc->alarm, sizeof(struct rtc_wkalrm));

Annotation

Implementation Notes