drivers/rtc/rtc-goldfish.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-goldfish.c
Extension
.c
Size
4799 bytes
Lines
208
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 goldfish_rtc {
	void __iomem *base;
	int irq;
	struct rtc_device *rtc;
};

static int goldfish_rtc_read_alarm(struct device *dev,
				   struct rtc_wkalrm *alrm)
{
	u64 rtc_alarm;
	u64 rtc_alarm_low;
	u64 rtc_alarm_high;
	void __iomem *base;
	struct goldfish_rtc *rtcdrv;

	rtcdrv = dev_get_drvdata(dev);
	base = rtcdrv->base;

	rtc_alarm_low = gf_ioread32(base + TIMER_ALARM_LOW);
	rtc_alarm_high = gf_ioread32(base + TIMER_ALARM_HIGH);
	rtc_alarm = (rtc_alarm_high << 32) | rtc_alarm_low;

	do_div(rtc_alarm, NSEC_PER_SEC);
	memset(alrm, 0, sizeof(struct rtc_wkalrm));

	rtc_time64_to_tm(rtc_alarm, &alrm->time);

	if (gf_ioread32(base + TIMER_ALARM_STATUS))
		alrm->enabled = 1;
	else
		alrm->enabled = 0;

	return 0;
}

static int goldfish_rtc_set_alarm(struct device *dev,
				  struct rtc_wkalrm *alrm)
{
	struct goldfish_rtc *rtcdrv;
	u64 rtc_alarm64;
	u64 rtc_status_reg;
	void __iomem *base;

	rtcdrv = dev_get_drvdata(dev);
	base = rtcdrv->base;

	if (alrm->enabled) {
		rtc_alarm64 = rtc_tm_to_time64(&alrm->time) * NSEC_PER_SEC;
		gf_iowrite32((rtc_alarm64 >> 32), base + TIMER_ALARM_HIGH);
		gf_iowrite32(rtc_alarm64, base + TIMER_ALARM_LOW);
		gf_iowrite32(1, base + TIMER_IRQ_ENABLED);
	} else {
		/*
		 * if this function was called with enabled=0
		 * then it could mean that the application is
		 * trying to cancel an ongoing alarm
		 */
		rtc_status_reg = gf_ioread32(base + TIMER_ALARM_STATUS);
		if (rtc_status_reg)
			gf_iowrite32(1, base + TIMER_CLEAR_ALARM);
	}

	return 0;
}

static int goldfish_rtc_alarm_irq_enable(struct device *dev,
					 unsigned int enabled)
{
	void __iomem *base;
	struct goldfish_rtc *rtcdrv;

	rtcdrv = dev_get_drvdata(dev);
	base = rtcdrv->base;

	if (enabled)
		gf_iowrite32(1, base + TIMER_IRQ_ENABLED);
	else
		gf_iowrite32(0, base + TIMER_IRQ_ENABLED);

	return 0;
}

static irqreturn_t goldfish_rtc_interrupt(int irq, void *dev_id)
{
	struct goldfish_rtc *rtcdrv = dev_id;
	void __iomem *base = rtcdrv->base;

	gf_iowrite32(1, base + TIMER_CLEAR_INTERRUPT);

	rtc_update_irq(rtcdrv->rtc, 1, RTC_IRQF | RTC_AF);

Annotation

Implementation Notes