drivers/rtc/rtc-msc313.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-msc313.c
Extension
.c
Size
6382 bytes
Lines
250
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 msc313_rtc {
	struct rtc_device *rtc_dev;
	void __iomem *rtc_base;
};

static int msc313_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
	struct msc313_rtc *priv = dev_get_drvdata(dev);
	unsigned long seconds;

	seconds = readw(priv->rtc_base + REG_RTC_MATCH_VAL_L)
			| ((unsigned long)readw(priv->rtc_base + REG_RTC_MATCH_VAL_H) << 16);

	rtc_time64_to_tm(seconds, &alarm->time);

	if (!(readw(priv->rtc_base + REG_RTC_CTRL) & INT_MASK_BIT))
		alarm->enabled = 1;

	return 0;
}

static int msc313_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
	struct msc313_rtc *priv = dev_get_drvdata(dev);
	u16 reg;

	reg = readw(priv->rtc_base + REG_RTC_CTRL);
	if (enabled)
		reg &= ~INT_MASK_BIT;
	else
		reg |= INT_MASK_BIT;
	writew(reg, priv->rtc_base + REG_RTC_CTRL);
	return 0;
}

static int msc313_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
	struct msc313_rtc *priv = dev_get_drvdata(dev);
	unsigned long seconds;

	seconds = rtc_tm_to_time64(&alarm->time);
	writew((seconds & 0xFFFF), priv->rtc_base + REG_RTC_MATCH_VAL_L);
	writew((seconds >> 16) & 0xFFFF, priv->rtc_base + REG_RTC_MATCH_VAL_H);

	msc313_rtc_alarm_irq_enable(dev, alarm->enabled);

	return 0;
}

static bool msc313_rtc_get_enabled(struct msc313_rtc *priv)
{
	return readw(priv->rtc_base + REG_RTC_CTRL) & CNT_EN_BIT;
}

static void msc313_rtc_set_enabled(struct msc313_rtc *priv)
{
	u16 reg;

	reg = readw(priv->rtc_base + REG_RTC_CTRL);
	reg |= CNT_EN_BIT;
	writew(reg, priv->rtc_base + REG_RTC_CTRL);
}

static int msc313_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct msc313_rtc *priv = dev_get_drvdata(dev);
	u32 seconds;
	u16 reg;

	if (!msc313_rtc_get_enabled(priv))
		return -EINVAL;

	reg = readw(priv->rtc_base + REG_RTC_CTRL);
	writew(reg | READ_EN_BIT, priv->rtc_base + REG_RTC_CTRL);

	/* Wait for HW latch done */
	while (readw(priv->rtc_base + REG_RTC_CTRL) & READ_EN_BIT)
		udelay(1);

	seconds = readw(priv->rtc_base + REG_RTC_CNT_VAL_L)
			| ((unsigned long)readw(priv->rtc_base + REG_RTC_CNT_VAL_H) << 16);

	rtc_time64_to_tm(seconds, tm);

	return 0;
}

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

Annotation

Implementation Notes