xref: /openbmc/linux/arch/m68k/mac/misc.c (revision 239480ab)
1 /*
2  * Miscellaneous Mac68K-specific stuff
3  */
4 
5 #include <linux/types.h>
6 #include <linux/errno.h>
7 #include <linux/kernel.h>
8 #include <linux/delay.h>
9 #include <linux/sched.h>
10 #include <linux/time.h>
11 #include <linux/rtc.h>
12 #include <linux/mm.h>
13 
14 #include <linux/adb.h>
15 #include <linux/cuda.h>
16 #include <linux/pmu.h>
17 
18 #include <linux/uaccess.h>
19 #include <asm/io.h>
20 #include <asm/segment.h>
21 #include <asm/setup.h>
22 #include <asm/macintosh.h>
23 #include <asm/mac_via.h>
24 #include <asm/mac_oss.h>
25 
26 #include <asm/machdep.h>
27 
28 /* Offset between Unix time (1970-based) and Mac time (1904-based) */
29 
30 #define RTC_OFFSET 2082844800
31 
32 static void (*rom_reset)(void);
33 
34 #ifdef CONFIG_ADB_CUDA
35 static long cuda_read_time(void)
36 {
37 	struct adb_request req;
38 	long time;
39 
40 	if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
41 		return 0;
42 	while (!req.complete)
43 		cuda_poll();
44 
45 	time = (req.reply[3] << 24) | (req.reply[4] << 16)
46 		| (req.reply[5] << 8) | req.reply[6];
47 	return time - RTC_OFFSET;
48 }
49 
50 static void cuda_write_time(long data)
51 {
52 	struct adb_request req;
53 	data += RTC_OFFSET;
54 	if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
55 			(data >> 24) & 0xFF, (data >> 16) & 0xFF,
56 			(data >> 8) & 0xFF, data & 0xFF) < 0)
57 		return;
58 	while (!req.complete)
59 		cuda_poll();
60 }
61 
62 static __u8 cuda_read_pram(int offset)
63 {
64 	struct adb_request req;
65 	if (cuda_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM,
66 			(offset >> 8) & 0xFF, offset & 0xFF) < 0)
67 		return 0;
68 	while (!req.complete)
69 		cuda_poll();
70 	return req.reply[3];
71 }
72 
73 static void cuda_write_pram(int offset, __u8 data)
74 {
75 	struct adb_request req;
76 	if (cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM,
77 			(offset >> 8) & 0xFF, offset & 0xFF, data) < 0)
78 		return;
79 	while (!req.complete)
80 		cuda_poll();
81 }
82 #else
83 #define cuda_read_time() 0
84 #define cuda_write_time(n)
85 #define cuda_read_pram NULL
86 #define cuda_write_pram NULL
87 #endif
88 
89 #ifdef CONFIG_ADB_PMU68K
90 static long pmu_read_time(void)
91 {
92 	struct adb_request req;
93 	long time;
94 
95 	if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
96 		return 0;
97 	while (!req.complete)
98 		pmu_poll();
99 
100 	time = (req.reply[1] << 24) | (req.reply[2] << 16)
101 		| (req.reply[3] << 8) | req.reply[4];
102 	return time - RTC_OFFSET;
103 }
104 
105 static void pmu_write_time(long data)
106 {
107 	struct adb_request req;
108 	data += RTC_OFFSET;
109 	if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
110 			(data >> 24) & 0xFF, (data >> 16) & 0xFF,
111 			(data >> 8) & 0xFF, data & 0xFF) < 0)
112 		return;
113 	while (!req.complete)
114 		pmu_poll();
115 }
116 
117 static __u8 pmu_read_pram(int offset)
118 {
119 	struct adb_request req;
120 	if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
121 			(offset >> 8) & 0xFF, offset & 0xFF) < 0)
122 		return 0;
123 	while (!req.complete)
124 		pmu_poll();
125 	return req.reply[3];
126 }
127 
128 static void pmu_write_pram(int offset, __u8 data)
129 {
130 	struct adb_request req;
131 	if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
132 			(offset >> 8) & 0xFF, offset & 0xFF, data) < 0)
133 		return;
134 	while (!req.complete)
135 		pmu_poll();
136 }
137 #else
138 #define pmu_read_time() 0
139 #define pmu_write_time(n)
140 #define pmu_read_pram NULL
141 #define pmu_write_pram NULL
142 #endif
143 
144 /*
145  * VIA PRAM/RTC access routines
146  *
147  * Must be called with interrupts disabled and
148  * the RTC should be enabled.
149  */
150 
151 static __u8 via_pram_readbyte(void)
152 {
153 	int	i,reg;
154 	__u8	data;
155 
156 	reg = via1[vBufB] & ~VIA1B_vRTCClk;
157 
158 	/* Set the RTC data line to be an input. */
159 
160 	via1[vDirB] &= ~VIA1B_vRTCData;
161 
162 	/* The bits of the byte come out in MSB order */
163 
164 	data = 0;
165 	for (i = 0 ; i < 8 ; i++) {
166 		via1[vBufB] = reg;
167 		via1[vBufB] = reg | VIA1B_vRTCClk;
168 		data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData);
169 	}
170 
171 	/* Return RTC data line to output state */
172 
173 	via1[vDirB] |= VIA1B_vRTCData;
174 
175 	return data;
176 }
177 
178 static void via_pram_writebyte(__u8 data)
179 {
180 	int	i,reg,bit;
181 
182 	reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData);
183 
184 	/* The bits of the byte go in in MSB order */
185 
186 	for (i = 0 ; i < 8 ; i++) {
187 		bit = data & 0x80? 1 : 0;
188 		data <<= 1;
189 		via1[vBufB] = reg | bit;
190 		via1[vBufB] = reg | bit | VIA1B_vRTCClk;
191 	}
192 }
193 
194 /*
195  * Execute a VIA PRAM/RTC command. For read commands
196  * data should point to a one-byte buffer for the
197  * resulting data. For write commands it should point
198  * to the data byte to for the command.
199  *
200  * This function disables all interrupts while running.
201  */
202 
203 static void via_pram_command(int command, __u8 *data)
204 {
205 	unsigned long flags;
206 	int	is_read;
207 
208 	local_irq_save(flags);
209 
210 	/* Enable the RTC and make sure the strobe line is high */
211 
212 	via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb;
213 
214 	if (command & 0xFF00) {		/* extended (two-byte) command */
215 		via_pram_writebyte((command & 0xFF00) >> 8);
216 		via_pram_writebyte(command & 0xFF);
217 		is_read = command & 0x8000;
218 	} else {			/* one-byte command */
219 		via_pram_writebyte(command);
220 		is_read = command & 0x80;
221 	}
222 	if (is_read) {
223 		*data = via_pram_readbyte();
224 	} else {
225 		via_pram_writebyte(*data);
226 	}
227 
228 	/* All done, disable the RTC */
229 
230 	via1[vBufB] |= VIA1B_vRTCEnb;
231 
232 	local_irq_restore(flags);
233 }
234 
235 static __u8 via_read_pram(int offset)
236 {
237 	return 0;
238 }
239 
240 static void via_write_pram(int offset, __u8 data)
241 {
242 }
243 
244 /*
245  * Return the current time in seconds since January 1, 1904.
246  *
247  * This only works on machines with the VIA-based PRAM/RTC, which
248  * is basically any machine with Mac II-style ADB.
249  */
250 
251 static long via_read_time(void)
252 {
253 	union {
254 		__u8 cdata[4];
255 		long idata;
256 	} result, last_result;
257 	int count = 1;
258 
259 	via_pram_command(0x81, &last_result.cdata[3]);
260 	via_pram_command(0x85, &last_result.cdata[2]);
261 	via_pram_command(0x89, &last_result.cdata[1]);
262 	via_pram_command(0x8D, &last_result.cdata[0]);
263 
264 	/*
265 	 * The NetBSD guys say to loop until you get the same reading
266 	 * twice in a row.
267 	 */
268 
269 	while (1) {
270 		via_pram_command(0x81, &result.cdata[3]);
271 		via_pram_command(0x85, &result.cdata[2]);
272 		via_pram_command(0x89, &result.cdata[1]);
273 		via_pram_command(0x8D, &result.cdata[0]);
274 
275 		if (result.idata == last_result.idata)
276 			return result.idata - RTC_OFFSET;
277 
278 		if (++count > 10)
279 			break;
280 
281 		last_result.idata = result.idata;
282 	}
283 
284 	pr_err("via_read_time: failed to read a stable value; got 0x%08lx then 0x%08lx\n",
285 	       last_result.idata, result.idata);
286 
287 	return 0;
288 }
289 
290 /*
291  * Set the current time to a number of seconds since January 1, 1904.
292  *
293  * This only works on machines with the VIA-based PRAM/RTC, which
294  * is basically any machine with Mac II-style ADB.
295  */
296 
297 static void via_write_time(long time)
298 {
299 	union {
300 		__u8  cdata[4];
301 		long  idata;
302 	} data;
303 	__u8	temp;
304 
305 	/* Clear the write protect bit */
306 
307 	temp = 0x55;
308 	via_pram_command(0x35, &temp);
309 
310 	data.idata = time + RTC_OFFSET;
311 	via_pram_command(0x01, &data.cdata[3]);
312 	via_pram_command(0x05, &data.cdata[2]);
313 	via_pram_command(0x09, &data.cdata[1]);
314 	via_pram_command(0x0D, &data.cdata[0]);
315 
316 	/* Set the write protect bit */
317 
318 	temp = 0xD5;
319 	via_pram_command(0x35, &temp);
320 }
321 
322 static void via_shutdown(void)
323 {
324 	if (rbv_present) {
325 		via2[rBufB] &= ~0x04;
326 	} else {
327 		/* Direction of vDirB is output */
328 		via2[vDirB] |= 0x04;
329 		/* Send a value of 0 on that line */
330 		via2[vBufB] &= ~0x04;
331 		mdelay(1000);
332 	}
333 }
334 
335 /*
336  * FIXME: not sure how this is supposed to work exactly...
337  */
338 
339 static void oss_shutdown(void)
340 {
341 	oss->rom_ctrl = OSS_POWEROFF;
342 }
343 
344 #ifdef CONFIG_ADB_CUDA
345 
346 static void cuda_restart(void)
347 {
348 	struct adb_request req;
349 	if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM) < 0)
350 		return;
351 	while (!req.complete)
352 		cuda_poll();
353 }
354 
355 static void cuda_shutdown(void)
356 {
357 	struct adb_request req;
358 	if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN) < 0)
359 		return;
360 	while (!req.complete)
361 		cuda_poll();
362 }
363 
364 #endif /* CONFIG_ADB_CUDA */
365 
366 #ifdef CONFIG_ADB_PMU68K
367 
368 void pmu_restart(void)
369 {
370 	struct adb_request req;
371 	if (pmu_request(&req, NULL,
372 			2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0)
373 		return;
374 	while (!req.complete)
375 		pmu_poll();
376 	if (pmu_request(&req, NULL, 1, PMU_RESET) < 0)
377 		return;
378 	while (!req.complete)
379 		pmu_poll();
380 }
381 
382 void pmu_shutdown(void)
383 {
384 	struct adb_request req;
385 	if (pmu_request(&req, NULL,
386 			2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0)
387 		return;
388 	while (!req.complete)
389 		pmu_poll();
390 	if (pmu_request(&req, NULL, 5, PMU_SHUTDOWN, 'M', 'A', 'T', 'T') < 0)
391 		return;
392 	while (!req.complete)
393 		pmu_poll();
394 }
395 
396 #endif
397 
398 /*
399  *-------------------------------------------------------------------
400  * Below this point are the generic routines; they'll dispatch to the
401  * correct routine for the hardware on which we're running.
402  *-------------------------------------------------------------------
403  */
404 
405 void mac_pram_read(int offset, __u8 *buffer, int len)
406 {
407 	__u8 (*func)(int);
408 	int i;
409 
410 	switch(macintosh_config->adb_type) {
411 	case MAC_ADB_PB1:
412 	case MAC_ADB_PB2:
413 		func = pmu_read_pram; break;
414 	case MAC_ADB_EGRET:
415 	case MAC_ADB_CUDA:
416 		func = cuda_read_pram; break;
417 	default:
418 		func = via_read_pram;
419 	}
420 	if (!func)
421 		return;
422 	for (i = 0 ; i < len ; i++) {
423 		buffer[i] = (*func)(offset++);
424 	}
425 }
426 
427 void mac_pram_write(int offset, __u8 *buffer, int len)
428 {
429 	void (*func)(int, __u8);
430 	int i;
431 
432 	switch(macintosh_config->adb_type) {
433 	case MAC_ADB_PB1:
434 	case MAC_ADB_PB2:
435 		func = pmu_write_pram; break;
436 	case MAC_ADB_EGRET:
437 	case MAC_ADB_CUDA:
438 		func = cuda_write_pram; break;
439 	default:
440 		func = via_write_pram;
441 	}
442 	if (!func)
443 		return;
444 	for (i = 0 ; i < len ; i++) {
445 		(*func)(offset++, buffer[i]);
446 	}
447 }
448 
449 void mac_poweroff(void)
450 {
451 	if (oss_present) {
452 		oss_shutdown();
453 	} else if (macintosh_config->adb_type == MAC_ADB_II) {
454 		via_shutdown();
455 #ifdef CONFIG_ADB_CUDA
456 	} else if (macintosh_config->adb_type == MAC_ADB_EGRET ||
457 	           macintosh_config->adb_type == MAC_ADB_CUDA) {
458 		cuda_shutdown();
459 #endif
460 #ifdef CONFIG_ADB_PMU68K
461 	} else if (macintosh_config->adb_type == MAC_ADB_PB1
462 		|| macintosh_config->adb_type == MAC_ADB_PB2) {
463 		pmu_shutdown();
464 #endif
465 	}
466 	local_irq_enable();
467 	pr_crit("It is now safe to turn off your Macintosh.\n");
468 	while(1);
469 }
470 
471 void mac_reset(void)
472 {
473 	if (macintosh_config->adb_type == MAC_ADB_II) {
474 		unsigned long flags;
475 
476 		/* need ROMBASE in booter */
477 		/* indeed, plus need to MAP THE ROM !! */
478 
479 		if (mac_bi_data.rombase == 0)
480 			mac_bi_data.rombase = 0x40800000;
481 
482 		/* works on some */
483 		rom_reset = (void *) (mac_bi_data.rombase + 0xa);
484 
485 		if (macintosh_config->ident == MAC_MODEL_SE30) {
486 			/*
487 			 * MSch: Machines known to crash on ROM reset ...
488 			 */
489 		} else {
490 			local_irq_save(flags);
491 
492 			rom_reset();
493 
494 			local_irq_restore(flags);
495 		}
496 #ifdef CONFIG_ADB_CUDA
497 	} else if (macintosh_config->adb_type == MAC_ADB_EGRET ||
498 	           macintosh_config->adb_type == MAC_ADB_CUDA) {
499 		cuda_restart();
500 #endif
501 #ifdef CONFIG_ADB_PMU68K
502 	} else if (macintosh_config->adb_type == MAC_ADB_PB1
503 		|| macintosh_config->adb_type == MAC_ADB_PB2) {
504 		pmu_restart();
505 #endif
506 	} else if (CPU_IS_030) {
507 
508 		/* 030-specific reset routine.  The idea is general, but the
509 		 * specific registers to reset are '030-specific.  Until I
510 		 * have a non-030 machine, I can't test anything else.
511 		 *  -- C. Scott Ananian <cananian@alumni.princeton.edu>
512 		 */
513 
514 		unsigned long rombase = 0x40000000;
515 
516 		/* make a 1-to-1 mapping, using the transparent tran. reg. */
517 		unsigned long virt = (unsigned long) mac_reset;
518 		unsigned long phys = virt_to_phys(mac_reset);
519 		unsigned long addr = (phys&0xFF000000)|0x8777;
520 		unsigned long offset = phys-virt;
521 		local_irq_disable(); /* lets not screw this up, ok? */
522 		__asm__ __volatile__(".chip 68030\n\t"
523 				     "pmove %0,%/tt0\n\t"
524 				     ".chip 68k"
525 				     : : "m" (addr));
526 		/* Now jump to physical address so we can disable MMU */
527 		__asm__ __volatile__(
528                     ".chip 68030\n\t"
529 		    "lea %/pc@(1f),%/a0\n\t"
530 		    "addl %0,%/a0\n\t"/* fixup target address and stack ptr */
531 		    "addl %0,%/sp\n\t"
532 		    "pflusha\n\t"
533 		    "jmp %/a0@\n\t" /* jump into physical memory */
534 		    "0:.long 0\n\t" /* a constant zero. */
535 		    /* OK.  Now reset everything and jump to reset vector. */
536 		    "1:\n\t"
537 		    "lea %/pc@(0b),%/a0\n\t"
538 		    "pmove %/a0@, %/tc\n\t" /* disable mmu */
539 		    "pmove %/a0@, %/tt0\n\t" /* disable tt0 */
540 		    "pmove %/a0@, %/tt1\n\t" /* disable tt1 */
541 		    "movel #0, %/a0\n\t"
542 		    "movec %/a0, %/vbr\n\t" /* clear vector base register */
543 		    "movec %/a0, %/cacr\n\t" /* disable caches */
544 		    "movel #0x0808,%/a0\n\t"
545 		    "movec %/a0, %/cacr\n\t" /* flush i&d caches */
546 		    "movew #0x2700,%/sr\n\t" /* set up status register */
547 		    "movel %1@(0x0),%/a0\n\t"/* load interrupt stack pointer */
548 		    "movec %/a0, %/isp\n\t"
549 		    "movel %1@(0x4),%/a0\n\t" /* load reset vector */
550 		    "reset\n\t" /* reset external devices */
551 		    "jmp %/a0@\n\t" /* jump to the reset vector */
552 		    ".chip 68k"
553 		    : : "r" (offset), "a" (rombase) : "a0");
554 	}
555 
556 	/* should never get here */
557 	local_irq_enable();
558 	pr_crit("Restart failed. Please restart manually.\n");
559 	while(1);
560 }
561 
562 /*
563  * This function translates seconds since 1970 into a proper date.
564  *
565  * Algorithm cribbed from glibc2.1, __offtime().
566  */
567 #define SECS_PER_MINUTE (60)
568 #define SECS_PER_HOUR  (SECS_PER_MINUTE * 60)
569 #define SECS_PER_DAY   (SECS_PER_HOUR * 24)
570 
571 static void unmktime(unsigned long time, long offset,
572 		     int *yearp, int *monp, int *dayp,
573 		     int *hourp, int *minp, int *secp)
574 {
575         /* How many days come before each month (0-12).  */
576 	static const unsigned short int __mon_yday[2][13] =
577 	{
578 		/* Normal years.  */
579 		{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
580 		/* Leap years.  */
581 		{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
582 	};
583 	long int days, rem, y, wday, yday;
584 	const unsigned short int *ip;
585 
586 	days = time / SECS_PER_DAY;
587 	rem = time % SECS_PER_DAY;
588 	rem += offset;
589 	while (rem < 0) {
590 		rem += SECS_PER_DAY;
591 		--days;
592 	}
593 	while (rem >= SECS_PER_DAY) {
594 		rem -= SECS_PER_DAY;
595 		++days;
596 	}
597 	*hourp = rem / SECS_PER_HOUR;
598 	rem %= SECS_PER_HOUR;
599 	*minp = rem / SECS_PER_MINUTE;
600 	*secp = rem % SECS_PER_MINUTE;
601 	/* January 1, 1970 was a Thursday. */
602 	wday = (4 + days) % 7; /* Day in the week. Not currently used */
603 	if (wday < 0) wday += 7;
604 	y = 1970;
605 
606 #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
607 #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
608 #define __isleap(year)	\
609   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
610 
611 	while (days < 0 || days >= (__isleap (y) ? 366 : 365))
612 	{
613 		/* Guess a corrected year, assuming 365 days per year.  */
614 		long int yg = y + days / 365 - (days % 365 < 0);
615 
616 		/* Adjust DAYS and Y to match the guessed year.  */
617 		days -= ((yg - y) * 365
618 			 + LEAPS_THRU_END_OF (yg - 1)
619 			 - LEAPS_THRU_END_OF (y - 1));
620 		y = yg;
621 	}
622 	*yearp = y - 1900;
623 	yday = days; /* day in the year.  Not currently used. */
624 	ip = __mon_yday[__isleap(y)];
625 	for (y = 11; days < (long int) ip[y]; --y)
626 		continue;
627 	days -= ip[y];
628 	*monp = y;
629 	*dayp = days + 1; /* day in the month */
630 	return;
631 }
632 
633 /*
634  * Read/write the hardware clock.
635  */
636 
637 int mac_hwclk(int op, struct rtc_time *t)
638 {
639 	unsigned long now;
640 
641 	if (!op) { /* read */
642 		switch (macintosh_config->adb_type) {
643 		case MAC_ADB_II:
644 		case MAC_ADB_IOP:
645 			now = via_read_time();
646 			break;
647 		case MAC_ADB_PB1:
648 		case MAC_ADB_PB2:
649 			now = pmu_read_time();
650 			break;
651 		case MAC_ADB_EGRET:
652 		case MAC_ADB_CUDA:
653 			now = cuda_read_time();
654 			break;
655 		default:
656 			now = 0;
657 		}
658 
659 		t->tm_wday = 0;
660 		unmktime(now, 0,
661 			 &t->tm_year, &t->tm_mon, &t->tm_mday,
662 			 &t->tm_hour, &t->tm_min, &t->tm_sec);
663 		pr_debug("%s: read %04d-%02d-%-2d %02d:%02d:%02d\n",
664 		         __func__, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
665 		         t->tm_hour, t->tm_min, t->tm_sec);
666 	} else { /* write */
667 		pr_debug("%s: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n",
668 		         __func__, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
669 		         t->tm_hour, t->tm_min, t->tm_sec);
670 
671 		now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
672 			     t->tm_hour, t->tm_min, t->tm_sec);
673 
674 		switch (macintosh_config->adb_type) {
675 		case MAC_ADB_II:
676 		case MAC_ADB_IOP:
677 			via_write_time(now);
678 			break;
679 		case MAC_ADB_EGRET:
680 		case MAC_ADB_CUDA:
681 			cuda_write_time(now);
682 			break;
683 		case MAC_ADB_PB1:
684 		case MAC_ADB_PB2:
685 			pmu_write_time(now);
686 			break;
687 		}
688 	}
689 	return 0;
690 }
691 
692 /*
693  * Set minutes/seconds in the hardware clock
694  */
695 
696 int mac_set_clock_mmss (unsigned long nowtime)
697 {
698 	struct rtc_time now;
699 
700 	mac_hwclk(0, &now);
701 	now.tm_sec = nowtime % 60;
702 	now.tm_min = (nowtime / 60) % 60;
703 	mac_hwclk(1, &now);
704 
705 	return 0;
706 }
707