File: /usr/src/linux/arch/ppc/kernel/apus_setup.c
1 /*
2 * BK Id: SCCS/s.apus_setup.c 1.20 09/08/01 15:47:42 paulus
3 */
4 /*
5 * linux/arch/ppc/kernel/apus_setup.c
6 *
7 * Copyright (C) 1998, 1999 Jesper Skov
8 *
9 * Basically what is needed to replace functionality found in
10 * arch/m68k allowing Amiga drivers to work under APUS.
11 * Bits of code and/or ideas from arch/m68k and arch/ppc files.
12 *
13 * TODO:
14 * This file needs a *really* good cleanup. Restructure and optimize.
15 * Make sure it can be compiled for non-APUS configs. Begin to move
16 * Amiga specific stuff into mach/amiga.
17 */
18
19 #include <linux/config.h>
20 #include <linux/types.h>
21 #include <linux/kernel.h>
22 #include <linux/sched.h>
23 #include <linux/kd.h>
24 #include <linux/init.h>
25 #include <linux/hdreg.h>
26 #include <linux/blk.h>
27 #include <linux/pci.h>
28
29 #ifdef CONFIG_APUS
30 #include <asm/logging.h>
31 #endif
32
33 /* Needs INITSERIAL call in head.S! */
34 #undef APUS_DEBUG
35
36
37 #include <linux/ide.h>
38 #define T_CHAR (0x0000) /* char: don't touch */
39 #define T_SHORT (0x4000) /* short: 12 -> 21 */
40 #define T_INT (0x8000) /* int: 1234 -> 4321 */
41 #define T_TEXT (0xc000) /* text: 12 -> 21 */
42
43 #define T_MASK_TYPE (0xc000)
44 #define T_MASK_COUNT (0x3fff)
45
46 #define D_CHAR(cnt) (T_CHAR | (cnt))
47 #define D_SHORT(cnt) (T_SHORT | (cnt))
48 #define D_INT(cnt) (T_INT | (cnt))
49 #define D_TEXT(cnt) (T_TEXT | (cnt))
50
51 static u_short driveid_types[] = {
52 D_SHORT(10), /* config - vendor2 */
53 D_TEXT(20), /* serial_no */
54 D_SHORT(3), /* buf_type, buf_size - ecc_bytes */
55 D_TEXT(48), /* fw_rev - model */
56 D_CHAR(2), /* max_multsect - vendor3 */
57 D_SHORT(1), /* dword_io */
58 D_CHAR(2), /* vendor4 - capability */
59 D_SHORT(1), /* reserved50 */
60 D_CHAR(4), /* vendor5 - tDMA */
61 D_SHORT(4), /* field_valid - cur_sectors */
62 D_INT(1), /* cur_capacity */
63 D_CHAR(2), /* multsect - multsect_valid */
64 D_INT(1), /* lba_capacity */
65 D_SHORT(194) /* dma_1word - reservedyy */
66 };
67
68 #define num_driveid_types (sizeof(driveid_types)/sizeof(*driveid_types))
69
70 #include <asm/bootinfo.h>
71 #include <asm/setup.h>
72 #include <asm/amigahw.h>
73 #include <asm/amigaints.h>
74 #include <asm/amigappc.h>
75 #include <asm/pgtable.h>
76 #include <asm/io.h>
77 #include <asm/dma.h>
78 #include <asm/machdep.h>
79
80 #include "local_irq.h"
81
82 unsigned long m68k_machtype;
83 char debug_device[6] = "";
84
85 extern void amiga_init_IRQ(void);
86
87 void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
88 /* machine dependent keyboard functions */
89 int (*mach_keyb_init) (void) __initdata = NULL;
90 int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
91 void (*mach_kbd_leds) (unsigned int) = NULL;
92 /* machine dependent irq functions */
93 void (*mach_init_IRQ) (void) __initdata = NULL;
94 void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
95 void (*mach_get_model) (char *model) = NULL;
96 int (*mach_get_hardware_list) (char *buffer) = NULL;
97 int (*mach_get_irq_list) (char *) = NULL;
98 void (*mach_process_int) (int, struct pt_regs *) = NULL;
99 /* machine dependent timer functions */
100 unsigned long (*mach_gettimeoffset) (void);
101 void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
102 int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
103 int (*mach_set_clock_mmss) (unsigned long) = NULL;
104 void (*mach_reset)( void );
105 long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
106 #if defined(CONFIG_AMIGA_FLOPPY)
107 void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
108 void (*mach_floppy_eject) (void) = NULL;
109 #endif
110 #ifdef CONFIG_HEARTBEAT
111 void (*mach_heartbeat) (int) = NULL;
112 extern void apus_heartbeat (void);
113 #endif
114
115 extern unsigned long amiga_model;
116 extern unsigned decrementer_count;/* count value for 1e6/HZ microseconds */
117 extern unsigned count_period_num; /* 1 decrementer count equals */
118 extern unsigned count_period_den; /* count_period_num / count_period_den us */
119
120 int num_memory = 0;
121 struct mem_info memory[NUM_MEMINFO];/* memory description */
122 /* FIXME: Duplicate memory data to avoid conflicts with m68k shared code. */
123 int m68k_realnum_memory = 0;
124 struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
125
126 struct mem_info ramdisk;
127
128 extern void amiga_floppy_setup(char *, int *);
129 extern void config_amiga(void);
130
131 static int __60nsram = 0;
132
133 /* for cpuinfo */
134 static int __bus_speed = 0;
135 static int __speed_test_failed = 0;
136
137 /********************************************** COMPILE PROTECTION */
138 /* Provide some stubs that links to Amiga specific functions.
139 * This allows CONFIG_APUS to be removed from generic PPC files while
140 * preventing link errors for other PPC targets.
141 */
142 unsigned long apus_get_rtc_time(void)
143 {
144 #ifdef CONFIG_APUS
145 extern unsigned long m68k_get_rtc_time(void);
146
147 return m68k_get_rtc_time ();
148 #else
149 return 0;
150 #endif
151 }
152
153 int apus_set_rtc_time(unsigned long nowtime)
154 {
155 #ifdef CONFIG_APUS
156 extern int m68k_set_rtc_time(unsigned long nowtime);
157
158 return m68k_set_rtc_time (nowtime);
159 #else
160 return 0;
161 #endif
162 }
163
164
165
166 /* Here some functions we don't support, but which the other ports reference */
167 int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
168 {
169 printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
170 return 0;
171 }
172 int pckbd_getkeycode(unsigned int scancode)
173 {
174 printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
175 return 0;
176 }
177 int pckbd_translate(unsigned char scancode, unsigned char *keycode,
178 char raw_mode)
179 {
180 printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
181 return 0;
182 }
183 char pckbd_unexpected_up(unsigned char keycode)
184 {
185 printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
186 return 0;
187 }
188 void pckbd_leds(unsigned char leds)
189 {
190 printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
191 }
192 void pckbd_init_hw(void)
193 {
194 printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
195 }
196 unsigned char pckbd_sysrq_xlate[128];
197
198 struct pci_bus * __init pci_scan_peer_bridge(int bus)
199 {
200 printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
201 return NULL;
202 }
203
204 /*********************************************************** SETUP */
205 /* From arch/m68k/kernel/setup.c. */
206 void __init apus_setup_arch(void)
207 {
208 #ifdef CONFIG_APUS
209 extern char cmd_line[];
210 int i;
211 char *p, *q;
212
213 /* Let m68k-shared code know it should do the Amiga thing. */
214 m68k_machtype = MACH_AMIGA;
215
216 /* Parse the command line for arch-specific options.
217 * For the m68k, this is currently only "debug=xxx" to enable printing
218 * certain kernel messages to some machine-specific device. */
219 for( p = cmd_line; p && *p; ) {
220 i = 0;
221 if (!strncmp( p, "debug=", 6 )) {
222 strncpy( debug_device, p+6, sizeof(debug_device)-1 );
223 debug_device[sizeof(debug_device)-1] = 0;
224 if ((q = strchr( debug_device, ' ' ))) *q = 0;
225 i = 1;
226 } else if (!strncmp( p, "60nsram", 7 )) {
227 APUS_WRITE (APUS_REG_WAITSTATE,
228 REGWAITSTATE_SETRESET
229 |REGWAITSTATE_PPCR
230 |REGWAITSTATE_PPCW);
231 __60nsram = 1;
232 i = 1;
233 }
234
235 if (i) {
236 /* option processed, delete it */
237 if ((q = strchr( p, ' ' )))
238 strcpy( p, q+1 );
239 else
240 *p = 0;
241 } else {
242 if ((p = strchr( p, ' ' ))) ++p;
243 }
244 }
245
246 config_amiga();
247
248 #if 0 /* Enable for logging - also include logging.o in Makefile rule */
249 {
250 #define LOG_SIZE 4096
251 void* base;
252
253 /* Throw away some memory - the P5 firmare stomps on top
254 * of CHIP memory during bootup.
255 */
256 amiga_chip_alloc(0x1000);
257
258 base = amiga_chip_alloc(LOG_SIZE+sizeof(klog_data_t));
259 LOG_INIT(base, base+sizeof(klog_data_t), LOG_SIZE);
260 }
261 #endif
262 #endif
263 }
264
265 int
266 apus_get_cpuinfo(char *buffer)
267 {
268 #ifdef CONFIG_APUS
269 extern int __map_without_bats;
270 extern unsigned long powerup_PCI_present;
271 int len;
272
273 len = sprintf(buffer, "machine\t\t: Amiga\n");
274 len += sprintf(buffer+len, "bus speed\t: %d%s", __bus_speed,
275 (__speed_test_failed) ? " [failed]\n" : "\n");
276 len += sprintf(buffer+len, "using BATs\t: %s\n",
277 (__map_without_bats) ? "No" : "Yes");
278 len += sprintf(buffer+len, "ram speed\t: %dns\n",
279 (__60nsram) ? 60 : 70);
280 len += sprintf(buffer+len, "PCI bridge\t: %s\n",
281 (powerup_PCI_present) ? "Yes" : "No");
282 return len;
283 #endif
284 }
285
286 static void get_current_tb(unsigned long long *time)
287 {
288 __asm __volatile ("1:mftbu 4 \n\t"
289 " mftb 5 \n\t"
290 " mftbu 6 \n\t"
291 " cmpw 4,6 \n\t"
292 " bne 1b \n\t"
293 " stw 4,0(%0)\n\t"
294 " stw 5,4(%0)\n\t"
295 :
296 : "r" (time)
297 : "r4", "r5", "r6");
298 }
299
300
301 void apus_calibrate_decr(void)
302 {
303 #ifdef CONFIG_APUS
304 unsigned long freq;
305
306 /* This algorithm for determining the bus speed was
307 contributed by Ralph Schmidt. */
308 unsigned long long start, stop;
309 int bus_speed;
310 int speed_test_failed = 0;
311
312 {
313 unsigned long loop = amiga_eclock / 10;
314
315 get_current_tb (&start);
316 while (loop--) {
317 unsigned char tmp;
318
319 tmp = ciaa.pra;
320 }
321 get_current_tb (&stop);
322 }
323
324 bus_speed = (((unsigned long)(stop-start))*10*4) / 1000000;
325 if (AMI_1200 == amiga_model)
326 bus_speed /= 2;
327
328 if ((bus_speed >= 47) && (bus_speed < 53)) {
329 bus_speed = 50;
330 freq = 12500000;
331 } else if ((bus_speed >= 57) && (bus_speed < 63)) {
332 bus_speed = 60;
333 freq = 15000000;
334 } else if ((bus_speed >= 63) && (bus_speed < 69)) {
335 bus_speed = 67;
336 freq = 16666667;
337 } else {
338 printk ("APUS: Unable to determine bus speed (%d). "
339 "Defaulting to 50MHz", bus_speed);
340 bus_speed = 50;
341 freq = 12500000;
342 speed_test_failed = 1;
343 }
344
345 /* Ease diagnostics... */
346 {
347 extern int __map_without_bats;
348 extern unsigned long powerup_PCI_present;
349
350 printk ("APUS: BATs=%d, BUS=%dMHz",
351 (__map_without_bats) ? 0 : 1,
352 bus_speed);
353 if (speed_test_failed)
354 printk ("[FAILED - please report]");
355
356 printk (", RAM=%dns, PCI bridge=%d\n",
357 (__60nsram) ? 60 : 70,
358 (powerup_PCI_present) ? 1 : 0);
359
360 /* print a bit more if asked politely... */
361 if (!(ciaa.pra & 0x40)){
362 extern unsigned int bat_addrs[4][3];
363 int b;
364 for (b = 0; b < 4; ++b) {
365 printk ("APUS: BAT%d ", b);
366 printk ("%08x-%08x -> %08x\n",
367 bat_addrs[b][0],
368 bat_addrs[b][1],
369 bat_addrs[b][2]);
370 }
371 }
372
373 }
374
375 printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
376 freq/1000000, freq%1000000);
377 tb_ticks_per_jiffy = freq / HZ;
378 tb_to_us = mulhwu_scale_factor(freq, 1000000);
379
380 __bus_speed = bus_speed;
381 __speed_test_failed = speed_test_failed;
382 #endif
383 }
384
385 void arch_gettod(int *year, int *mon, int *day, int *hour,
386 int *min, int *sec)
387 {
388 #ifdef CONFIG_APUS
389 if (mach_gettod)
390 mach_gettod(year, mon, day, hour, min, sec);
391 else
392 *year = *mon = *day = *hour = *min = *sec = 0;
393 #endif
394 }
395
396 /* for "kbd-reset" cmdline param */
397 __init
398 void kbd_reset_setup(char *str, int *ints)
399 {
400 }
401
402 /*********************************************************** FLOPPY */
403 #if defined(CONFIG_AMIGA_FLOPPY)
404 __init
405 void floppy_setup(char *str, int *ints)
406 {
407 if (mach_floppy_setup)
408 mach_floppy_setup (str, ints);
409 }
410
411 void floppy_eject(void)
412 {
413 if (mach_floppy_eject)
414 mach_floppy_eject();
415 }
416 #endif
417
418 /*********************************************************** MEMORY */
419 #define KMAP_MAX 32
420 unsigned long kmap_chunks[KMAP_MAX*3];
421 int kmap_chunk_count = 0;
422
423 /* From pgtable.h */
424 static __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va)
425 {
426 pgd_t *dir = 0;
427 pmd_t *pmd = 0;
428 pte_t *pte = 0;
429
430 va &= PAGE_MASK;
431
432 dir = pgd_offset( mm, va );
433 if (dir)
434 {
435 pmd = pmd_offset(dir, va & PAGE_MASK);
436 if (pmd && pmd_present(*pmd))
437 {
438 pte = pte_offset(pmd, va);
439 }
440 }
441 return pte;
442 }
443
444
445 /* Again simulating an m68k/mm/kmap.c function. */
446 void kernel_set_cachemode( unsigned long address, unsigned long size,
447 unsigned int cmode )
448 {
449 unsigned long mask, flags;
450
451 switch (cmode)
452 {
453 case IOMAP_FULL_CACHING:
454 mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
455 flags = 0;
456 break;
457 case IOMAP_NOCACHE_SER:
458 mask = ~0;
459 flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
460 break;
461 default:
462 panic ("kernel_set_cachemode() doesn't support mode %d\n",
463 cmode);
464 break;
465 }
466
467 size /= PAGE_SIZE;
468 address &= PAGE_MASK;
469 while (size--)
470 {
471 pte_t *pte;
472
473 pte = my_find_pte(&init_mm, address);
474 if ( !pte )
475 {
476 printk("pte NULL in kernel_set_cachemode()\n");
477 return;
478 }
479
480 pte_val (*pte) &= mask;
481 pte_val (*pte) |= flags;
482 flush_tlb_page(find_vma(&init_mm,address),address);
483
484 address += PAGE_SIZE;
485 }
486 }
487
488 unsigned long mm_ptov (unsigned long paddr)
489 {
490 unsigned long ret;
491 if (paddr < 16*1024*1024)
492 ret = ZTWO_VADDR(paddr);
493 else {
494 int i;
495
496 for (i = 0; i < kmap_chunk_count;){
497 unsigned long phys = kmap_chunks[i++];
498 unsigned long size = kmap_chunks[i++];
499 unsigned long virt = kmap_chunks[i++];
500 if (paddr >= phys
501 && paddr < (phys + size)){
502 ret = virt + paddr - phys;
503 goto exit;
504 }
505 }
506
507 ret = (unsigned long) __va(paddr);
508 }
509 exit:
510 #ifdef DEBUGPV
511 printk ("PTOV(%lx)=%lx\n", paddr, ret);
512 #endif
513 return ret;
514 }
515
516 int mm_end_of_chunk (unsigned long addr, int len)
517 {
518 if (memory[0].addr + memory[0].size == addr + len)
519 return 1;
520 return 0;
521 }
522
523 /*********************************************************** CACHE */
524
525 #define L1_CACHE_BYTES 32
526 #define MAX_CACHE_SIZE 8192
527 void cache_push(__u32 addr, int length)
528 {
529 addr = mm_ptov(addr);
530
531 if (MAX_CACHE_SIZE < length)
532 length = MAX_CACHE_SIZE;
533
534 while(length > 0){
535 __asm ("dcbf 0,%0\n\t"
536 : : "r" (addr));
537 addr += L1_CACHE_BYTES;
538 length -= L1_CACHE_BYTES;
539 }
540 /* Also flush trailing block */
541 __asm ("dcbf 0,%0\n\t"
542 "sync \n\t"
543 : : "r" (addr));
544 }
545
546 void cache_clear(__u32 addr, int length)
547 {
548 if (MAX_CACHE_SIZE < length)
549 length = MAX_CACHE_SIZE;
550
551 addr = mm_ptov(addr);
552
553 __asm ("dcbf 0,%0\n\t"
554 "sync \n\t"
555 "icbi 0,%0 \n\t"
556 "isync \n\t"
557 : : "r" (addr));
558
559 addr += L1_CACHE_BYTES;
560 length -= L1_CACHE_BYTES;
561
562 while(length > 0){
563 __asm ("dcbf 0,%0\n\t"
564 "sync \n\t"
565 "icbi 0,%0 \n\t"
566 "isync \n\t"
567 : : "r" (addr));
568 addr += L1_CACHE_BYTES;
569 length -= L1_CACHE_BYTES;
570 }
571
572 __asm ("dcbf 0,%0\n\t"
573 "sync \n\t"
574 "icbi 0,%0 \n\t"
575 "isync \n\t"
576 : : "r" (addr));
577 }
578
579 /****************************************************** from setup.c */
580 void
581 apus_restart(char *cmd)
582 {
583 cli();
584
585 APUS_WRITE(APUS_REG_LOCK,
586 REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
587 APUS_WRITE(APUS_REG_LOCK,
588 REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
589 APUS_WRITE(APUS_REG_LOCK,
590 REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
591 APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
592 APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
593 for(;;);
594 }
595
596 void
597 apus_power_off(void)
598 {
599 for (;;);
600 }
601
602 void
603 apus_halt(void)
604 {
605 apus_restart(NULL);
606 }
607
608 /****************************************************** from setup.c/IDE */
609 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
610 /*
611 * IDE stuff.
612 */
613
614 #if 0 /* no longer used -- paulus */
615 void
616 apus_ide_fix_driveid(struct hd_driveid *id)
617 {
618 u_char *p = (u_char *)id;
619 int i, j, cnt;
620 u_char t;
621
622 if (!MACH_IS_AMIGA && !MACH_IS_MAC)
623 return;
624 for (i = 0; i < num_driveid_types; i++) {
625 cnt = driveid_types[i] & T_MASK_COUNT;
626 switch (driveid_types[i] & T_MASK_TYPE) {
627 case T_CHAR:
628 p += cnt;
629 break;
630 case T_SHORT:
631 for (j = 0; j < cnt; j++) {
632 t = p[0];
633 p[0] = p[1];
634 p[1] = t;
635 p += 2;
636 }
637 break;
638 case T_INT:
639 for (j = 0; j < cnt; j++) {
640 t = p[0];
641 p[0] = p[3];
642 p[3] = t;
643 t = p[1];
644 p[1] = p[2];
645 p[2] = t;
646 p += 4;
647 }
648 break;
649 case T_TEXT:
650 for (j = 0; j < cnt; j += 2) {
651 t = p[0];
652 p[0] = p[1];
653 p[1] = t;
654 p += 2;
655 }
656 break;
657 }
658 }
659 }
660 #endif /* 0 */
661
662 __init
663 void apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port,
664 ide_ioreg_t ctrl_port, int *irq)
665 {
666 if (data_port || ctrl_port)
667 printk("apus_ide_init_hwif_ports: must not be called\n");
668 }
669 #endif
670 /****************************************************** IRQ stuff */
671
672 static unsigned int apus_irq_cannonicalize(unsigned int irq)
673 {
674 return irq;
675 }
676
677 int apus_get_irq_list(char *buf)
678 {
679 #ifdef CONFIG_APUS
680 extern int amiga_get_irq_list(char *buf);
681
682 return amiga_get_irq_list (buf);
683 #else
684 return 0;
685 #endif
686 }
687
688 /* IPL must be between 0 and 7 */
689 static inline void apus_set_IPL(unsigned long ipl)
690 {
691 APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
692 APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
693 APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | ((~ipl) & IPLEMU_IPLMASK));
694 APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
695 }
696
697 static inline unsigned long apus_get_IPL(void)
698 {
699 /* This returns the present IPL emulation level. */
700 unsigned long __f;
701 APUS_READ(APUS_IPL_EMU, __f);
702 return ((~__f) & IPLEMU_IPLMASK);
703 }
704
705 static inline unsigned long apus_get_prev_IPL(struct pt_regs* regs)
706 {
707 /* The value saved in mq is the IPL_EMU value at the time of
708 interrupt. The lower bits are the current interrupt level,
709 the upper bits the requested level. Thus, to restore the
710 IPL level to the post-interrupt state, we will need to use
711 the lower bits. */
712 unsigned long __f = regs->mq;
713 return ((~__f) & IPLEMU_IPLMASK);
714 }
715
716
717 #ifdef CONFIG_APUS
718 void free_irq(unsigned int irq, void *dev_id)
719 {
720 extern void amiga_free_irq(unsigned int irq, void *dev_id);
721
722 amiga_free_irq (irq, dev_id);
723 }
724
725 int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
726 unsigned long irqflags, const char * devname, void *dev_id)
727 {
728 extern int amiga_request_irq(unsigned int irq,
729 void (*handler)(int, void *,
730 struct pt_regs *),
731 unsigned long flags,
732 const char *devname,
733 void *dev_id);
734
735 return amiga_request_irq (irq, handler, irqflags, devname, dev_id);
736 }
737
738 /* In Linux/m68k the sys_request_irq deals with vectors 0-7. That's what
739 callers expect - but on Linux/APUS we actually use the IRQ_AMIGA_AUTO
740 vectors (24-31), so we put this dummy function in between to adjust
741 the vector argument (rather have cruft here than in the generic irq.c). */
742 int sys_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
743 unsigned long irqflags, const char * devname, void *dev_id)
744 {
745 extern int request_sysirq(unsigned int irq,
746 void (*handler)(int, void *,
747 struct pt_regs *),
748 unsigned long irqflags,
749 const char * devname, void *dev_id);
750 return request_sysirq(irq+IRQ_AMIGA_AUTO, handler, irqflags,
751 devname, dev_id);
752 }
753 #endif
754
755 int apus_get_irq(struct pt_regs* regs)
756 {
757 #ifdef CONFIG_APUS
758 int level = apus_get_IPL();
759
760 #ifdef __INTERRUPT_DEBUG
761 printk("<%d:%d>", level, apus_get_prev_IPL(regs));
762 #endif
763
764 if (0 == level)
765 return -8;
766 if (7 == level)
767 return -9;
768
769 return level + IRQ_AMIGA_AUTO;
770 #else
771 return 0;
772 #endif
773 }
774
775 void apus_post_irq(struct pt_regs* regs, int level)
776 {
777 #ifdef __INTERRUPT_DEBUG
778 printk("{%d}", apus_get_prev_IPL(regs));
779 #endif
780 /* Restore IPL to the previous value */
781 apus_set_IPL(apus_get_prev_IPL(regs));
782 }
783
784 /****************************************************** keyboard */
785 static int apus_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
786 {
787 return -EOPNOTSUPP;
788 }
789
790 static int apus_kbd_getkeycode(unsigned int scancode)
791 {
792 return scancode > 127 ? -EINVAL : scancode;
793 }
794
795 static int apus_kbd_translate(unsigned char keycode, unsigned char *keycodep,
796 char raw_mode)
797 {
798 *keycodep = keycode;
799 return 1;
800 }
801
802 static char apus_kbd_unexpected_up(unsigned char keycode)
803 {
804 return 0200;
805 }
806
807 static void apus_kbd_leds(unsigned char leds)
808 {
809 }
810
811 static void apus_kbd_init_hw(void)
812 {
813 #ifdef CONFIG_APUS
814 extern int amiga_keyb_init(void);
815
816 amiga_keyb_init();
817 #endif
818 }
819
820
821 /****************************************************** debugging */
822
823 /* some serial hardware definitions */
824 #define SDR_OVRUN (1<<15)
825 #define SDR_RBF (1<<14)
826 #define SDR_TBE (1<<13)
827 #define SDR_TSRE (1<<12)
828
829 #define AC_SETCLR (1<<15)
830 #define AC_UARTBRK (1<<11)
831
832 #define SER_DTR (1<<7)
833 #define SER_RTS (1<<6)
834 #define SER_DCD (1<<5)
835 #define SER_CTS (1<<4)
836 #define SER_DSR (1<<3)
837
838 static __inline__ void ser_RTSon(void)
839 {
840 ciab.pra &= ~SER_RTS; /* active low */
841 }
842
843 int __debug_ser_out( unsigned char c )
844 {
845 custom.serdat = c | 0x100;
846 mb();
847 while (!(custom.serdatr & 0x2000))
848 barrier();
849 return 1;
850 }
851
852 unsigned char __debug_ser_in( void )
853 {
854 unsigned char c;
855
856 /* XXX: is that ok?? derived from amiga_ser.c... */
857 while( !(custom.intreqr & IF_RBF) )
858 barrier();
859 c = custom.serdatr;
860 /* clear the interrupt, so that another character can be read */
861 custom.intreq = IF_RBF;
862 return c;
863 }
864
865 int __debug_serinit( void )
866 {
867 unsigned long flags;
868
869 save_flags (flags);
870 cli();
871
872 /* turn off Rx and Tx interrupts */
873 custom.intena = IF_RBF | IF_TBE;
874
875 /* clear any pending interrupt */
876 custom.intreq = IF_RBF | IF_TBE;
877
878 restore_flags (flags);
879
880 /*
881 * set the appropriate directions for the modem control flags,
882 * and clear RTS and DTR
883 */
884 ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */
885 ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */
886
887 #ifdef CONFIG_KGDB
888 /* turn Rx interrupts on for GDB */
889 custom.intena = IF_SETCLR | IF_RBF;
890 ser_RTSon();
891 #endif
892
893 return 0;
894 }
895
896 void __debug_print_hex(unsigned long x)
897 {
898 int i;
899 char hexchars[] = "0123456789ABCDEF";
900
901 for (i = 0; i < 8; i++) {
902 __debug_ser_out(hexchars[(x >> 28) & 15]);
903 x <<= 4;
904 }
905 __debug_ser_out('\n');
906 __debug_ser_out('\r');
907 }
908
909 void __debug_print_string(char* s)
910 {
911 unsigned char c;
912 while((c = *s++))
913 __debug_ser_out(c);
914 __debug_ser_out('\n');
915 __debug_ser_out('\r');
916 }
917
918 static void apus_progress(char *s, unsigned short value)
919 {
920 __debug_print_string(s);
921 }
922
923 /****************************************************** init */
924
925 /* The number of spurious interrupts */
926 volatile unsigned int num_spurious;
927
928 #define NUM_IRQ_NODES 100
929 static irq_node_t nodes[NUM_IRQ_NODES];
930
931 extern void (*amiga_default_handler[AUTO_IRQS])(int, void *, struct pt_regs *);
932
933 static const char *default_names[SYS_IRQS] = {
934 "spurious int", "int1 handler", "int2 handler", "int3 handler",
935 "int4 handler", "int5 handler", "int6 handler", "int7 handler"
936 };
937
938 irq_node_t *new_irq_node(void)
939 {
940 irq_node_t *node;
941 short i;
942
943 for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
944 if (!node->handler)
945 return node;
946
947 printk ("new_irq_node: out of nodes\n");
948 return NULL;
949 }
950
951 extern void amiga_enable_irq(unsigned int irq);
952 extern void amiga_disable_irq(unsigned int irq);
953
954 struct hw_interrupt_type amiga_irqctrl = {
955 " Amiga ",
956 NULL,
957 NULL,
958 amiga_enable_irq,
959 amiga_disable_irq,
960 0,
961 0
962 };
963
964 #define HARDWARE_MAPPED_SIZE (512*1024)
965 unsigned long __init apus_find_end_of_memory(void)
966 {
967 int shadow = 0;
968 unsigned long total;
969
970 /* The memory size reported by ADOS excludes the 512KB
971 reserved for PPC exception registers and possibly 512KB
972 containing a shadow of the ADOS ROM. */
973 {
974 unsigned long size = memory[0].size;
975
976 /* If 2MB aligned, size was probably user
977 specified. We can't tell anything about shadowing
978 in this case so skip shadow assignment. */
979 if (0 != (size & 0x1fffff)){
980 /* Align to 512KB to ensure correct handling
981 of both memfile and system specified
982 sizes. */
983 size = ((size+0x0007ffff) & 0xfff80000);
984 /* If memory is 1MB aligned, assume
985 shadowing. */
986 shadow = !(size & 0x80000);
987 }
988
989 /* Add the chunk that ADOS does not see. by aligning
990 the size to the nearest 2MB limit upwards. */
991 memory[0].size = ((size+0x001fffff) & 0xffe00000);
992 }
993
994 total = memory[0].size;
995
996 /* Remove the memory chunks that are controlled by special
997 Phase5 hardware. */
998
999 /* Remove the upper 512KB if it contains a shadow of
1000 the ADOS ROM. FIXME: It might be possible to
1001 disable this shadow HW. Check the booter
1002 (ppc_boot.c) */
1003 if (shadow)
1004 total -= HARDWARE_MAPPED_SIZE;
1005
1006 /* Remove the upper 512KB where the PPC exception
1007 vectors are mapped. */
1008 total -= HARDWARE_MAPPED_SIZE;
1009
1010 /* Linux/APUS only handles one block of memory -- the one on
1011 the PowerUP board. Other system memory is horrible slow in
1012 comparison. The user can use other memory for swapping
1013 using the z2ram device. */
1014 ram_phys_base = memory[0].addr;
1015 return total;
1016 }
1017
1018 static void __init
1019 apus_map_io(void)
1020 {
1021 /* Map PPC exception vectors. */
1022 io_block_mapping(0xfff00000, 0xfff00000, 0x00020000, _PAGE_KERNEL);
1023 /* Map chip and ZorroII memory */
1024 io_block_mapping(zTwoBase, 0x00000000, 0x01000000, _PAGE_IO);
1025 }
1026
1027 __init
1028 void apus_init_IRQ(void)
1029 {
1030 int i;
1031
1032 for ( i = 0 ; i < NR_IRQS ; i++ )
1033 irq_desc[i].handler = &amiga_irqctrl;
1034
1035 for (i = 0; i < NUM_IRQ_NODES; i++)
1036 nodes[i].handler = NULL;
1037
1038 for (i = 0; i < AUTO_IRQS; i++) {
1039 if (amiga_default_handler[i] != NULL)
1040 sys_request_irq(i, amiga_default_handler[i],
1041 0, default_names[i], NULL);
1042 }
1043
1044 amiga_init_IRQ();
1045
1046 }
1047
1048 __init
1049 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
1050 unsigned long r6, unsigned long r7)
1051 {
1052 extern int parse_bootinfo(const struct bi_record *);
1053 extern char _end[];
1054
1055 /* Parse bootinfo. The bootinfo is located right after
1056 the kernel bss */
1057 parse_bootinfo((const struct bi_record *)&_end);
1058 #ifdef CONFIG_BLK_DEV_INITRD
1059 /* Take care of initrd if we have one. Use data from
1060 bootinfo to avoid the need to initialize PPC
1061 registers when kernel is booted via a PPC reset. */
1062 if ( ramdisk.addr ) {
1063 initrd_start = (unsigned long) __va(ramdisk.addr);
1064 initrd_end = (unsigned long)
1065 __va(ramdisk.size + ramdisk.addr);
1066 }
1067 #endif /* CONFIG_BLK_DEV_INITRD */
1068
1069 ISA_DMA_THRESHOLD = 0x00ffffff;
1070
1071 ppc_md.setup_arch = apus_setup_arch;
1072 ppc_md.setup_residual = NULL;
1073 ppc_md.get_cpuinfo = apus_get_cpuinfo;
1074 ppc_md.irq_cannonicalize = apus_irq_cannonicalize;
1075 ppc_md.init_IRQ = apus_init_IRQ;
1076 ppc_md.get_irq = apus_get_irq;
1077
1078 #error Should use the ->end() member of irq_desc[x]. -- Cort
1079 /*ppc_md.post_irq = apus_post_irq;*/
1080
1081 #ifdef CONFIG_HEARTBEAT
1082 ppc_md.heartbeat = apus_heartbeat;
1083 ppc_md.heartbeat_count = 1;
1084 #endif
1085 #ifdef APUS_DEBUG
1086 __debug_serinit();
1087 ppc_md.progress = apus_progress;
1088 #endif
1089 ppc_md.init = NULL;
1090
1091 ppc_md.restart = apus_restart;
1092 ppc_md.power_off = apus_power_off;
1093 ppc_md.halt = apus_halt;
1094
1095 ppc_md.time_init = NULL;
1096 ppc_md.set_rtc_time = apus_set_rtc_time;
1097 ppc_md.get_rtc_time = apus_get_rtc_time;
1098 ppc_md.calibrate_decr = apus_calibrate_decr;
1099
1100 ppc_md.find_end_of_memory = apus_find_end_of_memory;
1101 ppc_md.setup_io_mappings = apus_map_io;
1102
1103 ppc_md.nvram_read_val = NULL;
1104 ppc_md.nvram_write_val = NULL;
1105
1106 /* These should not be used for the APUS yet, since it uses
1107 the M68K keyboard now. */
1108 ppc_md.kbd_setkeycode = apus_kbd_setkeycode;
1109 ppc_md.kbd_getkeycode = apus_kbd_getkeycode;
1110 ppc_md.kbd_translate = apus_kbd_translate;
1111 ppc_md.kbd_unexpected_up = apus_kbd_unexpected_up;
1112 ppc_md.kbd_leds = apus_kbd_leds;
1113 ppc_md.kbd_init_hw = apus_kbd_init_hw;
1114 #ifdef CONFIG_MAGIC_SYSRQ
1115 ppc_md.kbd_sysrq_xlate = NULL;
1116 #endif
1117
1118 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
1119 ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports;
1120 #endif
1121 }
1122
1123
1124 /*************************************************** coexistence */
1125 void __init adbdev_init(void)
1126 {
1127 }
1128