diff mbox series

MIPS: Loongson64: Add read_persistent_clock64()

Message ID 1605169793-10481-1-git-send-email-yangtiezhu@loongson.cn (mailing list archive)
State New
Headers show
Series MIPS: Loongson64: Add read_persistent_clock64() | expand

Commit Message

Tiezhu Yang Nov. 12, 2020, 8:29 a.m. UTC
Add read_persistent_clock64() to read the time from the battery backed
persistent clock. With this patch, we can fix the wrong time issue due
to the system clock is not consistent with hardware clock after resume
from sleep state S3 (suspend to RAM), at the same time, the system time
can be right instead of "Thu Jan 1 08:00:00 CST 1970" without rtc driver.

start_kernel()
  timekeeping_init()
    read_persistent_wall_and_boot_offset()
      read_persistent_clock64()

timekeeping_resume()
  read_persistent_clock64()

timekeeping_suspend()
  read_persistent_clock64()

Signed-off-by: Yinglu Yang <yangyinglu@loongson.cn>
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 arch/mips/include/asm/mach-loongson64/loongson.h | 20 +++++++++++++++++
 arch/mips/loongson64/time.c                      | 28 +++++++++++++++++++++++-
 2 files changed, 47 insertions(+), 1 deletion(-)

Comments

Jiaxun Yang Nov. 12, 2020, 10:04 a.m. UTC | #1
Hi Tiezhu,

在 2020/11/12 16:29, Tiezhu Yang 写道:
> Add read_persistent_clock64() to read the time from the battery backed
> persistent clock. With this patch, we can fix the wrong time issue due
> to the system clock is not consistent with hardware clock after resume
> from sleep state S3 (suspend to RAM), at the same time, the system time
> can be right instead of "Thu Jan 1 08:00:00 CST 1970" without rtc driver.
>
> start_kernel()
>    timekeeping_init()
>      read_persistent_wall_and_boot_offset()
>        read_persistent_clock64()
>
> timekeeping_resume()
>    read_persistent_clock64()
>
> timekeeping_suspend()
>    read_persistent_clock64()

It is highly discoraged to do anything with bridgetype, which isn't 
probed via
devicetree.

Please check if you can deal with that inside RTC framework, or make it as
a part of RTC driver (e.g. set up a callback).

Also you should submit RTC driver at first if you intend to complete 
LS7A support.

Thanks.

- Jiaxun

>
> Signed-off-by: Yinglu Yang <yangyinglu@loongson.cn>
> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
> ---
>   arch/mips/include/asm/mach-loongson64/loongson.h | 20 +++++++++++++++++
>   arch/mips/loongson64/time.c                      | 28 +++++++++++++++++++++++-
>   2 files changed, 47 insertions(+), 1 deletion(-)
>
> diff --git a/arch/mips/include/asm/mach-loongson64/loongson.h b/arch/mips/include/asm/mach-loongson64/loongson.h
> index fde1b75..448289e 100644
> --- a/arch/mips/include/asm/mach-loongson64/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson64/loongson.h
> @@ -238,4 +238,24 @@ extern u64 loongson_freqctrl[MAX_PACKAGES];
>   #define LOONGSON_PCIMAP_WIN(WIN, ADDR)	\
>   	((((ADDR)>>26) & LOONGSON_PCIMAP_PCIMAP_LO0) << ((WIN)*6))
>   
> +/* LS7A RTC */
> +#define LS7A_MISC_REG_BASE		0x10080000
> +#define LS7A_RTC_ADDR_OFFSET		0x50100
> +#define LS7A_RTC_SYS_TOYREAD0_OFFSET	0x2c
> +#define LS7A_RTC_SYS_TOYREAD1_OFFSET	0x30
> +#define LS7A_RTC_REG_BASE		(LS7A_MISC_REG_BASE + LS7A_RTC_ADDR_OFFSET)
> +#define LS7A_RTC_SYS_TOYREAD0_ADDR	(LS7A_RTC_REG_BASE + LS7A_RTC_SYS_TOYREAD0_OFFSET)
> +#define LS7A_RTC_SYS_TOYREAD1_ADDR	(LS7A_RTC_REG_BASE + LS7A_RTC_SYS_TOYREAD1_OFFSET)
> +#define LS7A_RTC_TOY_MON_MASK		GENMASK(31, 26)
> +#define LS7A_RTC_TOY_MON_SHIFT		26
> +#define LS7A_RTC_TOY_DAY_MASK		GENMASK(25, 21)
> +#define LS7A_RTC_TOY_DAY_SHIFT		21
> +#define LS7A_RTC_TOY_HOUR_MASK		GENMASK(20, 16)
> +#define LS7A_RTC_TOY_HOUR_SHIFT		16
> +#define LS7A_RTC_TOY_MIN_MASK		GENMASK(15, 10)
> +#define LS7A_RTC_TOY_MIN_SHIFT		10
> +#define LS7A_RTC_TOY_SEC_MASK		GENMASK(9, 4)
> +#define LS7A_RTC_TOY_SEC_SHIFT		4
> +#define LS7A_RTC_YEAR_BASE		1900
> +
>   #endif /* __ASM_MACH_LOONGSON64_LOONGSON_H */
> diff --git a/arch/mips/loongson64/time.c b/arch/mips/loongson64/time.c
> index 91e842b..7f3095546 100644
> --- a/arch/mips/loongson64/time.c
> +++ b/arch/mips/loongson64/time.c
> @@ -9,7 +9,7 @@
>   
>   #include <asm/time.h>
>   #include <asm/hpet.h>
> -
> +#include <asm/mc146818-time.h>
>   #include <loongson.h>
>   
>   void __init plat_time_init(void)
> @@ -21,3 +21,29 @@ void __init plat_time_init(void)
>   	setup_hpet_timer();
>   #endif
>   }
> +
> +static time64_t ls7a_get_rtc_time(void)
> +{
> +	unsigned int year, mon, day, hour, min, sec;
> +	unsigned int value;
> +
> +	value = readl((void __iomem *)TO_UNCAC(LS7A_RTC_SYS_TOYREAD0_ADDR));
> +	sec = (value & LS7A_RTC_TOY_SEC_MASK) >> LS7A_RTC_TOY_SEC_SHIFT;
> +	min = (value & LS7A_RTC_TOY_MIN_MASK) >> LS7A_RTC_TOY_MIN_SHIFT;
> +	hour = (value & LS7A_RTC_TOY_HOUR_MASK) >> LS7A_RTC_TOY_HOUR_SHIFT;
> +	day = (value & LS7A_RTC_TOY_DAY_MASK) >> LS7A_RTC_TOY_DAY_SHIFT;
> +	mon = (value & LS7A_RTC_TOY_MON_MASK) >> LS7A_RTC_TOY_MON_SHIFT;
> +	year = readl((void __iomem *)TO_UNCAC(LS7A_RTC_SYS_TOYREAD1_ADDR));
> +
> +	return mktime64(year + LS7A_RTC_YEAR_BASE, mon, day, hour, min, sec);
> +}
> +
> +void read_persistent_clock64(struct timespec64 *ts)
> +{
> +	if (loongson_sysconf.bridgetype == LS7A)
> +		ts->tv_sec = ls7a_get_rtc_time();
> +	else
> +		ts->tv_sec = mc146818_get_cmos_time();
> +
> +	ts->tv_nsec = 0;
> +}
Jiaxun Yang Nov. 12, 2020, 10:09 a.m. UTC | #2
在 2020/11/12 18:04, Jiaxun Yang 写道:
> Hi Tiezhu,
>
> 在 2020/11/12 16:29, Tiezhu Yang 写道:
>> Add read_persistent_clock64() to read the time from the battery backed
>> persistent clock. With this patch, we can fix the wrong time issue due
>> to the system clock is not consistent with hardware clock after resume
>> from sleep state S3 (suspend to RAM), at the same time, the system time
>> can be right instead of "Thu Jan 1 08:00:00 CST 1970" without rtc 
>> driver.
>>
>> start_kernel()
>>    timekeeping_init()
>>      read_persistent_wall_and_boot_offset()
>>        read_persistent_clock64()
>>
>> timekeeping_resume()
>>    read_persistent_clock64()
>>
>> timekeeping_suspend()
>>    read_persistent_clock64()
>
> It is highly discoraged to do anything with bridgetype, which isn't 
> probed via
> devicetree.
>
> Please check if you can deal with that inside RTC framework, or make 
> it as
> a part of RTC driver (e.g. set up a callback).
>
> Also you should submit RTC driver at first if you intend to complete 
> LS7A support.

Oops,
Just dig it deeper, I guess simply select RTC_HCTOSYS would solve the issue.
We're trying very hard to decouple all the drivers and conponents,
DeviceTree for all!

>
> Thanks.
>
> - Jiaxun
>
>>
>> Signed-off-by: Yinglu Yang <yangyinglu@loongson.cn>
>> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>> ---
>>
Tiezhu Yang Nov. 12, 2020, 12:03 p.m. UTC | #3
On 11/12/2020 06:09 PM, Jiaxun Yang wrote:
>
>
> 在 2020/11/12 18:04, Jiaxun Yang 写道:
>> Hi Tiezhu,
>>
>> 在 2020/11/12 16:29, Tiezhu Yang 写道:
>>> Add read_persistent_clock64() to read the time from the battery backed
>>> persistent clock. With this patch, we can fix the wrong time issue due
>>> to the system clock is not consistent with hardware clock after resume
>>> from sleep state S3 (suspend to RAM), at the same time, the system time
>>> can be right instead of "Thu Jan 1 08:00:00 CST 1970" without rtc 
>>> driver.
>>>
>>> start_kernel()
>>>    timekeeping_init()
>>>      read_persistent_wall_and_boot_offset()
>>>        read_persistent_clock64()
>>>
>>> timekeeping_resume()
>>>    read_persistent_clock64()
>>>
>>> timekeeping_suspend()
>>>    read_persistent_clock64()
>>
>> It is highly discoraged to do anything with bridgetype, which isn't 
>> probed via
>> devicetree.
>>
>> Please check if you can deal with that inside RTC framework, or make 
>> it as
>> a part of RTC driver (e.g. set up a callback).
>>
>> Also you should submit RTC driver at first if you intend to complete 
>> LS7A support.
>
> Oops,
> Just dig it deeper, I guess simply select RTC_HCTOSYS would solve the 
> issue.
> We're trying very hard to decouple all the drivers and conponents,
> DeviceTree for all!

+cc WANG Xuerui <git@xen0n.name>

Hi Jiaxun,

Thanks for your reply.

Xuerui has already submitted the patch of LS7A rtc driver [1],
but not yet been merged into the mainline kernel, I discussed
with him early today.

Do you mean that read_persistent_clock64() can call the function
like rtc_read_time() defined in rtc driver?

Thanks,
Tiezhu

[1] 
https://patchwork.kernel.org/project/linux-mips/patch/20200923075845.360974-2-git@xen0n.name/

>
>>
>> Thanks.
>>
>> - Jiaxun
>>
>>>
>>> Signed-off-by: Yinglu Yang <yangyinglu@loongson.cn>
>>> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>>> ---
>>>
Jiaxun Yang Nov. 13, 2020, 2:21 a.m. UTC | #4
在 2020/11/12 20:03, Tiezhu Yang 写道:
> On 11/12/2020 06:09 PM, Jiaxun Yang wrote:
>>
>>
>> 在 2020/11/12 18:04, Jiaxun Yang 写道:
>>> Hi Tiezhu,
>>>
>>> 在 2020/11/12 16:29, Tiezhu Yang 写道:
>>>> Add read_persistent_clock64() to read the time from the battery backed
>>>> persistent clock. With this patch, we can fix the wrong time issue due
>>>> to the system clock is not consistent with hardware clock after resume
>>>> from sleep state S3 (suspend to RAM), at the same time, the system 
>>>> time
>>>> can be right instead of "Thu Jan 1 08:00:00 CST 1970" without rtc 
>>>> driver.
>>>>
>>>> start_kernel()
>>>>    timekeeping_init()
>>>>      read_persistent_wall_and_boot_offset()
>>>>        read_persistent_clock64()
>>>>
>>>> timekeeping_resume()
>>>>    read_persistent_clock64()
>>>>
>>>> timekeeping_suspend()
>>>>    read_persistent_clock64()
>>>
>>> It is highly discoraged to do anything with bridgetype, which isn't 
>>> probed via
>>> devicetree.
>>>
>>> Please check if you can deal with that inside RTC framework, or make 
>>> it as
>>> a part of RTC driver (e.g. set up a callback).
>>>
>>> Also you should submit RTC driver at first if you intend to complete 
>>> LS7A support.
>>
>> Oops,
>> Just dig it deeper, I guess simply select RTC_HCTOSYS would solve the 
>> issue.
>> We're trying very hard to decouple all the drivers and conponents,
>> DeviceTree for all!
>
> +cc WANG Xuerui <git@xen0n.name>
>
> Hi Jiaxun,
>
> Thanks for your reply.
>
> Xuerui has already submitted the patch of LS7A rtc driver [1],
> but not yet been merged into the mainline kernel, I discussed
> with him early today.
>
> Do you mean that read_persistent_clock64() can call the function
> like rtc_read_time() defined in rtc driver?

I do think select RTC_HCTOSYS after getting RTC driver applied can help.
What's your point to have read_persistent_clock64 for Loongson64?

Thanks

- Jiaxun

>
> Thanks,
> Tiezhu
>
> [1] 
> https://patchwork.kernel.org/project/linux-mips/patch/20200923075845.360974-2-git@xen0n.name/
>
>>
>>>
>>> Thanks.
>>>
>>> - Jiaxun
>>>
>>>>
>>>> Signed-off-by: Yinglu Yang <yangyinglu@loongson.cn>
>>>> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>>>> ---
>>>>
Tiezhu Yang Nov. 13, 2020, 3:41 a.m. UTC | #5
On 11/13/2020 10:21 AM, Jiaxun Yang wrote:
>
>
> 在 2020/11/12 20:03, Tiezhu Yang 写道:
>> On 11/12/2020 06:09 PM, Jiaxun Yang wrote:
>>>
>>>
>>> 在 2020/11/12 18:04, Jiaxun Yang 写道:
>>>> Hi Tiezhu,
>>>>
>>>> 在 2020/11/12 16:29, Tiezhu Yang 写道:
>>>>> Add read_persistent_clock64() to read the time from the battery 
>>>>> backed
>>>>> persistent clock. With this patch, we can fix the wrong time issue 
>>>>> due
>>>>> to the system clock is not consistent with hardware clock after 
>>>>> resume
>>>>> from sleep state S3 (suspend to RAM), at the same time, the system 
>>>>> time
>>>>> can be right instead of "Thu Jan 1 08:00:00 CST 1970" without rtc 
>>>>> driver.
>>>>>
>>>>> start_kernel()
>>>>>    timekeeping_init()
>>>>>      read_persistent_wall_and_boot_offset()
>>>>>        read_persistent_clock64()
>>>>>
>>>>> timekeeping_resume()
>>>>>    read_persistent_clock64()
>>>>>
>>>>> timekeeping_suspend()
>>>>>    read_persistent_clock64()
>>>>
>>>> It is highly discoraged to do anything with bridgetype, which isn't 
>>>> probed via
>>>> devicetree.
>>>>
>>>> Please check if you can deal with that inside RTC framework, or 
>>>> make it as
>>>> a part of RTC driver (e.g. set up a callback).
>>>>
>>>> Also you should submit RTC driver at first if you intend to 
>>>> complete LS7A support.
>>>
>>> Oops,
>>> Just dig it deeper, I guess simply select RTC_HCTOSYS would solve 
>>> the issue.
>>> We're trying very hard to decouple all the drivers and conponents,
>>> DeviceTree for all!
>>
>> +cc WANG Xuerui <git@xen0n.name>
>>
>> Hi Jiaxun,
>>
>> Thanks for your reply.
>>
>> Xuerui has already submitted the patch of LS7A rtc driver [1],
>> but not yet been merged into the mainline kernel, I discussed
>> with him early today.
>>
>> Do you mean that read_persistent_clock64() can call the function
>> like rtc_read_time() defined in rtc driver?
>
> I do think select RTC_HCTOSYS after getting RTC driver applied can help.

Yes, I agree.

> What's your point to have read_persistent_clock64 for Loongson64?

(1) Currently, the LS7A RTC driver has not been merged into the
mainline kernel, read_persistent_clock64() is useful in the following
call path:

start_kernel()
    timekeeping_init()
      read_persistent_wall_and_boot_offset()
        read_persistent_clock64()

(2) When the LS7A RTC driver is merged into the mainline kernel
some time later, if RTC_HCTOSYS and RTC_DRV_LS2X are not set,
read_persistent_clock64() is also useful unless RTC_HCTOSYS
and RTC_DRV_LS2X are set by default in Kconfig instead of
loongson3_defconfig.

So I think read_persistent_clock64() looks like a backup function.

>
> Thanks
>
> - Jiaxun
>
>>
>> Thanks,
>> Tiezhu
>>
>> [1] 
>> https://patchwork.kernel.org/project/linux-mips/patch/20200923075845.360974-2-git@xen0n.name/
>>
>>>
>>>>
>>>> Thanks.
>>>>
>>>> - Jiaxun
>>>>
>>>>>
>>>>> Signed-off-by: Yinglu Yang <yangyinglu@loongson.cn>
>>>>> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>>>>> ---
>>>>>
Jiaxun Yang Nov. 13, 2020, 8:24 a.m. UTC | #6
于 2020年11月13日 GMT+08:00 上午11:41:01, Tiezhu Yang <yangtiezhu@loongson.cn> 写到:
>On 11/13/2020 10:21 AM, Jiaxun Yang wrote:
>>
>>
>> 在 2020/11/12 20:03, Tiezhu Yang 写道:
>>> On 11/12/2020 06:09 PM, Jiaxun Yang wrote:
>>>>
>>>>
>>>> 在 2020/11/12 18:04, Jiaxun Yang 写道:
>>>>> Hi Tiezhu,
>>>>>
>>>>> 在 2020/11/12 16:29, Tiezhu Yang 写道:
>>>>>> Add read_persistent_clock64() to read the time from the battery 
>>>>>> backed
>>>>>> persistent clock. With this patch, we can fix the wrong time issue 
>>>>>> due
>>>>>> to the system clock is not consistent with hardware clock after 
>>>>>> resume
>>>>>> from sleep state S3 (suspend to RAM), at the same time, the system 
>>>>>> time
>>>>>> can be right instead of "Thu Jan 1 08:00:00 CST 1970" without rtc 
>>>>>> driver.
>>>>>>
>>>>>> start_kernel()
>>>>>>    timekeeping_init()
>>>>>>      read_persistent_wall_and_boot_offset()
>>>>>>        read_persistent_clock64()
>>>>>>
>>>>>> timekeeping_resume()
>>>>>>    read_persistent_clock64()
>>>>>>
>>>>>> timekeeping_suspend()
>>>>>>    read_persistent_clock64()
>>>>>
>>>>> It is highly discoraged to do anything with bridgetype, which isn't 
>>>>> probed via
>>>>> devicetree.
>>>>>
>>>>> Please check if you can deal with that inside RTC framework, or 
>>>>> make it as
>>>>> a part of RTC driver (e.g. set up a callback).
>>>>>
>>>>> Also you should submit RTC driver at first if you intend to 
>>>>> complete LS7A support.
>>>>
>>>> Oops,
>>>> Just dig it deeper, I guess simply select RTC_HCTOSYS would solve 
>>>> the issue.
>>>> We're trying very hard to decouple all the drivers and conponents,
>>>> DeviceTree for all!
>>>
>>> +cc WANG Xuerui <git@xen0n.name>
>>>
>>> Hi Jiaxun,
>>>
>>> Thanks for your reply.
>>>
>>> Xuerui has already submitted the patch of LS7A rtc driver [1],
>>> but not yet been merged into the mainline kernel, I discussed
>>> with him early today.
>>>
>>> Do you mean that read_persistent_clock64() can call the function
>>> like rtc_read_time() defined in rtc driver?
>>
>> I do think select RTC_HCTOSYS after getting RTC driver applied can help.
>
>Yes, I agree.
>
>> What's your point to have read_persistent_clock64 for Loongson64?
>
>(1) Currently, the LS7A RTC driver has not been merged into the
>mainline kernel, read_persistent_clock64() is useful in the following
>call path:
>
>start_kernel()
>    timekeeping_init()
>      read_persistent_wall_and_boot_offset()
>        read_persistent_clock64()
>
>(2) When the LS7A RTC driver is merged into the mainline kernel
>some time later, if RTC_HCTOSYS and RTC_DRV_LS2X are not set,
>read_persistent_clock64() is also useful unless RTC_HCTOSYS
>and RTC_DRV_LS2X are set by default in Kconfig instead of
>loongson3_defconfig.
>
>So I think read_persistent_clock64() looks like a backup function.

Still can't understand why this kind of backup is necessary.
If you wish to help please help with the RTC driver.

Duplication is not the way we work.
Please try to learn common solutions, all others are doing so.

Thanks

- Jiaxun


>
>>
>> Thanks
>>
>> - Jiaxun
>>
>>>
>>> Thanks,
>>> Tiezhu
>>>
>>> [1] 
>>> https://patchwork.kernel.org/project/linux-mips/patch/20200923075845.360974-2-git@xen0n.name/
>>>
>>>>
>>>>>
>>>>> Thanks.
>>>>>
>>>>> - Jiaxun
>>>>>
>>>>>>
>>>>>> Signed-off-by: Yinglu Yang <yangyinglu@loongson.cn>
>>>>>> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>>>>>> ---
>>>>>>
diff mbox series

Patch

diff --git a/arch/mips/include/asm/mach-loongson64/loongson.h b/arch/mips/include/asm/mach-loongson64/loongson.h
index fde1b75..448289e 100644
--- a/arch/mips/include/asm/mach-loongson64/loongson.h
+++ b/arch/mips/include/asm/mach-loongson64/loongson.h
@@ -238,4 +238,24 @@  extern u64 loongson_freqctrl[MAX_PACKAGES];
 #define LOONGSON_PCIMAP_WIN(WIN, ADDR)	\
 	((((ADDR)>>26) & LOONGSON_PCIMAP_PCIMAP_LO0) << ((WIN)*6))
 
+/* LS7A RTC */
+#define LS7A_MISC_REG_BASE		0x10080000
+#define LS7A_RTC_ADDR_OFFSET		0x50100
+#define LS7A_RTC_SYS_TOYREAD0_OFFSET	0x2c
+#define LS7A_RTC_SYS_TOYREAD1_OFFSET	0x30
+#define LS7A_RTC_REG_BASE		(LS7A_MISC_REG_BASE + LS7A_RTC_ADDR_OFFSET)
+#define LS7A_RTC_SYS_TOYREAD0_ADDR	(LS7A_RTC_REG_BASE + LS7A_RTC_SYS_TOYREAD0_OFFSET)
+#define LS7A_RTC_SYS_TOYREAD1_ADDR	(LS7A_RTC_REG_BASE + LS7A_RTC_SYS_TOYREAD1_OFFSET)
+#define LS7A_RTC_TOY_MON_MASK		GENMASK(31, 26)
+#define LS7A_RTC_TOY_MON_SHIFT		26
+#define LS7A_RTC_TOY_DAY_MASK		GENMASK(25, 21)
+#define LS7A_RTC_TOY_DAY_SHIFT		21
+#define LS7A_RTC_TOY_HOUR_MASK		GENMASK(20, 16)
+#define LS7A_RTC_TOY_HOUR_SHIFT		16
+#define LS7A_RTC_TOY_MIN_MASK		GENMASK(15, 10)
+#define LS7A_RTC_TOY_MIN_SHIFT		10
+#define LS7A_RTC_TOY_SEC_MASK		GENMASK(9, 4)
+#define LS7A_RTC_TOY_SEC_SHIFT		4
+#define LS7A_RTC_YEAR_BASE		1900
+
 #endif /* __ASM_MACH_LOONGSON64_LOONGSON_H */
diff --git a/arch/mips/loongson64/time.c b/arch/mips/loongson64/time.c
index 91e842b..7f3095546 100644
--- a/arch/mips/loongson64/time.c
+++ b/arch/mips/loongson64/time.c
@@ -9,7 +9,7 @@ 
 
 #include <asm/time.h>
 #include <asm/hpet.h>
-
+#include <asm/mc146818-time.h>
 #include <loongson.h>
 
 void __init plat_time_init(void)
@@ -21,3 +21,29 @@  void __init plat_time_init(void)
 	setup_hpet_timer();
 #endif
 }
+
+static time64_t ls7a_get_rtc_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	unsigned int value;
+
+	value = readl((void __iomem *)TO_UNCAC(LS7A_RTC_SYS_TOYREAD0_ADDR));
+	sec = (value & LS7A_RTC_TOY_SEC_MASK) >> LS7A_RTC_TOY_SEC_SHIFT;
+	min = (value & LS7A_RTC_TOY_MIN_MASK) >> LS7A_RTC_TOY_MIN_SHIFT;
+	hour = (value & LS7A_RTC_TOY_HOUR_MASK) >> LS7A_RTC_TOY_HOUR_SHIFT;
+	day = (value & LS7A_RTC_TOY_DAY_MASK) >> LS7A_RTC_TOY_DAY_SHIFT;
+	mon = (value & LS7A_RTC_TOY_MON_MASK) >> LS7A_RTC_TOY_MON_SHIFT;
+	year = readl((void __iomem *)TO_UNCAC(LS7A_RTC_SYS_TOYREAD1_ADDR));
+
+	return mktime64(year + LS7A_RTC_YEAR_BASE, mon, day, hour, min, sec);
+}
+
+void read_persistent_clock64(struct timespec64 *ts)
+{
+	if (loongson_sysconf.bridgetype == LS7A)
+		ts->tv_sec = ls7a_get_rtc_time();
+	else
+		ts->tv_sec = mc146818_get_cmos_time();
+
+	ts->tv_nsec = 0;
+}