Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion arch/arm/boot/dts/hi3516cv300.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@
};

rtc: rtc@12090000 {
compatible = "hisilicon,hi_rtc";
compatible = "hisilicon,hi35xx-rtc";
Comment thread
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.
interrupts = <2>;
reg = <0x12090000 0x10000>;
};
Expand Down
49 changes: 36 additions & 13 deletions drivers/rtc/rtc-hibvt.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ union u_spi_rw {
#define REG_LOCK_STAT BIT(1)
#define REG_LOCK_BYPASS BIT(2)

/*
* A counter that lost every supply restarts from zero and reads as 1970.
* Times before 2000-01-01 are refused both ways, so such a counter reads
* as unset and every time set_time() accepts can be read back.
*/
#define RTC_MIN_VALID_SEC 946684800UL

#define RETRY_CNT 500

#define DATE_TO_SEC(d, h, m, s) (s + m*60 + h*60*60 + d*24*60*60)
Expand Down Expand Up @@ -191,12 +198,15 @@ static int hibvt_rtc_read_time(struct device *dev, struct rtc_time *time)
return ret;
}

if (raw_value & LV_INT_MASK) {
dev_err(dev,
"low voltage detected, date/time is not reliable.\n");
hibvt_spi_write(rtc->regs, RTC_INT_CLR, 1);
return -EINVAL;
}
/*
* Not a verdict on the time: on a hi3516ev300 the flag stays set,
* and returns about half a second after each clear, with a fresh
* backup cell that keeps the counter through a power cut, exactly as
* it did with a flat one. The counter below is what tells. Clear the
* flag by its own bit: writing 1 acknowledged the alarm instead.
*/
if (raw_value & LV_INT_MASK)
hibvt_spi_write(rtc->regs, RTC_INT_CLR, LV_INT_MASK);

ret |= hibvt_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value);
if (raw_value & REG_LOCK_BYPASS)
Expand Down Expand Up @@ -230,6 +240,13 @@ static int hibvt_rtc_read_time(struct device *dev, struct rtc_time *time)
day = (dayl | (dayh << 8));
seconds = DATE_TO_SEC(day, hour, minute, second);

/*
* Report a counter that restarted from zero as unset, so hctosys
* leaves the clock alone instead of stepping it to 1970.
*/
if (seconds < RTC_MIN_VALID_SEC)
return -EINVAL;

rtc_time_to_tm(seconds, time);

return rtc_valid_tm(time);
Expand All @@ -238,7 +255,7 @@ static int hibvt_rtc_read_time(struct device *dev, struct rtc_time *time)
static int hibvt_rtc_set_time(struct device *dev, struct rtc_time *time)
{
struct hibvt_rtc *rtc = dev_get_drvdata(dev);
unsigned char ret = 0;
int ret = 0;
unsigned int days;
unsigned long seconds = 0;
unsigned int cnt = RETRY_CNT;
Expand All @@ -247,6 +264,8 @@ static int hibvt_rtc_set_time(struct device *dev, struct rtc_time *time)
ret = rtc_tm_to_time(time, &seconds);
if (ret)
return ret;
if (seconds < RTC_MIN_VALID_SEC)
return -EINVAL;
days = SEC_TO_DAY(seconds);

ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_10MS, 0);
Expand Down Expand Up @@ -486,8 +505,15 @@ static int hibvt_rtc_init(struct hibvt_rtc *rtc)
ret |= hibvt_spi_rtc_write(spi_reg, RTC_IMSC, INT_MSK_DEFAULT);
ret |= hibvt_spi_rtc_write(spi_reg, RTC_SAR_CTRL, LV_CTL_DEFAULT);



#ifndef CONFIG_ARCH_HI3516CV300
/*
* The HiSilicon SDK's own hi3516cv300 RTC driver never writes
* RTC_CLK_CFG, and the register reads 0 on a running board, so leave
* the oscillator settings of that family as they come.
*/
ret |= hibvt_spi_rtc_write(spi_reg, RTC_CLK_CFG, 0x01);
#endif

/* default FREQ COEF */
ret |= hibvt_spi_rtc_write(spi_reg, RTC_FREQ_H, FREQ_H_DEFAULT);
Expand All @@ -500,11 +526,8 @@ static int hibvt_rtc_init(struct hibvt_rtc *rtc)
return ret;
}

if (val & LV_INT_MASK) {
dev_err(&rtc->rtc_dev->dev,
"low voltage detected, date/time is not reliable.\n");
hibvt_spi_write(rtc->regs, RTC_INT_CLR, 1);
}
if (val & LV_INT_MASK)
hibvt_spi_write(rtc->regs, RTC_INT_CLR, LV_INT_MASK);

return ret;
}
Expand Down