drivers/rtc/rtc-rx8581.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-rx8581.c
Extension
.c
Size
8675 bytes
Lines
323
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 rx85x1_config {
	struct regmap_config regmap;
	unsigned int num_nvram;
};

/*
 * In the routines that deal directly with the rx8581 hardware, we use
 * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
 */
static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct i2c_client *client = to_i2c_client(dev);
	unsigned char date[7];
	unsigned int data;
	int err;
	struct regmap *regmap = i2c_get_clientdata(client);

	/* First we ensure that the "update flag" is not set, we read the
	 * time and date then re-read the "update flag". If the update flag
	 * has been set, we know that the time has changed during the read so
	 * we repeat the whole process again.
	 */
	err = regmap_read(regmap, RX8581_REG_FLAG, &data);
	if (err < 0)
		return err;

	if (data & RX8581_FLAG_VLF) {
		dev_warn(dev,
			 "low voltage detected, date/time is not reliable.\n");
		return -EINVAL;
	}

	do {
		/* If update flag set, clear it */
		if (data & RX8581_FLAG_UF) {
			err = regmap_write(regmap, RX8581_REG_FLAG,
					   data & ~RX8581_FLAG_UF);
			if (err < 0)
				return err;
		}

		/* Now read time and date */
		err = regmap_bulk_read(regmap, RX8581_REG_SC, date,
				       sizeof(date));
		if (err < 0)
			return err;

		/* Check flag register */
		err = regmap_read(regmap, RX8581_REG_FLAG, &data);
		if (err < 0)
			return err;
	} while (data & RX8581_FLAG_UF);

	dev_dbg(dev, "%s: raw data is sec=%02x, min=%02x, hr=%02x, "
		"wday=%02x, mday=%02x, mon=%02x, year=%02x\n",
		__func__,
		date[0], date[1], date[2], date[3], date[4], date[5], date[6]);

	tm->tm_sec = bcd2bin(date[RX8581_REG_SC] & 0x7F);
	tm->tm_min = bcd2bin(date[RX8581_REG_MN] & 0x7F);
	tm->tm_hour = bcd2bin(date[RX8581_REG_HR] & 0x3F); /* rtc hr 0-23 */
	tm->tm_wday = ilog2(date[RX8581_REG_DW] & 0x7F);
	tm->tm_mday = bcd2bin(date[RX8581_REG_DM] & 0x3F);
	tm->tm_mon = bcd2bin(date[RX8581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
	tm->tm_year = bcd2bin(date[RX8581_REG_YR]) + 100;

	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
		"mday=%d, mon=%d, year=%d, wday=%d\n",
		__func__,
		tm->tm_sec, tm->tm_min, tm->tm_hour,
		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);

	return 0;
}

static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct i2c_client *client = to_i2c_client(dev);
	int err;
	unsigned char buf[7];
	struct regmap *regmap = i2c_get_clientdata(client);

	dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, "
		"mday=%d, mon=%d, year=%d, wday=%d\n",
		__func__,
		tm->tm_sec, tm->tm_min, tm->tm_hour,
		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);

	/* hours, minutes and seconds */
	buf[RX8581_REG_SC] = bin2bcd(tm->tm_sec);

Annotation

Implementation Notes