drivers/rtc/rtc-s32g.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-s32g.c
Extension
.c
Size
8841 bytes
Lines
386
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 rtc_priv {
	struct rtc_device *rdev;
	void __iomem *rtc_base;
	struct clk *ipg;
	struct clk *clk_src;
	const struct rtc_soc_data *rtc_data;
	u64 rtc_hz;
	time64_t sleep_sec;
	int irq;
	u32 clk_src_idx;
};

struct rtc_soc_data {
	u32 clk_div;
	u32 reserved_clk_mask;
};

static const struct rtc_soc_data rtc_s32g2_data = {
	.clk_div = DIV512_32,
	.reserved_clk_mask = RTC_CLK_SRC1_RESERVED,
};

static irqreturn_t s32g_rtc_handler(int irq, void *dev)
{
	struct rtc_priv *priv = platform_get_drvdata(dev);
	u32 status;

	status = readl(priv->rtc_base + RTCS_OFFSET);

	if (status & RTCS_APIF) {
		writel(0x0, priv->rtc_base + APIVAL_OFFSET);
		writel(status | RTCS_APIF, priv->rtc_base + RTCS_OFFSET);
	}

	rtc_update_irq(priv->rdev, 1, RTC_IRQF | RTC_AF);

	return IRQ_HANDLED;
}

/*
 * The function is not really getting time from the RTC since the S32G RTC
 * has several limitations. Thus, to setup alarm use system time.
 */
static int s32g_rtc_read_time(struct device *dev,
			      struct rtc_time *tm)
{
	struct rtc_priv *priv = dev_get_drvdata(dev);
	time64_t sec;

	if (check_add_overflow(ktime_get_real_seconds(),
			       priv->sleep_sec, &sec))
		return -ERANGE;

	rtc_time64_to_tm(sec, tm);

	return 0;
}

static int s32g_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct rtc_priv *priv = dev_get_drvdata(dev);
	u32 rtcc, rtcs;

	rtcc = readl(priv->rtc_base + RTCC_OFFSET);
	rtcs = readl(priv->rtc_base + RTCS_OFFSET);

	alrm->enabled = rtcc & RTCC_APIIE;
	if (alrm->enabled)
		alrm->pending = !(rtcs & RTCS_APIF);

	return 0;
}

static int s32g_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
	struct rtc_priv *priv = dev_get_drvdata(dev);
	u32 rtcc;

	/* RTC API functionality is used both for triggering interrupts
	 * and as a wakeup event. Hence it should always be enabled.
	 */
	rtcc = readl(priv->rtc_base + RTCC_OFFSET);
	rtcc |= RTCC_APIEN | RTCC_APIIE;
	writel(rtcc, priv->rtc_base + RTCC_OFFSET);

	return 0;
}

static int s32g_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{

Annotation

Implementation Notes