patch-2.2.17 linux/arch/ppc/kernel/pmac_time.c

Next file: linux/arch/ppc/kernel/ppc-stub.c
Previous file: linux/arch/ppc/kernel/pmac_support.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.16/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c
@@ -22,8 +22,9 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
+#include <asm/nvram.h>
 
-#include "time.h"
+#include <asm/time.h>
 
 /* Apparently the RTC stores seconds since 1 Jan 1904 */
 #define RTC_OFFSET	2082844800
@@ -49,11 +50,32 @@
 /* Bits in IFR and IER */
 #define T1_INT		0x40		/* Timer 1 interrupt */
 
-__pmac
+extern struct timezone sys_tz;
+
+__init
+void pmac_time_init(void)
+{
+	s32 delta = 0;
+	int dst;
+	
+	delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
+	delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
+	delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
+	if (delta & 0x00800000UL)
+		delta |= 0xFF000000UL;
+	dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
+	printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
+		dst ? "on" : "off");
+	sys_tz.tz_minuteswest = -delta/60;
+	/* I _suppose_ this is 0:off, 1:on */
+	sys_tz.tz_dsttime = dst;
+}
 
+__pmac
 unsigned long pmac_get_rtc_time(void)
 {
 	struct adb_request req;
+	int offset = sys_tz.tz_minuteswest * 60;
 
 	/* Get the time from the RTC */
 	if (adb_controller == 0)
@@ -70,7 +92,7 @@
 			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
 			       req.reply_len);
 		return (req.reply[3] << 24) + (req.reply[4] << 16)
-			+ (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET;
+			+ (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET + offset;
 	case ADB_VIAPMU:
 		if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) {
 			printk("pmac_read_rtc_time: pmu_request failed\n");
@@ -82,7 +104,7 @@
 			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
 			       req.reply_len);
 		return (req.reply[1] << 24) + (req.reply[2] << 16)
-			+ (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET;
+			+ (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET + offset;
 	default:
 		return 0;
 	}
@@ -90,7 +112,51 @@
 
 int pmac_set_rtc_time(unsigned long nowtime)
 {
-	return 0;
+	struct adb_request req;
+	int dst, delta;
+
+	nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60;
+
+	/* Set the time in the RTC */
+	if (adb_controller == 0)
+		return 0;
+	/* adb_controller->kind, not adb_hardware, since that doesn't
+	   get set until we call adb_init - paulus. */
+	switch (adb_controller->kind) {
+	case ADB_VIACUDA:
+		if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
+				 nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
+			return 0;
+		while (!req.complete)
+			cuda_poll();
+//		if (req.reply_len != 7)
+			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		break;
+	case ADB_VIAPMU:
+		if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
+				nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
+			return 0;
+		while (!req.complete)
+			pmu_poll();
+		if (req.reply_len != 5)
+			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		break;
+	default:
+		return 0;
+	}
+
+	/* write the timezone offset back into the xpram */
+	delta = sys_tz.tz_minuteswest * -60;
+	pmac_xpram_write(PMAC_XPRAM_MACHINE_LOC + 0x9, delta >> 16);
+	pmac_xpram_write(PMAC_XPRAM_MACHINE_LOC + 0xa, delta >> 8);
+	pmac_xpram_write(PMAC_XPRAM_MACHINE_LOC + 0xb, delta);
+	dst = pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 8);
+	dst = sys_tz.tz_dsttime? (dst | 0x80): (dst & ~0x80);
+	pmac_xpram_write(PMAC_XPRAM_MACHINE_LOC + 8, dst);
+
+	return 1;
 }
 
 /*

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)