drivers/rtc/rtc-rx8111.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-rx8111.c
Extension
.c
Size
10398 bytes
Lines
369
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 rx8111_data {
	struct regmap *regmap;
	struct regmap_field *regfields[RX8111_REGF_MAX];
	struct device *dev;
	struct rtc_device *rtc;
};

static int rx8111_read_vl_flag(struct rx8111_data *data, unsigned int *vlval)
{
	int ret;

	ret = regmap_field_read(data->regfields[RX8111_REGF_VLF], vlval);
	if (ret)
		dev_dbg(data->dev, "Could not read VL flag (%d)", ret);

	return ret;
}

static int rx8111_read_time(struct device *dev, struct rtc_time *tm)
{
	struct rx8111_data *data = dev_get_drvdata(dev);
	u8 buf[RX8111_TIME_BUF_SZ];
	unsigned int regval;
	int ret;

	/* Check status. */
	ret = regmap_read(data->regmap, RX8111_REG_FLAG, &regval);
	if (ret) {
		dev_dbg(data->dev, "Could not read flag register (%d)\n", ret);
		return ret;
	}

	if (FIELD_GET(RX8111_FLAG_XST_BIT, regval)) {
		dev_dbg(data->dev,
			"Crystal oscillation stopped, time is not reliable\n");
		return -EINVAL;
	}

	if (FIELD_GET(RX8111_FLAG_VLF_BIT, regval)) {
		dev_dbg(data->dev,
			"Low voltage detected, time is not reliable\n");
		return -EINVAL;
	}

	ret = regmap_field_read(data->regfields[RX8111_REGF_STOP], &regval);
	if (ret) {
		dev_dbg(data->dev, "Could not read clock status (%d)\n", ret);
		return ret;
	}

	if (regval) {
		dev_dbg(data->dev, "Clock stopped, time is not reliable\n");
		return -EINVAL;
	}

	/* Read time. */
	ret = regmap_bulk_read(data->regmap, RX8111_REG_SEC, buf,
			       ARRAY_SIZE(buf));
	if (ret) {
		dev_dbg(data->dev, "Could not bulk read time (%d)\n", ret);
		return ret;
	}

	tm->tm_sec = bcd2bin(buf[0]);
	tm->tm_min = bcd2bin(buf[1]);
	tm->tm_hour = bcd2bin(buf[2]);
	tm->tm_wday = ffs(buf[3]) - 1;
	tm->tm_mday = bcd2bin(buf[4]);
	tm->tm_mon = bcd2bin(buf[5]) - 1;
	tm->tm_year = bcd2bin(buf[6]) + 100;

	return 0;
}

static int rx8111_set_time(struct device *dev, struct rtc_time *tm)
{
	struct rx8111_data *data = dev_get_drvdata(dev);
	u8 buf[RX8111_TIME_BUF_SZ];
	int ret;

	buf[0] = bin2bcd(tm->tm_sec);
	buf[1] = bin2bcd(tm->tm_min);
	buf[2] = bin2bcd(tm->tm_hour);
	buf[3] = BIT(tm->tm_wday);
	buf[4] = bin2bcd(tm->tm_mday);
	buf[5] = bin2bcd(tm->tm_mon + 1);
	buf[6] = bin2bcd(tm->tm_year - 100);

	ret = regmap_clear_bits(data->regmap, RX8111_REG_FLAG,
				RX8111_FLAG_XST_BIT | RX8111_FLAG_VLF_BIT);

Annotation

Implementation Notes