aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/powermac/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/powermac/time.c')
-rw-r--r--arch/powerpc/platforms/powermac/time.c250
1 files changed, 152 insertions, 98 deletions
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index a6d2d231d5a..82982bf6453 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 @@ long __init pmac_time_init(void)
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;
}
-unsigned long pmac_get_boot_time(void)
+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)
{
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
struct adb_request req;
unsigned long now;
-#endif
- /* Get the time from the RTC */
- 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
- 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: ;
- }
+ 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;
}
-void pmac_get_rtc_time(struct rtc_time *tm)
+#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;
- now = pmac_get_boot_time();
- to_tm(now, tm);
- tm->tm_year -= 1900;
- tm->tm_mon -= 1; /* month is 0-based */
+ 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;
}
-int pmac_set_rtc_time(struct rtc_time *tm)
+#define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm))
+
+static int pmu_set_rtc_time(struct rtc_time *tm)
{
- unsigned long nowtime;
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
+ 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
- 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;
+#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)
+{
+ /* 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, 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
+ return cuda_get_time();
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 @@ via_calibrate_decr(void)
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 @@ static struct pmu_sleep_notifier time_sleep_notifier = {
/*
* 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 @@ pmac_calibrate_decr(void)
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
}