drivers/rtc/rtc-tps6594.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-tps6594.c
Extension
.c
Size
13074 bytes
Lines
506
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 tps6594_rtc {
	struct rtc_device *rtc_dev;
	int irq;
};

static int tps6594_rtc_alarm_irq_enable(struct device *dev,
					unsigned int enabled)
{
	struct tps6594 *tps = dev_get_drvdata(dev->parent);
	u8 val;

	val = enabled ? TPS6594_BIT_IT_ALARM : 0;

	return regmap_update_bits(tps->regmap, TPS6594_REG_RTC_INTERRUPTS,
				  TPS6594_BIT_IT_ALARM, val);
}

/* Pulse GET_TIME field of RTC_CTRL_1 to store a timestamp in shadow registers. */
static int tps6594_rtc_shadow_timestamp(struct device *dev, struct tps6594 *tps)
{
	int ret;

	/*
	 * Set GET_TIME to 0. Next time we set GET_TIME to 1 we will be sure to store
	 * an up-to-date timestamp.
	 */
	ret = regmap_clear_bits(tps->regmap, TPS6594_REG_RTC_CTRL_1,
				TPS6594_BIT_GET_TIME);
	if (ret < 0)
		return ret;

	/*
	 * Copy content of RTC registers to shadow registers or latches to read
	 * a coherent timestamp.
	 */
	return regmap_set_bits(tps->regmap, TPS6594_REG_RTC_CTRL_1,
			       TPS6594_BIT_GET_TIME);
}

static int tps6594_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	unsigned char rtc_data[NUM_TIME_REGS];
	struct tps6594 *tps = dev_get_drvdata(dev->parent);
	int ret;

	// Check if RTC is running.
	ret = regmap_test_bits(tps->regmap, TPS6594_REG_RTC_STATUS,
			       TPS6594_BIT_RUN);
	if (ret < 0)
		return ret;
	if (ret == 0)
		return -EINVAL;

	ret = tps6594_rtc_shadow_timestamp(dev, tps);
	if (ret < 0)
		return ret;

	// Read shadowed RTC registers.
	ret = regmap_bulk_read(tps->regmap, TPS6594_REG_RTC_SECONDS, rtc_data,
			       NUM_TIME_REGS);
	if (ret < 0)
		return ret;

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

	return 0;
}

static int tps6594_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	unsigned char rtc_data[NUM_TIME_REGS];
	struct tps6594 *tps = dev_get_drvdata(dev->parent);
	int ret;

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

	// Stop RTC while updating the RTC time registers.
	ret = regmap_clear_bits(tps->regmap, TPS6594_REG_RTC_CTRL_1,

Annotation

Implementation Notes