drivers/rtc/rtc-pic32.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-pic32.c
Extension
.c
Size
9766 bytes
Lines
382
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 pic32_rtc_dev {
	struct rtc_device	*rtc;
	void __iomem		*reg_base;
	struct clk		*clk;
	spinlock_t		alarm_lock;
	int			alarm_irq;
	bool			alarm_clk_enabled;
};

static void pic32_rtc_alarm_clk_enable(struct pic32_rtc_dev *pdata,
				       bool enable)
{
	unsigned long flags;

	spin_lock_irqsave(&pdata->alarm_lock, flags);
	if (enable) {
		if (!pdata->alarm_clk_enabled) {
			clk_enable(pdata->clk);
			pdata->alarm_clk_enabled = true;
		}
	} else {
		if (pdata->alarm_clk_enabled) {
			clk_disable(pdata->clk);
			pdata->alarm_clk_enabled = false;
		}
	}
	spin_unlock_irqrestore(&pdata->alarm_lock, flags);
}

static irqreturn_t pic32_rtc_alarmirq(int irq, void *id)
{
	struct pic32_rtc_dev *pdata = (struct pic32_rtc_dev *)id;

	clk_enable(pdata->clk);
	rtc_update_irq(pdata->rtc, 1, RTC_AF | RTC_IRQF);
	clk_disable(pdata->clk);

	pic32_rtc_alarm_clk_enable(pdata, false);

	return IRQ_HANDLED;
}

static int pic32_rtc_setaie(struct device *dev, unsigned int enabled)
{
	struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
	void __iomem *base = pdata->reg_base;

	clk_enable(pdata->clk);

	writel(PIC32_RTCALRM_ALRMEN,
	       base + (enabled ? PIC32_SET(PIC32_RTCALRM) :
		       PIC32_CLR(PIC32_RTCALRM)));

	clk_disable(pdata->clk);

	pic32_rtc_alarm_clk_enable(pdata, enabled);

	return 0;
}

static int pic32_rtc_setfreq(struct device *dev, int freq)
{
	struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
	void __iomem *base = pdata->reg_base;

	clk_enable(pdata->clk);

	writel(PIC32_RTCALRM_AMASK, base + PIC32_CLR(PIC32_RTCALRM));
	writel(freq << 8, base + PIC32_SET(PIC32_RTCALRM));
	writel(PIC32_RTCALRM_CHIME, base + PIC32_SET(PIC32_RTCALRM));

	clk_disable(pdata->clk);

	return 0;
}

static int pic32_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
{
	struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
	void __iomem *base = pdata->reg_base;
	unsigned int tries = 0;

	clk_enable(pdata->clk);

	do {
		rtc_tm->tm_hour = readb(base + PIC32_RTCHOUR);
		rtc_tm->tm_min = readb(base + PIC32_RTCMIN);
		rtc_tm->tm_mon  = readb(base + PIC32_RTCMON);
		rtc_tm->tm_mday = readb(base + PIC32_RTCDAY);
		rtc_tm->tm_year = readb(base + PIC32_RTCYEAR);

Annotation

Implementation Notes