1
2
3
4
5
6
7
8
9
10#include <linux/config.h>
11#include <linux/errno.h>
12#include <linux/sched.h>
13#include <linux/kernel.h>
14#include <linux/param.h>
15#include <linux/string.h>
16#include <linux/mm.h>
17#include <linux/init.h>
18#include <linux/time.h>
19#include <linux/adb.h>
20#include <linux/pmu.h>
21
22#include <asm/sections.h>
23#include <asm/prom.h>
24#include <asm/system.h>
25#include <asm/io.h>
26#include <asm/pgtable.h>
27#include <asm/machdep.h>
28#include <asm/hardirq.h>
29#include <asm/time.h>
30#include <asm/nvram.h>
31
32#undef DEBUG
33
34#ifdef DEBUG
35#define DBG(x...) printk(x)
36#else
37#define DBG(x...)
38#endif
39
40extern void setup_default_decr(void);
41
42extern unsigned long ppc_tb_freq;
43extern unsigned long ppc_proc_freq;
44
45
46#define RTC_OFFSET 2082844800
47
48
49
50
51#define VIA_TIMER_FREQ_6 4700000
52
53extern struct timezone sys_tz;
54extern void to_tm(int tim, struct rtc_time * tm);
55
56void __pmac pmac_get_rtc_time(struct rtc_time *tm)
57{
58 struct adb_request req;
59 unsigned int now;
60
61
62 if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
63 return;
64 while (!req.complete)
65 pmu_poll();
66 if (req.reply_len != 4)
67 printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
68 req.reply_len);
69 now = (req.reply[0] << 24) + (req.reply[1] << 16)
70 + (req.reply[2] << 8) + req.reply[3];
71 DBG("get: %u -> %u\n", (int)now, (int)(now - RTC_OFFSET));
72 now -= RTC_OFFSET;
73
74 to_tm(now, tm);
75 tm->tm_year -= 1900;
76 tm->tm_mon -= 1;
77
78 DBG("-> tm_mday: %d, tm_mon: %d, tm_year: %d, %d:%02d:%02d\n",
79 tm->tm_mday, tm->tm_mon, tm->tm_year,
80 tm->tm_hour, tm->tm_min, tm->tm_sec);
81}
82
83int __pmac pmac_set_rtc_time(struct rtc_time *tm)
84{
85 struct adb_request req;
86 unsigned int nowtime;
87
88 DBG("set: tm_mday: %d, tm_mon: %d, tm_year: %d, %d:%02d:%02d\n",
89 tm->tm_mday, tm->tm_mon, tm->tm_year,
90 tm->tm_hour, tm->tm_min, tm->tm_sec);
91
92 nowtime = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
93 tm->tm_hour, tm->tm_min, tm->tm_sec);
94 DBG("-> %u -> %u\n", (int)nowtime, (int)(nowtime + RTC_OFFSET));
95 nowtime += RTC_OFFSET;
96
97 if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
98 nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
99 return 0;
100 while (!req.complete)
101 pmu_poll();
102 if (req.reply_len != 0)
103 printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
104 req.reply_len);
105 return 1;
106}
107
108void __init pmac_get_boot_time(struct rtc_time *tm)
109{
110 pmac_get_rtc_time(tm);
111
112#ifdef disabled__CONFIG_NVRAM
113 s32 delta = 0;
114 int dst;
115
116 delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
117 delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
118 delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
119 if (delta & 0x00800000UL)
120 delta |= 0xFF000000UL;
121 dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
122 printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
123 dst ? "on" : "off");
124#endif
125}
126
127
128
129
130
131
132void __init pmac_calibrate_decr(void)
133{
134 struct device_node *cpu;
135 unsigned int freq, *fp;
136 struct div_result divres;
137
138
139
140
141
142 cpu = find_type_devices("cpu");
143 if (cpu == 0)
144 panic("can't find cpu node in time_init");
145 fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);
146 if (fp == 0)
147 panic("can't get cpu timebase frequency");
148 freq = *fp;
149 printk("time_init: decrementer frequency = %u.%.6u MHz\n",
150 freq/1000000, freq%1000000);
151 tb_ticks_per_jiffy = freq / HZ;
152 tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
153 tb_ticks_per_usec = freq / 1000000;
154 tb_to_us = mulhwu_scale_factor(freq, 1000000);
155 div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres );
156 tb_to_xs = divres.result_low;
157 ppc_tb_freq = freq;
158
159 fp = (unsigned int *)get_property(cpu, "clock-frequency", NULL);
160 if (fp == 0)
161 panic("can't get cpu processor frequency");
162 ppc_proc_freq = *fp;
163
164 setup_default_decr();
165}
166
167