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