drivers/rtc/rtc-da9052.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-da9052.c
Extension
.c
Size
7863 bytes
Lines
334
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 da9052_rtc {
	struct rtc_device *rtc;
	struct da9052 *da9052;
};

static int da9052_rtc_enable_alarm(struct da9052_rtc *rtc, bool enable)
{
	int ret;
	if (enable) {
		ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG,
				DA9052_ALARM_Y_ALARM_ON|DA9052_ALARM_Y_TICK_ON,
				DA9052_ALARM_Y_ALARM_ON);
		if (ret != 0)
			rtc_err(rtc, "Failed to enable ALM: %d\n", ret);
	} else {
		ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG,
			DA9052_ALARM_Y_ALARM_ON|DA9052_ALARM_Y_TICK_ON, 0);
		if (ret != 0)
			rtc_err(rtc, "Write error: %d\n", ret);
	}
	return ret;
}

static irqreturn_t da9052_rtc_irq(int irq, void *data)
{
	struct da9052_rtc *rtc = data;

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

	return IRQ_HANDLED;
}

static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
{
	int ret;
	uint8_t v[2][5];
	int idx = 1;
	int timeout = DA9052_GET_TIME_RETRIES;

	ret = da9052_group_read(rtc->da9052, DA9052_ALARM_MI_REG, 5, &v[0][0]);
	if (ret) {
		rtc_err(rtc, "Failed to group read ALM: %d\n", ret);
		return ret;
	}

	do {
		ret = da9052_group_read(rtc->da9052,
					DA9052_ALARM_MI_REG, 5, &v[idx][0]);
		if (ret) {
			rtc_err(rtc, "Failed to group read ALM: %d\n", ret);
			return ret;
		}

		if (memcmp(&v[0][0], &v[1][0], 5) == 0) {
			rtc_tm->tm_year = (v[0][4] & DA9052_RTC_YEAR) + 100;
			rtc_tm->tm_mon  = (v[0][3] & DA9052_RTC_MONTH) - 1;
			rtc_tm->tm_mday = v[0][2] & DA9052_RTC_DAY;
			rtc_tm->tm_hour = v[0][1] & DA9052_RTC_HOUR;
			rtc_tm->tm_min  = v[0][0] & DA9052_RTC_MIN;
			rtc_tm->tm_sec = 0;

			ret = rtc_valid_tm(rtc_tm);
			return ret;
		}

		idx = (1-idx);
		msleep(20);

	} while (timeout--);

	rtc_err(rtc, "Timed out reading alarm time\n");

	return -EIO;
}

static int da9052_set_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
{
	struct da9052 *da9052 = rtc->da9052;
	unsigned long alm_time;
	int ret;
	uint8_t v[3];

	alm_time = rtc_tm_to_time64(rtc_tm);

	if (rtc_tm->tm_sec > 0) {
		alm_time += 60 - rtc_tm->tm_sec;
		rtc_time64_to_tm(alm_time, rtc_tm);
	}
	BUG_ON(rtc_tm->tm_sec); /* it will cause repeated irqs if not zero */

Annotation

Implementation Notes