drivers/rtc/rtc-s3c.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-s3c.c
Extension
.c
Size
13536 bytes
Lines
567
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 s3c_rtc {
	struct device *dev;
	struct rtc_device *rtc;

	void __iomem *base;
	struct clk *rtc_clk;
	struct clk *rtc_src_clk;
	bool alarm_enabled;

	const struct s3c_rtc_data *data;

	int irq_alarm;
	spinlock_t alarm_lock;

	bool wake_en;
};

struct s3c_rtc_data {
	bool needs_src_clk;

	void (*irq_handler) (struct s3c_rtc *info, int mask);
	void (*enable) (struct s3c_rtc *info);
	void (*disable) (struct s3c_rtc *info);
};

static int s3c_rtc_enable_clk(struct s3c_rtc *info)
{
	int ret;

	ret = clk_enable(info->rtc_clk);
	if (ret)
		return ret;

	if (info->data->needs_src_clk) {
		ret = clk_enable(info->rtc_src_clk);
		if (ret) {
			clk_disable(info->rtc_clk);
			return ret;
		}
	}
	return 0;
}

static void s3c_rtc_disable_clk(struct s3c_rtc *info)
{
	if (info->data->needs_src_clk)
		clk_disable(info->rtc_src_clk);
	clk_disable(info->rtc_clk);
}

/* IRQ Handler */
static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
{
	struct s3c_rtc *info = (struct s3c_rtc *)id;

	if (info->data->irq_handler)
		info->data->irq_handler(info, S3C2410_INTP_ALM);

	return IRQ_HANDLED;
}

/* Update control registers */
static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
{
	struct s3c_rtc *info = dev_get_drvdata(dev);
	unsigned long flags;
	unsigned int tmp;
	int ret;

	dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled);

	ret = s3c_rtc_enable_clk(info);
	if (ret)
		return ret;

	tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;

	if (enabled)
		tmp |= S3C2410_RTCALM_ALMEN;

	writeb(tmp, info->base + S3C2410_RTCALM);

	spin_lock_irqsave(&info->alarm_lock, flags);

	if (info->alarm_enabled && !enabled)
		s3c_rtc_disable_clk(info);
	else if (!info->alarm_enabled && enabled)
		ret = s3c_rtc_enable_clk(info);

	info->alarm_enabled = enabled;

Annotation

Implementation Notes