patch-2.2.8 linux/arch/ppc/kernel/chrp_setup.c

Next file: linux/arch/ppc/kernel/head.S
Previous file: linux/arch/ppc/kernel/chrp_pci.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
@@ -41,8 +41,50 @@
 #include <asm/prom.h>
 #include <asm/gg2.h>
 #include <asm/pci-bridge.h>
-
-extern void hydra_init(void);
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/adb.h>
+#include <asm/hydra.h>
+
+#include "time.h"
+#include "local_irq.h"
+#include "i8259.h"
+#include "open_pic.h"
+
+/* Fixme - need to move these into their own .c and .h file */
+extern void i8259_mask_and_ack_irq(unsigned int irq_nr);
+extern void i8259_set_irq_mask(unsigned int irq_nr);
+extern void i8259_mask_irq(unsigned int irq_nr);
+extern void i8259_unmask_irq(unsigned int irq_nr);
+extern void i8259_init(void);
+
+/* Fixme - remove this when it is fixed. - Corey */
+extern volatile unsigned char *chrp_int_ack_special;
+
+unsigned long chrp_get_rtc_time(void);
+int chrp_set_rtc_time(unsigned long nowtime);
+void chrp_calibrate_decr(void);
+void chrp_time_init(void);
+
+void chrp_setup_pci_ptrs(void);
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[128];
+extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int mackbd_getkeycode(unsigned int scancode);
+extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
+			    char raw_mode);
+extern char mackbd_unexpected_up(unsigned char keycode);
+extern void mackbd_leds(unsigned char leds);
+extern void mackbd_init_hw(void);
+extern unsigned char mackbd_sysrq_xlate[128];
 
 /* for the mac fs */
 kdev_t boot_dev;
@@ -61,17 +103,17 @@
 #endif
 
 static const char *gg2_memtypes[4] = {
-    "FPM", "SDRAM", "EDO", "BEDO"
+	"FPM", "SDRAM", "EDO", "BEDO"
 };
 static const char *gg2_cachesizes[4] = {
-    "256 KB", "512 KB", "1 MB", "Reserved"
+	"256 KB", "512 KB", "1 MB", "Reserved"
 };
 static const char *gg2_cachetypes[4] = {
-    "Asynchronous", "Reserved", "Flow-Through Synchronous",
-    "Pipelined Synchronous"
+	"Asynchronous", "Reserved", "Flow-Through Synchronous",
+	"Pipelined Synchronous"
 };
 static const char *gg2_cachemodes[4] = {
-    "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
+	"Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
 };
 
 int
@@ -84,7 +126,7 @@
 
 	root = find_path_device("/");
 	if (root)
-	    model = get_property(root, "model", NULL);
+		model = get_property(root, "model", NULL);
 	len = sprintf(buffer,"machine\t\t: CHRP %s\n", model);
 
 	/* longtrail (goldengate) stuff */
@@ -137,7 +179,7 @@
 	return len;
 }
 
-    /*
+/*
      *  Fixes for the National Semiconductor PC78308VUL SuperI/O
      *
      *  Some versions of Open Firmware incorrectly initialize the IRQ settings
@@ -146,56 +188,56 @@
 
 __initfunc(static inline void sio_write(u8 val, u8 index))
 {
-    outb(index, 0x15c);
-    outb(val, 0x15d);
+	outb(index, 0x15c);
+	outb(val, 0x15d);
 }
 
 __initfunc(static inline u8 sio_read(u8 index))
 {
-    outb(index, 0x15c);
-    return inb(0x15d);
+	outb(index, 0x15c);
+	return inb(0x15d);
 }
 
 __initfunc(static void sio_fixup_irq(const char *name, u8 device, u8 level,
 				     u8 type))
 {
-    u8 level0, type0, active;
+	u8 level0, type0, active;
 
-    /* select logical device */
-    sio_write(device, 0x07);
-    active = sio_read(0x30);
-    level0 = sio_read(0x70);
-    type0 = sio_read(0x71);
-    printk("sio: %s irq level %d, type %d, %sactive: ", name, level0, type0,
-	   !active ? "in" : "");
-    if (level0 == level && type0 == type && active)
-	printk("OK\n");
-    else {
-	printk("remapping to level %d, type %d, active\n", level, type);
-	sio_write(0x01, 0x30);
-	sio_write(level, 0x70);
-	sio_write(type, 0x71);
-    }
+	/* select logical device */
+	sio_write(device, 0x07);
+	active = sio_read(0x30);
+	level0 = sio_read(0x70);
+	type0 = sio_read(0x71);
+	printk("sio: %s irq level %d, type %d, %sactive: ", name, level0, type0,
+	       !active ? "in" : "");
+	if (level0 == level && type0 == type && active)
+		printk("OK\n");
+	else {
+		printk("remapping to level %d, type %d, active\n", level, type);
+		sio_write(0x01, 0x30);
+		sio_write(level, 0x70);
+		sio_write(type, 0x71);
+	}
 
 }
 
 __initfunc(static void sio_init(void))
 {
-    /* logical device 0 (KBC/Keyboard) */
-    sio_fixup_irq("keyboard", 0, 1, 2);
-    /* select logical device 1 (KBC/Mouse) */
-    sio_fixup_irq("mouse", 1, 12, 2);
+	/* logical device 0 (KBC/Keyboard) */
+	sio_fixup_irq("keyboard", 0, 1, 2);
+	/* select logical device 1 (KBC/Mouse) */
+	sio_fixup_irq("mouse", 1, 12, 2);
 }
 
 
 __initfunc(void
-chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
+	   chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
 {
 	extern char cmd_line[];
 
 	/* init to some ~sane value until calibrate_delay() runs */
 	loops_per_sec = 50000000;
-	
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* this is fine for chrp */
 	initrd_below_start_ok = 1;
@@ -243,27 +285,210 @@
 	if ( !strncmp("MOT", get_property(find_path_device("/"),
 					  "model", NULL),3) )
 		*memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+	/*
+	 * The f50 has a lot of IO space - we need to map some in that
+	 * isn't covered by the BAT mappings in MMU_init() -- Cort
+	 */
+	if ( !strncmp("F5", get_property(find_path_device("/"),
+					 "ibm,model-class", NULL),2) )
+	{
+#if 0		
+		/*
+		 * This ugly hack allows us to force ioremap() to
+		 * create a 1-to-1 mapping for us, even though
+		 * the address is < ioremap_base.  This is necessary
+		 * since we want our PCI IO space to have contiguous
+		 * virtual addresses and I think it's worse to have
+		 * calls to map_page() here.
+		 * -- Cort
+		 */
+		unsigned long hold = ioremap_base;
+		ioremap_base = 0;
+		__ioremap(0x90000000, 0x10000000, _PAGE_NO_CACHE);
+		ioremap_base = hold;
+#endif		
+	}
 }
 
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+void
+chrp_restart(char *cmd)
+{
+#if 0
+	extern unsigned int rtas_entry, rtas_data, rtas_size;
+	printk("RTAS system-reboot returned %d\n",
+	       call_rtas("system-reboot", 0, 1, NULL));
+	printk("rtas_entry: %08lx rtas_data: %08lx rtas_size: %08lx\n",
+	       rtas_entry,rtas_data,rtas_size);
+	for (;;);
+#else
+	printk("System Halted\n");
+	while(1);
+#endif
+}
 
-unsigned int chrp_ide_irq = 0;
-int chrp_ide_ports_known = 0;
-ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
-ide_ioreg_t chrp_idedma_regbase;
+void
+chrp_power_off(void)
+{
+	/* RTAS doesn't seem to work on Longtrail.
+	   For now, do it the same way as the PReP. */
+#if 0
+	extern unsigned int rtas_entry, rtas_data, rtas_size;
+	printk("RTAS power-off returned %d\n",
+	       call_rtas("power-off", 2, 1, NULL, 0, 0));
+	printk("rtas_entry: %08lx rtas_data: %08lx rtas_size: %08lx\n",
+	       rtas_entry,rtas_data,rtas_size);
+	for (;;);
+#else
+	chrp_restart(NULL);
+#endif
+}
 
-void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void
+chrp_halt(void)
 {
-        ide_ioreg_t port = base;
-        int i = 8;
+	chrp_restart(NULL);
+}
 
-        while (i--)
-                *p++ = port++;
-        *p++ = port;
-        if (irq != NULL)
-                *irq = chrp_ide_irq;
+u_int
+chrp_irq_cannonicalize(u_int irq)
+{
+	if (irq == 2)
+	{
+		return 9;
+	}
+	else
+	{
+		return irq;
+	}
+}
+
+void
+chrp_do_IRQ(struct pt_regs *regs,
+	    int            cpu,
+            int            isfake)
+{
+        int irq;
+        unsigned long bits = 0;
+        int openpic_eoi_done = 0;
+
+#ifdef __SMP__
+        {
+                unsigned int loops = 1000000;
+                while (test_bit(0, &global_irq_lock)) {
+                        if (smp_processor_id() == global_irq_holder) {
+                                printk("uh oh, interrupt while we hold global irq lock!\n");
+#ifdef CONFIG_XMON
+                                xmon(0);
+#endif
+                                break;
+                        }
+                        if (loops-- == 0) {
+                                printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
+#ifdef CONFIG_XMON
+                                xmon(0);
+#endif
+                        }
+                }
+        }
+#endif /* __SMP__ */
+
+        irq = openpic_irq(0);
+        if (irq == IRQ_8259_CASCADE)
+        {
+                /*
+                 * This magic address generates a PCI IACK cycle.
+                 *
+                 * This should go in the above mask/ack code soon. -- Cort
+                 */
+		if ( chrp_int_ack_special )
+			irq = *chrp_int_ack_special;
+		else
+			irq = i8259_irq(0);
+                /*
+                 * Acknowledge as soon as possible to allow i8259
+                 * interrupt nesting                         */
+                openpic_eoi(0);
+                openpic_eoi_done = 1;
+        }
+        if (irq == OPENPIC_VEC_SPURIOUS)
+        {
+                /*
+                 * Spurious interrupts should never be
+                 * acknowledged
+                 */
+                ppc_spurious_interrupts++;
+                openpic_eoi_done = 1;
+		goto out;
+        }
+        bits = 1UL << irq;
+
+        if (irq < 0)
+        {
+                printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+                       irq, regs->nip);
+                ppc_spurious_interrupts++;
+        }
+	else
+        {
+		ppc_irq_dispatch_handler( regs, irq );
+	}
+out:
+        if (!openpic_eoi_done)
+                openpic_eoi(0);
 }
 
+__initfunc(void
+	   chrp_init_IRQ(void))
+{
+	struct device_node *np;
+	int i;
+
+	if ( !(np = find_devices("pci") ) )
+		printk("Cannot find pci to get ack address\n");
+	else
+	{
+		chrp_int_ack_special = (volatile unsigned char *)
+			(*(unsigned long *)get_property(np,
+							"8259-interrupt-acknowledge", NULL));
+	}
+	for ( i = 16 ; i < NR_IRQS ; i++ )
+		irq_desc[i].ctl = &open_pic;
+	/* openpic knows that it's at irq 16 offset
+	 * so we don't need to set it in the pic structure
+	 * -- Cort
+	 */
+	openpic_init(1);
+	for ( i = 0 ; i < 16  ; i++ )
+		irq_desc[i].ctl = &i8259_pic;
+	i8259_init();
+#ifdef CONFIG_XMON
+	request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI),
+		    xmon_irq, 0, "NMI", 0);
+#endif	/* CONFIG_XMON */
+#ifdef __SMP__
+	request_irq(openpic_to_irq(OPENPIC_VEC_IPI),
+		    openpic_ipi_action, 0, "IPI0", 0);
+#endif	/* __SMP__ */
+}
+
+__initfunc(void
+	   chrp_init2(void))
+{
+	adb_init();
+
+	/* Should this be here? - Corey */
+	pmac_nvram_init();
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+unsigned int chrp_ide_irq = 0;
+int chrp_ide_ports_known = 0;
+ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
+ide_ioreg_t chrp_idedma_regbase;
+
 void chrp_ide_probe(void) {
 
         struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
@@ -281,9 +506,167 @@
         }
 }
 
+void
+chrp_ide_insw(ide_ioreg_t port, void *buf, int ns)
+{
+	ide_insw(port+_IO_BASE, buf, ns);
+}
+
+void
+chrp_ide_outsw(ide_ioreg_t port, void *buf, int ns)
+{
+	ide_outsw(port+_IO_BASE, buf, ns);
+}
+
+int
+chrp_ide_default_irq(ide_ioreg_t base)
+{
+        if (chrp_ide_ports_known == 0)
+	        chrp_ide_probe();
+	return chrp_ide_irq;
+}
+
+ide_ioreg_t
+chrp_ide_default_io_base(int index)
+{
+        if (chrp_ide_ports_known == 0)
+	        chrp_ide_probe();
+	return chrp_ide_regbase[index];
+}
+
+int
+chrp_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+        return check_region(from, extent);
+}
+
+void
+chrp_ide_request_region(ide_ioreg_t from,
+			unsigned int extent,
+			const char *name)
+{
+        request_region(from, extent, name);
+}
+
+void
+chrp_ide_release_region(ide_ioreg_t from,
+			unsigned int extent)
+{
+        release_region(from, extent);
+}
+
+void
+chrp_ide_fix_driveid(struct hd_driveid *id)
+{
+        ppc_generic_ide_fix_driveid(id);
+}
+
+void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+{
+        ide_ioreg_t port = base;
+        int i = 8;
+
+        while (i--)
+                *p++ = port++;
+        *p++ = port;
+        if (irq != NULL)
+                *irq = chrp_ide_irq;
+}
+
 EXPORT_SYMBOL(chrp_ide_irq);
 EXPORT_SYMBOL(chrp_ide_ports_known);
 EXPORT_SYMBOL(chrp_ide_regbase);
 EXPORT_SYMBOL(chrp_ide_probe);
 
 #endif
+
+__initfunc(void
+	   chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
+		     unsigned long r6, unsigned long r7))
+{
+	chrp_setup_pci_ptrs();
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* take care of initrd if we have one */
+	if ( r3 )
+	{
+		initrd_start = r3 + KERNELBASE;
+		initrd_end = r3 + r4 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+        /* pci_dram_offset/isa_io_base/isa_mem_base set by setup_pci_ptrs() */
+	ISA_DMA_THRESHOLD = ~0L;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	ppc_md.setup_arch     = chrp_setup_arch;
+	ppc_md.setup_residual = NULL;
+	ppc_md.get_cpuinfo    = chrp_get_cpuinfo;
+	ppc_md.irq_cannonicalize = chrp_irq_cannonicalize;
+	ppc_md.init_IRQ       = chrp_init_IRQ;
+	ppc_md.do_IRQ         = chrp_do_IRQ;
+		
+	ppc_md.init           = chrp_init2;
+
+	ppc_md.restart        = chrp_restart;
+	ppc_md.power_off      = chrp_power_off;
+	ppc_md.halt           = chrp_halt;
+
+	ppc_md.time_init      = chrp_time_init;
+	ppc_md.set_rtc_time   = chrp_set_rtc_time;
+	ppc_md.get_rtc_time   = chrp_get_rtc_time;
+	ppc_md.calibrate_decr = chrp_calibrate_decr;
+
+#ifdef CONFIG_VT
+#ifdef CONFIG_MAC_KEYBOAD
+	if ( adb_hardware == ADB_NONE )
+	{
+		ppc_md.kbd_setkeycode    = pckbd_setkeycode;
+		ppc_md.kbd_getkeycode    = pckbd_getkeycode;
+		ppc_md.kbd_translate     = pckbd_translate;
+		ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+		ppc_md.kbd_leds          = pckbd_leds;
+		ppc_md.kbd_init_hw       = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+		ppc_md.kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
+#endif		
+	}
+	else
+	{
+		ppc_md.kbd_setkeycode    = mackbd_setkeycode;
+		ppc_md.kbd_getkeycode    = mackbd_getkeycode;
+		ppc_md.kbd_translate     = mackbd_translate;
+		ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
+		ppc_md.kbd_leds          = mackbd_leds;
+		ppc_md.kbd_init_hw       = mackbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+		ppc_md.kbd_sysrq_xlate	 = mackbd_sysrq_xlate;
+#endif		
+	}
+#else
+	ppc_md.kbd_setkeycode    = pckbd_setkeycode;
+	ppc_md.kbd_getkeycode    = pckbd_getkeycode;
+	ppc_md.kbd_translate     = pckbd_translate;
+	ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+	ppc_md.kbd_leds          = pckbd_leds;
+	ppc_md.kbd_init_hw       = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+	ppc_md.kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
+#endif
+#endif
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+        ppc_ide_md.insw = chrp_ide_insw;
+        ppc_ide_md.outsw = chrp_ide_outsw;
+        ppc_ide_md.default_irq = chrp_ide_default_irq;
+        ppc_ide_md.default_io_base = chrp_ide_default_io_base;
+        ppc_ide_md.check_region = chrp_ide_check_region;
+        ppc_ide_md.request_region = chrp_ide_request_region;
+        ppc_ide_md.release_region = chrp_ide_release_region;
+        ppc_ide_md.fix_driveid = chrp_ide_fix_driveid;
+        ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports;
+
+        ppc_ide_md.io_base = _IO_BASE;
+#endif		
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)