powerpc: Convert to new irq_* function names
[linux-2.6.git] / arch / powerpc / platforms / chrp / setup.c
index dda5f2c..1227864 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  arch/ppc/platforms/setup.c
- *
  *  Copyright (C) 1995  Linus Torvalds
  *  Adapted from 'alpha' version by Gary Thomas
  *  Modified by Cort Dougan (cort@cs.nmt.edu)
@@ -10,7 +8,6 @@
  * bootup setup stuff..
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/slab.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/tty.h>
 #include <linux/major.h>
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/version.h>
+#include <generated/utsrelease.h>
 #include <linux/adb.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/ide.h>
 #include <linux/console.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/initrd.h>
-#include <linux/module.h>
+#include <linux/timer.h>
 
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
-#include <asm/gg2.h>
 #include <asm/pci-bridge.h>
 #include <asm/dma.h>
 #include <asm/machdep.h>
 #include <asm/hydra.h>
 #include <asm/sections.h>
 #include <asm/time.h>
-#include <asm/btext.h>
 #include <asm/i8259.h>
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 #include <asm/xmon.h>
 
 #include "chrp.h"
+#include "gg2.h"
 
 void rtas_indicator_progress(char *, unsigned short);
-void btext_progress(char *, unsigned short);
 
 int _chrp_type;
 EXPORT_SYMBOL(_chrp_type);
 
-struct mpic *chrp_mpic;
+static struct mpic *chrp_mpic;
 
-/*
- * XXX this should be in xmon.h, but putting it there means xmon.h
- * has to include <linux/interrupt.h> (to get irqreturn_t), which
- * causes all sorts of problems.  -- paulus
- */
-extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
+/* Used for doing CHRP event-scans */
+DEFINE_PER_CPU(struct timer_list, heartbeat_timer);
+unsigned long event_scan_interval;
 
 extern unsigned long loops_per_jiffy;
 
+/* To be replaced by RTAS when available */
+static unsigned int __iomem *briq_SPOR;
+
 #ifdef CONFIG_SMP
 extern struct smp_ops_t chrp_smp_ops;
 #endif
@@ -92,6 +84,15 @@ static const char *gg2_cachemodes[4] = {
        "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
 };
 
+static const char *chrp_names[] = {
+       "Unknown",
+       "","","",
+       "Motorola",
+       "IBM or Longtrail",
+       "Genesi Pegasos",
+       "Total Impact Briq"
+};
+
 void chrp_show_cpuinfo(struct seq_file *m)
 {
        int i, sdramen;
@@ -99,13 +100,13 @@ void chrp_show_cpuinfo(struct seq_file *m)
        struct device_node *root;
        const char *model = "";
 
-       root = find_path_device("/");
+       root = of_find_node_by_path("/");
        if (root)
-               model = get_property(root, "model", NULL);
+               model = of_get_property(root, "model", NULL);
        seq_printf(m, "machine\t\t: CHRP %s\n", model);
 
        /* longtrail (goldengate) stuff */
-       if (!strncmp(model, "IBM,LongTrail", 13)) {
+       if (model && !strncmp(model, "IBM,LongTrail", 13)) {
                /* VLSI VAS96011/12 `Golden Gate 2' */
                /* Memory banks */
                sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL)
@@ -149,6 +150,7 @@ void chrp_show_cpuinfo(struct seq_file *m)
                           gg2_cachetypes[(t>>2) & 3],
                           gg2_cachemodes[t & 3]);
        }
+       of_node_put(root);
 }
 
 /*
@@ -192,14 +194,21 @@ static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
 static void __init sio_init(void)
 {
        struct device_node *root;
+       const char *model;
 
-       if ((root = find_path_device("/")) &&
-           !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
+       root = of_find_node_by_path("/");
+       if (!root)
+               return;
+
+       model = of_get_property(root, "model", NULL);
+       if (model && !strncmp(model, "IBM,LongTrail", 13)) {
                /* 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);
        }
+
+       of_node_put(root);
 }
 
 
@@ -212,13 +221,12 @@ static void __init pegasos_set_l2cr(void)
                return;
 
        /* Enable L2 cache if needed */
-       np = find_type_devices("cpu");
+       np = of_find_node_by_type(NULL, "cpu");
        if (np != NULL) {
-               unsigned int *l2cr = (unsigned int *)
-                       get_property (np, "l2cr", NULL);
+               const unsigned int *l2cr = of_get_property(np, "l2cr", NULL);
                if (l2cr == NULL) {
                        printk ("Pegasos l2cr : no cpu l2cr property found\n");
-                       return;
+                       goto out;
                }
                if (!((*l2cr) & 0x80000000)) {
                        printk ("Pegasos l2cr : L2 cache was not active, "
@@ -227,31 +235,96 @@ static void __init pegasos_set_l2cr(void)
                        _set_L2CR((*l2cr) | 0x80000000);
                }
        }
+out:
+       of_node_put(np);
+}
+
+static void briq_restart(char *cmd)
+{
+       local_irq_disable();
+       if (briq_SPOR)
+               out_be32(briq_SPOR, 0);
+       for(;;);
+}
+
+/*
+ * Per default, input/output-device points to the keyboard/screen
+ * If no card is installed, the built-in serial port is used as a fallback.
+ * But unfortunately, the firmware does not connect /chosen/{stdin,stdout}
+ * the the built-in serial node. Instead, a /failsafe node is created.
+ */
+static void chrp_init_early(void)
+{
+       struct device_node *node;
+       const char *property;
+
+       if (strstr(cmd_line, "console="))
+               return;
+       /* find the boot console from /chosen/stdout */
+       if (!of_chosen)
+               return;
+       node = of_find_node_by_path("/");
+       if (!node)
+               return;
+       property = of_get_property(node, "model", NULL);
+       if (!property)
+               goto out_put;
+       if (strcmp(property, "Pegasos2"))
+               goto out_put;
+       /* this is a Pegasos2 */
+       property = of_get_property(of_chosen, "linux,stdout-path", NULL);
+       if (!property)
+               goto out_put;
+       of_node_put(node);
+       node = of_find_node_by_path(property);
+       if (!node)
+               return;
+       property = of_get_property(node, "device_type", NULL);
+       if (!property)
+               goto out_put;
+       if (strcmp(property, "serial"))
+               goto out_put;
+       /*
+        * The 9pin connector is either /failsafe
+        * or /pci@80000000/isa@C/serial@i2F8
+        * The optional graphics card has also type 'serial' in VGA mode.
+        */
+       property = of_get_property(node, "name", NULL);
+       if (!property)
+               goto out_put;
+       if (!strcmp(property, "failsafe") || !strcmp(property, "serial"))
+               add_preferred_console("ttyS", 0, NULL);
+out_put:
+       of_node_put(node);
 }
 
 void __init chrp_setup_arch(void)
 {
-       struct device_node *root = find_path_device ("/");
-       char *machine = NULL;
-       struct device_node *device;
-       unsigned int *p = NULL;
+       struct device_node *root = of_find_node_by_path("/");
+       const char *machine = NULL;
 
        /* init to some ~sane value until calibrate_delay() runs */
        loops_per_jiffy = 50000000/HZ;
 
        if (root)
-               machine = get_property(root, "model", NULL);
+               machine = of_get_property(root, "model", NULL);
        if (machine && strncmp(machine, "Pegasos", 7) == 0) {
                _chrp_type = _CHRP_Pegasos;
        } else if (machine && strncmp(machine, "IBM", 3) == 0) {
                _chrp_type = _CHRP_IBM;
        } else if (machine && strncmp(machine, "MOT", 3) == 0) {
                _chrp_type = _CHRP_Motorola;
+       } else if (machine && strncmp(machine, "TotalImpact,BRIQ-1", 18) == 0) {
+               _chrp_type = _CHRP_briq;
+               /* Map the SPOR register on briq and change the restart hook */
+               briq_SPOR = ioremap(0xff0000e8, 4);
+               ppc_md.restart = briq_restart;
        } else {
                /* Let's assume it is an IBM chrp if all else fails */
                _chrp_type = _CHRP_IBM;
        }
-       printk("chrp type = %x\n", _chrp_type);
+       of_node_put(root);
+       printk("chrp type = %x [%s]\n", _chrp_type, chrp_names[_chrp_type]);
 
        rtas_initialize();
        if (rtas_token("display-character") >= 0)
@@ -264,21 +337,6 @@ void __init chrp_setup_arch(void)
                ppc_md.set_rtc_time     = rtas_set_rtc_time;
        }
 
-#ifdef CONFIG_BOOTX_TEXT
-       if (ppc_md.progress == NULL && boot_text_mapped)
-               ppc_md.progress = btext_progress;
-#endif
-
-#ifdef CONFIG_BLK_DEV_INITRD
-       /* this is fine for chrp */
-       initrd_below_start_ok = 1;
-
-       if (initrd_start)
-               ROOT_DEV = Root_RAM0;
-       else
-#endif
-               ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
-
        /* On pegasos, enable the L2 cache if not already done by OF */
        pegasos_set_l2cr();
 
@@ -296,21 +354,6 @@ void __init chrp_setup_arch(void)
         */
        sio_init();
 
-       /* Get the event scan rate for the rtas so we know how
-        * often it expects a heartbeat. -- Cort
-        */
-       device = find_devices("rtas");
-       if (device)
-               p = (unsigned int *) get_property
-                       (device, "rtas-event-scan-rate", NULL);
-       if (p && *p) {
-               ppc_md.heartbeat = chrp_event_scan;
-               ppc_md.heartbeat_reset = HZ / (*p * 30) - 1;
-               ppc_md.heartbeat_count = 1;
-               printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
-                      *p, ppc_md.heartbeat_reset);
-       }
-
        pci_create_OF_bus_map();
 
        /*
@@ -320,16 +363,15 @@ void __init chrp_setup_arch(void)
        if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
 }
 
-void
-chrp_event_scan(void)
+static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       unsigned char log[1024];
-       int ret = 0;
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       unsigned int cascade_irq = i8259_irq();
 
-       /* XXX: we should loop until the hardware says no more error logs -- Cort */
-       rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0,
-                 __pa(log), 1024);
-       ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+       if (cascade_irq != NO_IRQ)
+               generic_handle_irq(cascade_irq);
+
+       chip->irq_eoi(&desc->irq_data);
 }
 
 /*
@@ -338,41 +380,36 @@ chrp_event_scan(void)
 static void __init chrp_find_openpic(void)
 {
        struct device_node *np, *root;
-       int len, i, j, irq_count;
+       int len, i, j;
        int isu_size, idu_size;
-       unsigned int *iranges, *opprop = NULL;
+       const unsigned int *iranges, *opprop = NULL;
        int oplen = 0;
        unsigned long opaddr;
        int na = 1;
-       unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
 
-       np = find_type_devices("open-pic");
+       np = of_find_node_by_type(NULL, "open-pic");
        if (np == NULL)
                return;
-       root = find_path_device("/");
+       root = of_find_node_by_path("/");
        if (root) {
-               opprop = (unsigned int *) get_property
-                       (root, "platform-open-pic", &oplen);
-               na = prom_n_addr_cells(root);
+               opprop = of_get_property(root, "platform-open-pic", &oplen);
+               na = of_n_addr_cells(root);
        }
        if (opprop && oplen >= na * sizeof(unsigned int)) {
                opaddr = opprop[na-1];  /* assume 32-bit */
                oplen /= na * sizeof(unsigned int);
        } else {
-               if (np->n_addrs == 0)
-                       return;
-               opaddr = np->addrs[0].address;
+               struct resource r;
+               if (of_address_to_resource(np, 0, &r)) {
+                       goto bail;
+               }
+               opaddr = r.start;
                oplen = 0;
        }
 
        printk(KERN_INFO "OpenPIC at %lx\n", opaddr);
 
-       irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
-       prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4);
-       /* i8259 cascade is always positive level */
-       init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE;
-
-       iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
+       iranges = of_get_property(np, "interrupt-ranges", &len);
        if (iranges == NULL)
                len = 0;        /* non-distributed mpic */
        else
@@ -384,7 +421,7 @@ static void __init chrp_find_openpic(void)
         */
        if (oplen < len) {
                printk(KERN_ERR "Insufficient addresses for distributed"
-                      " OpenPIC (%d < %d)\n", np->n_addrs, len);
+                      " OpenPIC (%d < %d)\n", oplen, len);
                len = oplen;
        }
 
@@ -398,15 +435,12 @@ static void __init chrp_find_openpic(void)
        if (len > 1)
                isu_size = iranges[3];
 
-       chrp_mpic = mpic_alloc(opaddr, MPIC_PRIMARY,
-                              isu_size, NUM_ISA_INTERRUPTS, irq_count,
-                              NR_IRQS - 4, init_senses, irq_count,
-                              " MPIC    ");
+       chrp_mpic = mpic_alloc(np, opaddr, MPIC_PRIMARY,
+                              isu_size, 0, " MPIC    ");
        if (chrp_mpic == NULL) {
                printk(KERN_ERR "Failed to allocate MPIC structure\n");
-               return;
+               goto bail;
        }
-
        j = na - 1;
        for (i = 1; i < len; ++i) {
                iranges += 2;
@@ -418,53 +452,103 @@ static void __init chrp_find_openpic(void)
        }
 
        mpic_init(chrp_mpic);
-       mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL);
+       ppc_md.get_irq = mpic_get_irq;
+ bail:
+       of_node_put(root);
+       of_node_put(np);
 }
 
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON)
 static struct irqaction xmon_irqaction = {
        .handler = xmon_irq,
-       .mask = CPU_MASK_NONE,
        .name = "XMON break",
 };
 #endif
 
-void __init chrp_init_IRQ(void)
+static void __init chrp_find_8259(void)
 {
-       struct device_node *np;
+       struct device_node *np, *pic = NULL;
        unsigned long chrp_int_ack = 0;
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
-       struct device_node *kbd;
-#endif
+       unsigned int cascade_irq;
 
-       for (np = find_devices("pci"); np != NULL; np = np->next) {
-               unsigned int *addrp = (unsigned int *)
-                       get_property(np, "8259-interrupt-acknowledge", NULL);
+       /* Look for cascade */
+       for_each_node_by_type(np, "interrupt-controller")
+               if (of_device_is_compatible(np, "chrp,iic")) {
+                       pic = np;
+                       break;
+               }
+       /* Ok, 8259 wasn't found. We need to handle the case where
+        * we have a pegasos that claims to be chrp but doesn't have
+        * a proper interrupt tree
+        */
+       if (pic == NULL && chrp_mpic != NULL) {
+               printk(KERN_ERR "i8259: Not found in device-tree"
+                      " assuming no legacy interrupts\n");
+               return;
+       }
+
+       /* Look for intack. In a perfect world, we would look for it on
+        * the ISA bus that holds the 8259 but heh... Works that way. If
+        * we ever see a problem, we can try to re-use the pSeries code here.
+        * Also, Pegasos-type platforms don't have a proper node to start
+        * from anyway
+        */
+       for_each_node_by_name(np, "pci") {
+               const unsigned int *addrp = of_get_property(np,
+                               "8259-interrupt-acknowledge", NULL);
 
                if (addrp == NULL)
                        continue;
-               chrp_int_ack = addrp[prom_n_addr_cells(np)-1];
+               chrp_int_ack = addrp[of_n_addr_cells(np)-1];
                break;
        }
+       of_node_put(np);
        if (np == NULL)
-               printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n");
+               printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
+                      " address, polling\n");
 
+       i8259_init(pic, chrp_int_ack);
+       if (ppc_md.get_irq == NULL) {
+               ppc_md.get_irq = i8259_irq;
+               irq_set_default_host(i8259_get_host());
+       }
+       if (chrp_mpic != NULL) {
+               cascade_irq = irq_of_parse_and_map(pic, 0);
+               if (cascade_irq == NO_IRQ)
+                       printk(KERN_ERR "i8259: failed to map cascade irq\n");
+               else
+                       irq_set_chained_handler(cascade_irq,
+                                               chrp_8259_cascade);
+       }
+}
+
+void __init chrp_init_IRQ(void)
+{
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON)
+       struct device_node *kbd;
+#endif
        chrp_find_openpic();
+       chrp_find_8259();
 
-       i8259_init(chrp_int_ack, 0);
+#ifdef CONFIG_SMP
+       /* Pegasos has no MPIC, those ops would make it crash. It might be an
+        * option to move setting them to after we probe the PIC though
+        */
+       if (chrp_mpic != NULL)
+               smp_ops = &chrp_smp_ops;
+#endif /* CONFIG_SMP */
 
        if (_chrp_type == _CHRP_Pegasos)
                ppc_md.get_irq        = i8259_irq;
-       else
-               ppc_md.get_irq        = mpic_get_irq;
 
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON)
        /* see if there is a keyboard in the device tree
           with a parent of type "adb" */
-       for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
+       for_each_node_by_name(kbd, "keyboard")
                if (kbd->parent && kbd->parent->type
                    && strcmp(kbd->parent->type, "adb") == 0)
                        break;
+       of_node_put(kbd);
        if (kbd)
                setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction);
 #endif
@@ -488,46 +572,36 @@ chrp_init2(void)
                ppc_md.progress("  Have fun!    ", 0x7777);
 }
 
-void __init chrp_init(void)
+static int __init chrp_probe(void)
 {
+       char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
+                                         "device_type", NULL);
+       if (dtype == NULL)
+               return 0;
+       if (strcmp(dtype, "chrp"))
+               return 0;
+
        ISA_DMA_THRESHOLD = ~0L;
        DMA_MODE_READ = 0x44;
        DMA_MODE_WRITE = 0x48;
-       isa_io_base = CHRP_ISA_IO_BASE;         /* default value */
-       ppc_do_canonicalize_irqs = 1;
-
-       /* Assume we have an 8259... */
-       __irq_offset_value = NUM_ISA_INTERRUPTS;
-
-       ppc_md.setup_arch     = chrp_setup_arch;
-       ppc_md.show_cpuinfo   = chrp_show_cpuinfo;
-
-       ppc_md.init_IRQ       = chrp_init_IRQ;
-       ppc_md.init           = chrp_init2;
 
-       ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
-
-       ppc_md.restart        = rtas_restart;
-       ppc_md.power_off      = rtas_power_off;
-       ppc_md.halt           = rtas_halt;
-
-       ppc_md.time_init      = chrp_time_init;
-       ppc_md.calibrate_decr = chrp_calibrate_decr;
-
-       /* this may get overridden with rtas routines later... */
-       ppc_md.set_rtc_time   = chrp_set_rtc_time;
-       ppc_md.get_rtc_time   = chrp_get_rtc_time;
-
-#ifdef CONFIG_SMP
-       smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
+       return 1;
 }
 
-#ifdef CONFIG_BOOTX_TEXT
-void
-btext_progress(char *s, unsigned short hex)
-{
-       btext_drawstring(s);
-       btext_drawstring("\n");
-}
-#endif /* CONFIG_BOOTX_TEXT */
+define_machine(chrp) {
+       .name                   = "CHRP",
+       .probe                  = chrp_probe,
+       .setup_arch             = chrp_setup_arch,
+       .init                   = chrp_init2,
+       .init_early             = chrp_init_early,
+       .show_cpuinfo           = chrp_show_cpuinfo,
+       .init_IRQ               = chrp_init_IRQ,
+       .restart                = rtas_restart,
+       .power_off              = rtas_power_off,
+       .halt                   = rtas_halt,
+       .time_init              = chrp_time_init,
+       .set_rtc_time           = chrp_set_rtc_time,
+       .get_rtc_time           = chrp_get_rtc_time,
+       .calibrate_decr         = generic_calibrate_decr,
+       .phys_mem_access_prot   = pci_phys_mem_access_prot,
+};