powerpc: Merge in 64-bit powermac support.

This brings in a lot of changes from arch/ppc64/kernel/pmac_*.c to
arch/powerpc/platforms/powermac/*.c and makes various minor tweaks
elsewhere.  On the powermac we now initialize ppc_md by copying
the whole pmac_md structure into it, which required some changes in
the ordering of initializations of individual fields of it.

Signed-off-by: Paul Mackerras <paulus@samba.org>
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index a6d2d23..82982bf 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -33,6 +33,7 @@
 #include <asm/machdep.h>
 #include <asm/time.h>
 #include <asm/nvram.h>
+#include <asm/smu.h>
 
 #undef DEBUG
 
@@ -68,8 +69,8 @@
 
 long __init pmac_time_init(void)
 {
-#ifdef CONFIG_NVRAM
 	s32 delta = 0;
+#ifdef CONFIG_NVRAM
 	int dst;
 	
 	delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
@@ -80,110 +81,181 @@
 	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");
-	return delta;
-#else
-	return 0;
 #endif
+	return delta;
 }
 
+static void to_rtc_time(unsigned long now, struct rtc_time *tm)
+{
+	to_tm(now, tm);
+	tm->tm_year -= 1900;
+	tm->tm_mon -= 1;
+}
+
+static unsigned long from_rtc_time(struct rtc_time *tm)
+{
+	return mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
+		      tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
+#ifdef CONFIG_ADB_CUDA
+static unsigned long cuda_get_time(void)
+{
+	struct adb_request req;
+	unsigned long now;
+
+	if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
+		return 0;
+	while (!req.complete)
+		cuda_poll();
+	if (req.reply_len != 7)
+		printk(KERN_ERR "cuda_get_time: got %d byte reply\n",
+		       req.reply_len);
+	now = (req.reply[3] << 24) + (req.reply[4] << 16)
+		+ (req.reply[5] << 8) + req.reply[6];
+	if (now < RTC_OFFSET)
+		return 0;
+	return now - RTC_OFFSET;
+}
+
+#define cuda_get_rtc_time(tm)	to_rtc_time(cuda_get_time(), (tm))
+
+static int cuda_set_rtc_time(struct rtc_time *tm)
+{
+	unsigned int nowtime;
+	struct adb_request req;
+
+	nowtime = from_rtc_time(tm) + RTC_OFFSET;
+	if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
+			 nowtime >> 24, nowtime >> 16, nowtime >> 8,
+			 nowtime) < 0)
+		return -ENXIO;
+	while (!req.complete)
+		cuda_poll();
+	if ((req.reply_len != 3) && (req.reply_len != 7))
+		printk(KERN_ERR "cuda_set_rtc_time: got %d byte reply\n",
+		       req.reply_len);
+	return 0;
+}
+
+#else
+#define cuda_get_time()		0
+#define cuda_get_rtc_time(tm)
+#define cuda_set_rtc_time(tm)	0
+#endif
+
+#ifdef CONFIG_ADB_PMU
+static unsigned long pmu_get_time(void)
+{
+	struct adb_request req;
+	unsigned long now;
+
+	if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
+		return 0;
+	pmu_wait_complete(&req);
+	if (req.reply_len != 4)
+		printk(KERN_ERR "pmu_get_time: got %d byte reply from PMU\n",
+		       req.reply_len);
+	now = (req.reply[0] << 24) + (req.reply[1] << 16)
+		+ (req.reply[2] << 8) + req.reply[3];
+	if (now < RTC_OFFSET)
+		return 0;
+	return now - RTC_OFFSET;
+}
+
+#define pmu_get_rtc_time(tm)	to_rtc_time(pmu_get_time(), (tm))
+
+static int pmu_set_rtc_time(struct rtc_time *tm)
+{
+	unsigned int nowtime;
+	struct adb_request req;
+
+	nowtime = from_rtc_time(tm) + RTC_OFFSET;
+	if (pmu_request(&req, NULL, 5, PMU_SET_RTC, nowtime >> 24,
+			nowtime >> 16, nowtime >> 8, nowtime) < 0)
+		return -ENXIO;
+	pmu_wait_complete(&req);
+	if (req.reply_len != 0)
+		printk(KERN_ERR "pmu_set_rtc_time: %d byte reply from PMU\n",
+		       req.reply_len);
+	return 0;
+}
+
+#else
+#define pmu_get_time()		0
+#define pmu_get_rtc_time(tm)
+#define pmu_set_rtc_time(tm)	0
+#endif
+
+#ifdef CONFIG_PMAC_SMU
+static unsigned long smu_get_time(void)
+{
+	struct rtc_time tm;
+
+	if (smu_get_rtc_time(&tm, 1))
+		return 0;
+	return from_rtc_time(&tm);
+}
+
+#else
+#define smu_get_time()			0
+#define smu_get_rtc_time(tm, spin)
+#define smu_set_rtc_time(tm, spin)	0
+#endif
+
 unsigned long pmac_get_boot_time(void)
 {
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
-	struct adb_request req;
-	unsigned long now;
-#endif
-
-	/* Get the time from the RTC */
+	/* Get the time from the RTC, used only at boot time */
 	switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
 	case SYS_CTRLER_CUDA:
-		if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
-			return 0;
-		while (!req.complete)
-			cuda_poll();
-		if (req.reply_len != 7)
-			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
-			       req.reply_len);
-		now = (req.reply[3] << 24) + (req.reply[4] << 16)
-			+ (req.reply[5] << 8) + req.reply[6];
-		return now - RTC_OFFSET;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
+		return cuda_get_time();
 	case SYS_CTRLER_PMU:
-		if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
-			return 0;
-		while (!req.complete)
-			pmu_poll();
-		if (req.reply_len != 4)
-			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
-			       req.reply_len);
-		now = (req.reply[0] << 24) + (req.reply[1] << 16)
-			+ (req.reply[2] << 8) + req.reply[3];
-		return now - RTC_OFFSET;
-#endif /* CONFIG_ADB_PMU */
-	default: ;
-	}
-	return 0;
-}
-
-void pmac_get_rtc_time(struct rtc_time *tm)
-{
-	unsigned long now;
-
-	now = pmac_get_boot_time();
-	to_tm(now, tm);
-	tm->tm_year -= 1900;
-	tm->tm_mon -= 1;		/* month is 0-based */
-}
-
-int pmac_set_rtc_time(struct rtc_time *tm)
-{
-	unsigned long nowtime;
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
-	struct adb_request req;
-#endif
-
-	nowtime = mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
-			 tm->tm_hour, tm->tm_min, tm->tm_sec);
-	nowtime += RTC_OFFSET;
-
-	switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
-	case SYS_CTRLER_CUDA:
-		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 != 3) && (req.reply_len != 7))
-			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
-			       req.reply_len);
-		return 1;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
-	case SYS_CTRLER_PMU:
-		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 != 0)
-			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
-			       req.reply_len);
-		return 1;
-#endif /* CONFIG_ADB_PMU */
+		return pmu_get_time();
+	case SYS_CTRLER_SMU:
+		return smu_get_time();
 	default:
 		return 0;
 	}
 }
 
+void pmac_get_rtc_time(struct rtc_time *tm)
+{
+	/* Get the time from the RTC, used only at boot time */
+	switch (sys_ctrler) {
+	case SYS_CTRLER_CUDA:
+		cuda_get_rtc_time(tm);
+		break;
+	case SYS_CTRLER_PMU:
+		pmu_get_rtc_time(tm);
+		break;
+	case SYS_CTRLER_SMU:
+		smu_get_rtc_time(tm, 1);
+		break;
+	default:
+		;
+	}
+}
+
+int pmac_set_rtc_time(struct rtc_time *tm)
+{
+	switch (sys_ctrler) {
+	case SYS_CTRLER_CUDA:
+		return cuda_set_rtc_time(tm);
+	case SYS_CTRLER_PMU:
+		return pmu_set_rtc_time(tm);
+	case SYS_CTRLER_SMU:
+		return smu_set_rtc_time(tm, 1);
+	default:
+		return -ENODEV;
+	}
+}
+
+#ifdef CONFIG_PPC32
 /*
  * Calibrate the decrementer register using VIA timer 1.
  * This is used both on powermacs and CHRP machines.
  */
-int __init
-via_calibrate_decr(void)
+int __init via_calibrate_decr(void)
 {
 	struct device_node *vias;
 	volatile unsigned char __iomem *via;
@@ -217,15 +289,12 @@
 	dend = get_dec();
 
 	ppc_tb_freq = (dstart - dend) * 100 / 6;
-	tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100);
-
-	printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %lu (%u ticks)\n",
-	       tb_ticks_per_jiffy, dstart - dend);
 
 	iounmap(via);
 	
 	return 1;
 }
+#endif
 
 #ifdef CONFIG_PM
 /*
@@ -262,19 +331,17 @@
 
 /*
  * Query the OF and get the decr frequency.
- * This was taken from the pmac time_init() when merging the prep/pmac
- * time functions.
  */
-void __init
-pmac_calibrate_decr(void)
+void __init pmac_calibrate_decr(void)
 {
-	struct device_node *cpu;
-	unsigned int freq, *fp;
-
 #ifdef CONFIG_PM
+	/* XXX why here? */
 	pmu_register_sleep_notifier(&time_sleep_notifier);
 #endif /* CONFIG_PM */
 
+	generic_calibrate_decr();
+
+#ifdef CONFIG_PPC32
 	/* We assume MacRISC2 machines have correct device-tree
 	 * calibration. That's better since the VIA itself seems
 	 * to be slightly off. --BenH
@@ -293,18 +360,5 @@
 	if (machine_is_compatible("PowerMac3,5"))
 		if (via_calibrate_decr())
 			return;
-	/*
-	 * The cpu node should have a timebase-frequency property
-	 * to tell us the rate at which the decrementer counts.
-	 */
-	cpu = find_type_devices("cpu");
-	if (cpu == 0)
-		panic("can't find cpu node in time_init");
-	fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);
-	if (fp == 0)
-		panic("can't get cpu timebase frequency");
-	freq = *fp;
-	printk("time_init: decrementer frequency = %u.%.6u MHz\n",
-	       freq/1000000, freq%1000000);
-	ppc_tb_freq = freq;
+#endif
 }