aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powermac/time.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-22 02:02:39 -0400
committerPaul Mackerras <paulus@samba.org>2005-10-22 02:02:39 -0400
commit35499c0195e46f479cf6ac16ad8d3f394b5fcc10 (patch)
tree25660acd2425de5236a1eff7a25dc931e6f86492 /arch/powerpc/platforms/powermac/time.c
parentb6ba92819dc1304a4e5a0bf06b297c657b58168a (diff)
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>
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 a6d2d231d5a0..82982bf6453c 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -33,6 +33,7 @@
33#include <asm/machdep.h> 33#include <asm/machdep.h>
34#include <asm/time.h> 34#include <asm/time.h>
35#include <asm/nvram.h> 35#include <asm/nvram.h>
36#include <asm/smu.h>
36 37
37#undef DEBUG 38#undef DEBUG
38 39
@@ -68,8 +69,8 @@
68 69
69long __init pmac_time_init(void) 70long __init pmac_time_init(void)
70{ 71{
71#ifdef CONFIG_NVRAM
72 s32 delta = 0; 72 s32 delta = 0;
73#ifdef CONFIG_NVRAM
73 int dst; 74 int dst;
74 75
75 delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16; 76 delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
@@ -80,110 +81,181 @@ long __init pmac_time_init(void)
80 dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0); 81 dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
81 printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60, 82 printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
82 dst ? "on" : "off"); 83 dst ? "on" : "off");
83 return delta;
84#else
85 return 0;
86#endif 84#endif
85 return delta;
87} 86}
88 87
89unsigned long pmac_get_boot_time(void) 88static void to_rtc_time(unsigned long now, struct rtc_time *tm)
89{
90 to_tm(now, tm);
91 tm->tm_year -= 1900;
92 tm->tm_mon -= 1;
93}
94
95static unsigned long from_rtc_time(struct rtc_time *tm)
96{
97 return mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
98 tm->tm_hour, tm->tm_min, tm->tm_sec);
99}
100
101#ifdef CONFIG_ADB_CUDA
102static unsigned long cuda_get_time(void)
90{ 103{
91#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
92 struct adb_request req; 104 struct adb_request req;
93 unsigned long now; 105 unsigned long now;
94#endif
95 106
96 /* Get the time from the RTC */ 107 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
97 switch (sys_ctrler) { 108 return 0;
98#ifdef CONFIG_ADB_CUDA 109 while (!req.complete)
99 case SYS_CTRLER_CUDA: 110 cuda_poll();
100 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) 111 if (req.reply_len != 7)
101 return 0; 112 printk(KERN_ERR "cuda_get_time: got %d byte reply\n",
102 while (!req.complete) 113 req.reply_len);
103 cuda_poll(); 114 now = (req.reply[3] << 24) + (req.reply[4] << 16)
104 if (req.reply_len != 7) 115 + (req.reply[5] << 8) + req.reply[6];
105 printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", 116 if (now < RTC_OFFSET)
106 req.reply_len); 117 return 0;
107 now = (req.reply[3] << 24) + (req.reply[4] << 16) 118 return now - RTC_OFFSET;
108 + (req.reply[5] << 8) + req.reply[6]; 119}
109 return now - RTC_OFFSET; 120
110#endif /* CONFIG_ADB_CUDA */ 121#define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm))
111#ifdef CONFIG_ADB_PMU 122
112 case SYS_CTRLER_PMU: 123static int cuda_set_rtc_time(struct rtc_time *tm)
113 if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) 124{
114 return 0; 125 unsigned int nowtime;
115 while (!req.complete) 126 struct adb_request req;
116 pmu_poll(); 127
117 if (req.reply_len != 4) 128 nowtime = from_rtc_time(tm) + RTC_OFFSET;
118 printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", 129 if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
119 req.reply_len); 130 nowtime >> 24, nowtime >> 16, nowtime >> 8,
120 now = (req.reply[0] << 24) + (req.reply[1] << 16) 131 nowtime) < 0)
121 + (req.reply[2] << 8) + req.reply[3]; 132 return -ENXIO;
122 return now - RTC_OFFSET; 133 while (!req.complete)
123#endif /* CONFIG_ADB_PMU */ 134 cuda_poll();
124 default: ; 135 if ((req.reply_len != 3) && (req.reply_len != 7))
125 } 136 printk(KERN_ERR "cuda_set_rtc_time: got %d byte reply\n",
137 req.reply_len);
126 return 0; 138 return 0;
127} 139}
128 140
129void pmac_get_rtc_time(struct rtc_time *tm) 141#else
142#define cuda_get_time() 0
143#define cuda_get_rtc_time(tm)
144#define cuda_set_rtc_time(tm) 0
145#endif
146
147#ifdef CONFIG_ADB_PMU
148static unsigned long pmu_get_time(void)
130{ 149{
150 struct adb_request req;
131 unsigned long now; 151 unsigned long now;
132 152
133 now = pmac_get_boot_time(); 153 if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
134 to_tm(now, tm); 154 return 0;
135 tm->tm_year -= 1900; 155 pmu_wait_complete(&req);
136 tm->tm_mon -= 1; /* month is 0-based */ 156 if (req.reply_len != 4)
157 printk(KERN_ERR "pmu_get_time: got %d byte reply from PMU\n",
158 req.reply_len);
159 now = (req.reply[0] << 24) + (req.reply[1] << 16)
160 + (req.reply[2] << 8) + req.reply[3];
161 if (now < RTC_OFFSET)
162 return 0;
163 return now - RTC_OFFSET;
137} 164}
138 165
139int pmac_set_rtc_time(struct rtc_time *tm) 166#define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm))
167
168static int pmu_set_rtc_time(struct rtc_time *tm)
140{ 169{
141 unsigned long nowtime; 170 unsigned int nowtime;
142#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
143 struct adb_request req; 171 struct adb_request req;
172
173 nowtime = from_rtc_time(tm) + RTC_OFFSET;
174 if (pmu_request(&req, NULL, 5, PMU_SET_RTC, nowtime >> 24,
175 nowtime >> 16, nowtime >> 8, nowtime) < 0)
176 return -ENXIO;
177 pmu_wait_complete(&req);
178 if (req.reply_len != 0)
179 printk(KERN_ERR "pmu_set_rtc_time: %d byte reply from PMU\n",
180 req.reply_len);
181 return 0;
182}
183
184#else
185#define pmu_get_time() 0
186#define pmu_get_rtc_time(tm)
187#define pmu_set_rtc_time(tm) 0
144#endif 188#endif
145 189
146 nowtime = mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, 190#ifdef CONFIG_PMAC_SMU
147 tm->tm_hour, tm->tm_min, tm->tm_sec); 191static unsigned long smu_get_time(void)
148 nowtime += RTC_OFFSET; 192{
193 struct rtc_time tm;
194
195 if (smu_get_rtc_time(&tm, 1))
196 return 0;
197 return from_rtc_time(&tm);
198}
199
200#else
201#define smu_get_time() 0
202#define smu_get_rtc_time(tm, spin)
203#define smu_set_rtc_time(tm, spin) 0
204#endif
149 205
206unsigned long pmac_get_boot_time(void)
207{
208 /* Get the time from the RTC, used only at boot time */
150 switch (sys_ctrler) { 209 switch (sys_ctrler) {
151#ifdef CONFIG_ADB_CUDA
152 case SYS_CTRLER_CUDA: 210 case SYS_CTRLER_CUDA:
153 if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, 211 return cuda_get_time();
154 nowtime >> 24, nowtime >> 16, nowtime >> 8,
155 nowtime) < 0)
156 return 0;
157 while (!req.complete)
158 cuda_poll();
159 if ((req.reply_len != 3) && (req.reply_len != 7))
160 printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
161 req.reply_len);
162 return 1;
163#endif /* CONFIG_ADB_CUDA */
164#ifdef CONFIG_ADB_PMU
165 case SYS_CTRLER_PMU: 212 case SYS_CTRLER_PMU:
166 if (pmu_request(&req, NULL, 5, PMU_SET_RTC, 213 return pmu_get_time();
167 nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) 214 case SYS_CTRLER_SMU:
168 return 0; 215 return smu_get_time();
169 while (!req.complete)
170 pmu_poll();
171 if (req.reply_len != 0)
172 printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
173 req.reply_len);
174 return 1;
175#endif /* CONFIG_ADB_PMU */
176 default: 216 default:
177 return 0; 217 return 0;
178 } 218 }
179} 219}
180 220
221void pmac_get_rtc_time(struct rtc_time *tm)
222{
223 /* Get the time from the RTC, used only at boot time */
224 switch (sys_ctrler) {
225 case SYS_CTRLER_CUDA:
226 cuda_get_rtc_time(tm);
227 break;
228 case SYS_CTRLER_PMU:
229 pmu_get_rtc_time(tm);
230 break;
231 case SYS_CTRLER_SMU:
232 smu_get_rtc_time(tm, 1);
233 break;
234 default:
235 ;
236 }
237}
238
239int pmac_set_rtc_time(struct rtc_time *tm)
240{
241 switch (sys_ctrler) {
242 case SYS_CTRLER_CUDA:
243 return cuda_set_rtc_time(tm);
244 case SYS_CTRLER_PMU:
245 return pmu_set_rtc_time(tm);
246 case SYS_CTRLER_SMU:
247 return smu_set_rtc_time(tm, 1);
248 default:
249 return -ENODEV;
250 }
251}
252
253#ifdef CONFIG_PPC32
181/* 254/*
182 * Calibrate the decrementer register using VIA timer 1. 255 * Calibrate the decrementer register using VIA timer 1.
183 * This is used both on powermacs and CHRP machines. 256 * This is used both on powermacs and CHRP machines.
184 */ 257 */
185int __init 258int __init via_calibrate_decr(void)
186via_calibrate_decr(void)
187{ 259{
188 struct device_node *vias; 260 struct device_node *vias;
189 volatile unsigned char __iomem *via; 261 volatile unsigned char __iomem *via;
@@ -217,15 +289,12 @@ via_calibrate_decr(void)
217 dend = get_dec(); 289 dend = get_dec();
218 290
219 ppc_tb_freq = (dstart - dend) * 100 / 6; 291 ppc_tb_freq = (dstart - dend) * 100 / 6;
220 tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100);
221
222 printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %lu (%u ticks)\n",
223 tb_ticks_per_jiffy, dstart - dend);
224 292
225 iounmap(via); 293 iounmap(via);
226 294
227 return 1; 295 return 1;
228} 296}
297#endif
229 298
230#ifdef CONFIG_PM 299#ifdef CONFIG_PM
231/* 300/*
@@ -262,19 +331,17 @@ static struct pmu_sleep_notifier time_sleep_notifier = {
262 331
263/* 332/*
264 * Query the OF and get the decr frequency. 333 * Query the OF and get the decr frequency.
265 * This was taken from the pmac time_init() when merging the prep/pmac
266 * time functions.
267 */ 334 */
268void __init 335void __init pmac_calibrate_decr(void)
269pmac_calibrate_decr(void)
270{ 336{
271 struct device_node *cpu;
272 unsigned int freq, *fp;
273
274#ifdef CONFIG_PM 337#ifdef CONFIG_PM
338 /* XXX why here? */
275 pmu_register_sleep_notifier(&time_sleep_notifier); 339 pmu_register_sleep_notifier(&time_sleep_notifier);
276#endif /* CONFIG_PM */ 340#endif /* CONFIG_PM */
277 341
342 generic_calibrate_decr();
343
344#ifdef CONFIG_PPC32
278 /* We assume MacRISC2 machines have correct device-tree 345 /* We assume MacRISC2 machines have correct device-tree
279 * calibration. That's better since the VIA itself seems 346 * calibration. That's better since the VIA itself seems
280 * to be slightly off. --BenH 347 * to be slightly off. --BenH
@@ -293,18 +360,5 @@ pmac_calibrate_decr(void)
293 if (machine_is_compatible("PowerMac3,5")) 360 if (machine_is_compatible("PowerMac3,5"))
294 if (via_calibrate_decr()) 361 if (via_calibrate_decr())
295 return; 362 return;
296 /* 363#endif
297 * The cpu node should have a timebase-frequency property
298 * to tell us the rate at which the decrementer counts.
299 */
300 cpu = find_type_devices("cpu");
301 if (cpu == 0)
302 panic("can't find cpu node in time_init");
303 fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);
304 if (fp == 0)
305 panic("can't get cpu timebase frequency");
306 freq = *fp;
307 printk("time_init: decrementer frequency = %u.%.6u MHz\n",
308 freq/1000000, freq%1000000);
309 ppc_tb_freq = freq;
310} 364}