Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/kernel.h>
0003 #include <linux/time.h>
0004 #include <linux/timer.h>
0005 #include <linux/init.h>
0006 #include <linux/rtc.h>
0007 #include <linux/delay.h>
0008 #include <linux/ratelimit.h>
0009 #include <asm/rtas.h>
0010 #include <asm/time.h>
0011 
0012 
0013 #define MAX_RTC_WAIT 5000   /* 5 sec */
0014 
0015 time64_t __init rtas_get_boot_time(void)
0016 {
0017     int ret[8];
0018     int error;
0019     unsigned int wait_time;
0020     u64 max_wait_tb;
0021 
0022     max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
0023     do {
0024         error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
0025 
0026         wait_time = rtas_busy_delay_time(error);
0027         if (wait_time) {
0028             /* This is boot time so we spin. */
0029             udelay(wait_time*1000);
0030         }
0031     } while (wait_time && (get_tb() < max_wait_tb));
0032 
0033     if (error != 0) {
0034         printk_ratelimited(KERN_WARNING
0035                    "error: reading the clock failed (%d)\n",
0036                    error);
0037         return 0;
0038     }
0039 
0040     return mktime64(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]);
0041 }
0042 
0043 /* NOTE: get_rtc_time will get an error if executed in interrupt context
0044  * and if a delay is needed to read the clock.  In this case we just
0045  * silently return without updating rtc_tm.
0046  */
0047 void rtas_get_rtc_time(struct rtc_time *rtc_tm)
0048 {
0049         int ret[8];
0050     int error;
0051     unsigned int wait_time;
0052     u64 max_wait_tb;
0053 
0054     max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
0055     do {
0056         error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
0057 
0058         wait_time = rtas_busy_delay_time(error);
0059         if (wait_time) {
0060             if (in_interrupt()) {
0061                 memset(rtc_tm, 0, sizeof(struct rtc_time));
0062                 printk_ratelimited(KERN_WARNING
0063                            "error: reading clock "
0064                            "would delay interrupt\n");
0065                 return; /* delay not allowed */
0066             }
0067             msleep(wait_time);
0068         }
0069     } while (wait_time && (get_tb() < max_wait_tb));
0070 
0071     if (error != 0) {
0072         printk_ratelimited(KERN_WARNING
0073                    "error: reading the clock failed (%d)\n",
0074                    error);
0075         return;
0076         }
0077 
0078     rtc_tm->tm_sec = ret[5];
0079     rtc_tm->tm_min = ret[4];
0080     rtc_tm->tm_hour = ret[3];
0081     rtc_tm->tm_mday = ret[2];
0082     rtc_tm->tm_mon = ret[1] - 1;
0083     rtc_tm->tm_year = ret[0] - 1900;
0084 }
0085 
0086 int rtas_set_rtc_time(struct rtc_time *tm)
0087 {
0088     int error, wait_time;
0089     u64 max_wait_tb;
0090 
0091     max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
0092     do {
0093             error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL,
0094                   tm->tm_year + 1900, tm->tm_mon + 1,
0095                   tm->tm_mday, tm->tm_hour, tm->tm_min,
0096                   tm->tm_sec, 0);
0097 
0098         wait_time = rtas_busy_delay_time(error);
0099         if (wait_time) {
0100             if (in_interrupt())
0101                 return 1;   /* probably decrementer */
0102             msleep(wait_time);
0103         }
0104     } while (wait_time && (get_tb() < max_wait_tb));
0105 
0106     if (error != 0)
0107         printk_ratelimited(KERN_WARNING
0108                    "error: setting the clock failed (%d)\n",
0109                    error);
0110 
0111         return 0;
0112 }