aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ppc64/kernel/mf.c85
-rw-r--r--arch/ppc64/kernel/rtc.c39
-rw-r--r--include/asm-ppc64/iSeries/mf.h1
3 files changed, 67 insertions, 58 deletions
diff --git a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c
index 1bd52ece497c..5aca7e8005a8 100644
--- a/arch/ppc64/kernel/mf.c
+++ b/arch/ppc64/kernel/mf.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * mf.c 2 * mf.c
3 * Copyright (C) 2001 Troy D. Armstrong IBM Corporation 3 * Copyright (C) 2001 Troy D. Armstrong IBM Corporation
4 * Copyright (C) 2004 Stephen Rothwell IBM Corporation 4 * Copyright (C) 2004-2005 Stephen Rothwell IBM Corporation
5 * 5 *
6 * This modules exists as an interface between a Linux secondary partition 6 * This modules exists as an interface between a Linux secondary partition
7 * running on an iSeries and the primary partition's Virtual Service 7 * running on an iSeries and the primary partition's Virtual Service
@@ -36,10 +36,12 @@
36 36
37#include <asm/time.h> 37#include <asm/time.h>
38#include <asm/uaccess.h> 38#include <asm/uaccess.h>
39#include <asm/paca.h>
39#include <asm/iSeries/vio.h> 40#include <asm/iSeries/vio.h>
40#include <asm/iSeries/mf.h> 41#include <asm/iSeries/mf.h>
41#include <asm/iSeries/HvLpConfig.h> 42#include <asm/iSeries/HvLpConfig.h>
42#include <asm/iSeries/ItSpCommArea.h> 43#include <asm/iSeries/ItSpCommArea.h>
44#include <asm/iSeries/ItLpQueue.h>
43 45
44/* 46/*
45 * This is the structure layout for the Machine Facilites LPAR event 47 * This is the structure layout for the Machine Facilites LPAR event
@@ -696,36 +698,23 @@ static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
696 complete(&rtc->com); 698 complete(&rtc->com);
697} 699}
698 700
699int mf_get_rtc(struct rtc_time *tm) 701static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
700{ 702{
701 struct ce_msg_comp_data ce_complete;
702 struct rtc_time_data rtc_data;
703 int rc;
704
705 memset(&ce_complete, 0, sizeof(ce_complete));
706 memset(&rtc_data, 0, sizeof(rtc_data));
707 init_completion(&rtc_data.com);
708 ce_complete.handler = &get_rtc_time_complete;
709 ce_complete.token = &rtc_data;
710 rc = signal_ce_msg_simple(0x40, &ce_complete);
711 if (rc)
712 return rc;
713 wait_for_completion(&rtc_data.com);
714 tm->tm_wday = 0; 703 tm->tm_wday = 0;
715 tm->tm_yday = 0; 704 tm->tm_yday = 0;
716 tm->tm_isdst = 0; 705 tm->tm_isdst = 0;
717 if (rtc_data.rc) { 706 if (rc) {
718 tm->tm_sec = 0; 707 tm->tm_sec = 0;
719 tm->tm_min = 0; 708 tm->tm_min = 0;
720 tm->tm_hour = 0; 709 tm->tm_hour = 0;
721 tm->tm_mday = 15; 710 tm->tm_mday = 15;
722 tm->tm_mon = 5; 711 tm->tm_mon = 5;
723 tm->tm_year = 52; 712 tm->tm_year = 52;
724 return rtc_data.rc; 713 return rc;
725 } 714 }
726 715
727 if ((rtc_data.ce_msg.ce_msg[2] == 0xa9) || 716 if ((ce_msg[2] == 0xa9) ||
728 (rtc_data.ce_msg.ce_msg[2] == 0xaf)) { 717 (ce_msg[2] == 0xaf)) {
729 /* TOD clock is not set */ 718 /* TOD clock is not set */
730 tm->tm_sec = 1; 719 tm->tm_sec = 1;
731 tm->tm_min = 1; 720 tm->tm_min = 1;
@@ -736,7 +725,6 @@ int mf_get_rtc(struct rtc_time *tm)
736 mf_set_rtc(tm); 725 mf_set_rtc(tm);
737 } 726 }
738 { 727 {
739 u8 *ce_msg = rtc_data.ce_msg.ce_msg;
740 u8 year = ce_msg[5]; 728 u8 year = ce_msg[5];
741 u8 sec = ce_msg[6]; 729 u8 sec = ce_msg[6];
742 u8 min = ce_msg[7]; 730 u8 min = ce_msg[7];
@@ -765,6 +753,63 @@ int mf_get_rtc(struct rtc_time *tm)
765 return 0; 753 return 0;
766} 754}
767 755
756int mf_get_rtc(struct rtc_time *tm)
757{
758 struct ce_msg_comp_data ce_complete;
759 struct rtc_time_data rtc_data;
760 int rc;
761
762 memset(&ce_complete, 0, sizeof(ce_complete));
763 memset(&rtc_data, 0, sizeof(rtc_data));
764 init_completion(&rtc_data.com);
765 ce_complete.handler = &get_rtc_time_complete;
766 ce_complete.token = &rtc_data;
767 rc = signal_ce_msg_simple(0x40, &ce_complete);
768 if (rc)
769 return rc;
770 wait_for_completion(&rtc_data.com);
771 return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
772}
773
774struct boot_rtc_time_data {
775 int busy;
776 struct ce_msg_data ce_msg;
777 int rc;
778};
779
780static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
781{
782 struct boot_rtc_time_data *rtc = token;
783
784 memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
785 rtc->rc = 0;
786 rtc->busy = 0;
787}
788
789int mf_get_boot_rtc(struct rtc_time *tm)
790{
791 struct ce_msg_comp_data ce_complete;
792 struct boot_rtc_time_data rtc_data;
793 int rc;
794
795 memset(&ce_complete, 0, sizeof(ce_complete));
796 memset(&rtc_data, 0, sizeof(rtc_data));
797 rtc_data.busy = 1;
798 ce_complete.handler = &get_boot_rtc_time_complete;
799 ce_complete.token = &rtc_data;
800 rc = signal_ce_msg_simple(0x40, &ce_complete);
801 if (rc)
802 return rc;
803 /* We need to poll here as we are not yet taking interrupts */
804 while (rtc_data.busy) {
805 extern unsigned long lpevent_count;
806 struct ItLpQueue *lpq = get_paca()->lpqueue_ptr;
807 if (lpq && ItLpQueue_isLpIntPending(lpq))
808 lpevent_count += ItLpQueue_process(lpq, NULL);
809 }
810 return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
811}
812
768int mf_set_rtc(struct rtc_time *tm) 813int mf_set_rtc(struct rtc_time *tm)
769{ 814{
770 char ce_time[12]; 815 char ce_time[12];
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
index 3e70b91375fc..67989055a9fe 100644
--- a/arch/ppc64/kernel/rtc.c
+++ b/arch/ppc64/kernel/rtc.c
@@ -292,47 +292,10 @@ int iSeries_set_rtc_time(struct rtc_time *tm)
292 292
293void iSeries_get_boot_time(struct rtc_time *tm) 293void iSeries_get_boot_time(struct rtc_time *tm)
294{ 294{
295 unsigned long time;
296 static unsigned long lastsec = 1;
297
298 u32 dataWord1 = *((u32 *)(&xSpCommArea.xBcdTimeAtIplStart));
299 u32 dataWord2 = *(((u32 *)&(xSpCommArea.xBcdTimeAtIplStart)) + 1);
300 int year = 1970;
301 int year1 = ( dataWord1 >> 24 ) & 0x000000FF;
302 int year2 = ( dataWord1 >> 16 ) & 0x000000FF;
303 int sec = ( dataWord1 >> 8 ) & 0x000000FF;
304 int min = dataWord1 & 0x000000FF;
305 int hour = ( dataWord2 >> 24 ) & 0x000000FF;
306 int day = ( dataWord2 >> 8 ) & 0x000000FF;
307 int mon = dataWord2 & 0x000000FF;
308
309 if ( piranha_simulator ) 295 if ( piranha_simulator )
310 return; 296 return;
311 297
312 BCD_TO_BIN(sec); 298 mf_get_boot_rtc(tm);
313 BCD_TO_BIN(min);
314 BCD_TO_BIN(hour);
315 BCD_TO_BIN(day);
316 BCD_TO_BIN(mon);
317 BCD_TO_BIN(year1);
318 BCD_TO_BIN(year2);
319 year = year1 * 100 + year2;
320
321 time = mktime(year, mon, day, hour, min, sec);
322 time += ( jiffies / HZ );
323
324 /* Now THIS is a nasty hack!
325 * It ensures that the first two calls get different answers.
326 * That way the loop in init_time (time.c) will not think
327 * the clock is stuck.
328 */
329 if ( lastsec ) {
330 time -= lastsec;
331 --lastsec;
332 }
333
334 to_tm(time, tm);
335 tm->tm_year -= 1900;
336 tm->tm_mon -= 1; 299 tm->tm_mon -= 1;
337} 300}
338#endif 301#endif
diff --git a/include/asm-ppc64/iSeries/mf.h b/include/asm-ppc64/iSeries/mf.h
index 2e59a8e15a0b..db333e1ee216 100644
--- a/include/asm-ppc64/iSeries/mf.h
+++ b/include/asm-ppc64/iSeries/mf.h
@@ -52,6 +52,7 @@ extern void mf_clear_src(void);
52extern void mf_init(void); 52extern void mf_init(void);
53 53
54extern int mf_get_rtc(struct rtc_time *tm); 54extern int mf_get_rtc(struct rtc_time *tm);
55extern int mf_get_boot_rtc(struct rtc_time *tm);
55extern int mf_set_rtc(struct rtc_time *tm); 56extern int mf_set_rtc(struct rtc_time *tm);
56 57
57#endif /* _ASM_PPC64_ISERIES_MF_H */ 58#endif /* _ASM_PPC64_ISERIES_MF_H */