drivers/rtc/rtc-max8997.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-max8997.c
Extension
.c
Size
12529 bytes
Lines
534
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 max8997_rtc_info {
	struct device		*dev;
	struct max8997_dev	*max8997;
	struct i2c_client	*rtc;
	struct rtc_device	*rtc_dev;
	struct mutex		lock;
	int virq;
	int rtc_24hr_mode;
};

static void max8997_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
				   int rtc_24hr_mode)
{
	tm->tm_sec = data[RTC_SEC] & 0x7f;
	tm->tm_min = data[RTC_MIN] & 0x7f;
	if (rtc_24hr_mode)
		tm->tm_hour = data[RTC_HOUR] & 0x1f;
	else {
		tm->tm_hour = data[RTC_HOUR] & 0x0f;
		if (data[RTC_HOUR] & HOUR_PM_MASK)
			tm->tm_hour += 12;
	}

	tm->tm_wday = fls(data[RTC_WEEKDAY] & 0x7f) - 1;
	tm->tm_mday = data[RTC_DATE] & 0x1f;
	tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
	tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100;
	tm->tm_yday = 0;
	tm->tm_isdst = 0;
}

static int max8997_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
{
	data[RTC_SEC] = tm->tm_sec;
	data[RTC_MIN] = tm->tm_min;
	data[RTC_HOUR] = tm->tm_hour;
	data[RTC_WEEKDAY] = 1 << tm->tm_wday;
	data[RTC_DATE] = tm->tm_mday;
	data[RTC_MONTH] = tm->tm_mon + 1;
	data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0;

	if (tm->tm_year < 100) {
		pr_warn("RTC cannot handle the year %d.  Assume it's 2000.\n",
			1900 + tm->tm_year);
		return -EINVAL;
	}
	return 0;
}

static inline int max8997_rtc_set_update_reg(struct max8997_rtc_info *info)
{
	int ret;

	ret = max8997_write_reg(info->rtc, MAX8997_RTC_UPDATE1,
						RTC_UDR_MASK);
	if (ret < 0)
		dev_err(info->dev, "%s: fail to write update reg(%d)\n",
				__func__, ret);
	else {
		/* Minimum 16ms delay required before RTC update.
		 * Otherwise, we may read and update based on out-of-date
		 * value */
		msleep(20);
	}

	return ret;
}

static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct max8997_rtc_info *info = dev_get_drvdata(dev);
	u8 data[RTC_NR_TIME];
	int ret;

	mutex_lock(&info->lock);
	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data);
	mutex_unlock(&info->lock);

	if (ret < 0) {
		dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__,
				ret);
		return ret;
	}

	max8997_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);

	return 0;
}

static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm)

Annotation

Implementation Notes