drivers/rtc/rtc-amlogic-a4.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-amlogic-a4.c
Extension
.c
Size
11662 bytes
Lines
444
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 aml_rtc_config {
	bool gray_stored;
};

struct aml_rtc_data {
	struct regmap *map;
	struct rtc_device *rtc_dev;
	int irq;
	struct clk *rtc_clk;
	struct clk *sys_clk;
	int rtc_enabled;
	const struct aml_rtc_config *config;
};

static inline u32 gray_to_binary(u32 gray)
{
	u32 bcd = gray;
	int size = sizeof(bcd) * 8;
	int i;

	for (i = 0; (1 << i) < size; i++)
		bcd ^= bcd >> (1 << i);

	return bcd;
}

static inline u32 binary_to_gray(u32 bcd)
{
	return bcd ^ (bcd >> 1);
}

static int aml_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct aml_rtc_data *rtc = dev_get_drvdata(dev);
	u32 time_sec;

	/* if RTC disabled, read time failed */
	if (!rtc->rtc_enabled)
		return -EINVAL;

	regmap_read(rtc->map, RTC_REAL_TIME, &time_sec);
	if (rtc->config->gray_stored)
		time_sec = gray_to_binary(time_sec);
	rtc_time64_to_tm(time_sec, tm);
	dev_dbg(dev, "%s: read time = %us\n", __func__, time_sec);

	return 0;
}

static int aml_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct aml_rtc_data *rtc = dev_get_drvdata(dev);
	u32 time_sec;

	/* if RTC disabled, first enable it */
	if (!rtc->rtc_enabled) {
		regmap_write_bits(rtc->map, RTC_CTRL, RTC_ENABLE, RTC_ENABLE);
		usleep_range(100, 200);
		rtc->rtc_enabled = regmap_test_bits(rtc->map, RTC_CTRL, RTC_ENABLE);
		if (!rtc->rtc_enabled)
			return -EINVAL;
	}

	time_sec = rtc_tm_to_time64(tm);
	if (rtc->config->gray_stored)
		time_sec = binary_to_gray(time_sec);
	regmap_write(rtc->map, RTC_COUNTER_REG, time_sec);
	dev_dbg(dev, "%s: set time = %us\n", __func__, time_sec);

	return 0;
}

static int aml_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
	struct aml_rtc_data *rtc = dev_get_drvdata(dev);
	time64_t alarm_sec;

	/* if RTC disabled, set alarm failed */
	if (!rtc->rtc_enabled)
		return -EINVAL;

	regmap_update_bits(rtc->map, RTC_CTRL,
			   RTC_ALRM0_EN, RTC_ALRM0_EN);
	regmap_update_bits(rtc->map, RTC_INT_MASK,
			   RTC_ALRM0_IRQ_MSK, 0);

	alarm_sec = rtc_tm_to_time64(&alarm->time);
	if (rtc->config->gray_stored)
		alarm_sec = binary_to_gray(alarm_sec);
	regmap_write(rtc->map, RTC_ALARM0_REG, alarm_sec);

Annotation

Implementation Notes