]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/powerpc/kernel/prom.c
[PATCH] powerpc: Merge signal.h
[karo-tx-linux.git] / arch / powerpc / kernel / prom.c
index c8d288457b4c966b0a9b0376ba24caa3b459c423..f645adb57534be04a39a2ed7718362b06359e812 100644 (file)
@@ -78,15 +78,13 @@ extern struct rtas_t rtas;
 extern struct lmb lmb;
 extern unsigned long klimit;
 
-static unsigned long memory_limit;
-
 static int __initdata dt_root_addr_cells;
 static int __initdata dt_root_size_cells;
 
 #ifdef CONFIG_PPC64
 static int __initdata iommu_is_off;
 int __initdata iommu_force_on;
-extern unsigned long tce_alloc_start, tce_alloc_end;
+unsigned long tce_alloc_start, tce_alloc_end;
 #endif
 
 typedef u32 cell_t;
@@ -110,9 +108,6 @@ struct device_node *of_chosen;
 struct device_node *dflt_interrupt_controller;
 int num_interrupt_controllers;
 
-u32 rtas_data;
-u32 rtas_entry;
-
 /*
  * Wrapper for allocating memory for various data that needs to be
  * attached to device nodes as they are processed at boot or when
@@ -299,16 +294,63 @@ static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictr
        return nintrc;
 }
 
+static unsigned char map_isa_senses[4] = {
+       IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE,
+       IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE,
+       IRQ_SENSE_EDGE  | IRQ_POLARITY_NEGATIVE,
+       IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE
+};
+
+static unsigned char map_mpic_senses[4] = {
+       IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE,
+       IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE,
+       /* 2 seems to be used for the 8259 cascade... */
+       IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE,
+       IRQ_SENSE_EDGE  | IRQ_POLARITY_NEGATIVE,
+};
+
 static int __devinit finish_node_interrupts(struct device_node *np,
                                            unsigned long *mem_start,
                                            int measure_only)
 {
        unsigned int *ints;
        int intlen, intrcells, intrcount;
-       int i, j, n;
+       int i, j, n, sense;
        unsigned int *irq, virq;
        struct device_node *ic;
 
+       if (num_interrupt_controllers == 0) {
+               /*
+                * Old machines just have a list of interrupt numbers
+                * and no interrupt-controller nodes.
+                */
+               ints = (unsigned int *) get_property(np, "AAPL,interrupts",
+                                                    &intlen);
+               /* XXX old interpret_pci_props looked in parent too */
+               /* XXX old interpret_macio_props looked for interrupts
+                  before AAPL,interrupts */
+               if (ints == NULL)
+                       ints = (unsigned int *) get_property(np, "interrupts",
+                                                            &intlen);
+               if (ints == NULL)
+                       return 0;
+
+               np->n_intrs = intlen / sizeof(unsigned int);
+               np->intrs = prom_alloc(np->n_intrs * sizeof(np->intrs[0]),
+                                      mem_start);
+               if (!np->intrs)
+                       return -ENOMEM;
+               if (measure_only)
+                       return 0;
+
+               for (i = 0; i < np->n_intrs; ++i) {
+                       np->intrs[i].line = *ints++;
+                       np->intrs[i].sense = IRQ_SENSE_LEVEL
+                               | IRQ_POLARITY_NEGATIVE;
+               }
+               return 0;
+       }
+
        ints = (unsigned int *) get_property(np, "interrupts", &intlen);
        if (ints == NULL)
                return 0;
@@ -331,19 +373,20 @@ static int __devinit finish_node_interrupts(struct device_node *np,
                /* don't map IRQ numbers under a cascaded 8259 controller */
                if (ic && device_is_compatible(ic, "chrp,iic")) {
                        np->intrs[intrcount].line = irq[0];
+                       sense = (n > 1)? (irq[1] & 3): 3;
+                       np->intrs[intrcount].sense = map_isa_senses[sense];
                } else {
-#ifdef CONFIG_PPC64
                        virq = virt_irq_create_mapping(irq[0]);
+#ifdef CONFIG_PPC64
                        if (virq == NO_IRQ) {
                                printk(KERN_CRIT "Could not allocate interrupt"
                                       " number for %s\n", np->full_name);
                                continue;
                        }
-                       virq = irq_offset_up(virq);
-#else
-                       virq = irq[0];
 #endif
-                       np->intrs[intrcount].line = virq;
+                       np->intrs[intrcount].line = irq_offset_up(virq);
+                       sense = (n > 1)? (irq[1] & 3): 1;
+                       np->intrs[intrcount].sense = map_mpic_senses[sense];
                }
 
 #ifdef CONFIG_PPC64
@@ -358,9 +401,6 @@ static int __devinit finish_node_interrupts(struct device_node *np,
                                break;
                }
 #endif
-               np->intrs[intrcount].sense = 1;
-               if (n > 1)
-                       np->intrs[intrcount].sense = irq[1];
                if (n > 2) {
                        printk("hmmm, got %d intr cells for %s:", n,
                               np->full_name);
@@ -684,10 +724,10 @@ static inline char *find_flat_dt_string(u32 offset)
  * used to extract the memory informations at boot before we can
  * unflatten the tree
  */
-static int __init scan_flat_dt(int (*it)(unsigned long node,
-                                        const char *uname, int depth,
-                                        void *data),
-                              void *data)
+int __init of_scan_flat_dt(int (*it)(unsigned long node,
+                                    const char *uname, int depth,
+                                    void *data),
+                          void *data)
 {
        unsigned long p = ((unsigned long)initial_boot_params) +
                initial_boot_params->off_dt_struct;
@@ -744,8 +784,8 @@ static int __init scan_flat_dt(int (*it)(unsigned long node,
  * This  function can be used within scan_flattened_dt callback to get
  * access to properties
  */
-static void* __init get_flat_dt_prop(unsigned long node, const char *name,
-                                    unsigned long *size)
+void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
+                                unsigned long *size)
 {
        unsigned long p = node;
 
@@ -1024,6 +1064,8 @@ void __init unflatten_device_tree(void)
 
        /* Get pointer to OF "/chosen" node for use everywhere */
        of_chosen = of_find_node_by_path("/chosen");
+       if (of_chosen == NULL)
+               of_chosen = of_find_node_by_path("/chosen@0");
 
        /* Retreive command line */
        if (of_chosen != NULL) {
@@ -1045,7 +1087,7 @@ void __init unflatten_device_tree(void)
 static int __init early_init_dt_scan_cpus(unsigned long node,
                                          const char *uname, int depth, void *data)
 {
-       char *type = get_flat_dt_prop(node, "device_type", NULL);
+       char *type = of_get_flat_dt_prop(node, "device_type", NULL);
        u32 *prop;
        unsigned long size = 0;
 
@@ -1053,46 +1095,34 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
        if (type == NULL || strcmp(type, "cpu") != 0)
                return 0;
 
-#ifdef CONFIG_PPC_PSERIES
-       /* On LPAR, look for the first ibm,pft-size property for the  hash table size
-        */
-       if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) {
-               u32 *pft_size;
-               pft_size = get_flat_dt_prop(node, "ibm,pft-size", NULL);
-               if (pft_size != NULL) {
-                       /* pft_size[0] is the NUMA CEC cookie */
-                       ppc64_pft_size = pft_size[1];
-               }
-       }
-#endif
-
-#ifdef CONFIG_PPC64
+       boot_cpuid = 0;
+       boot_cpuid_phys = 0;
        if (initial_boot_params && initial_boot_params->version >= 2) {
                /* version 2 of the kexec param format adds the phys cpuid
                 * of booted proc.
                 */
                boot_cpuid_phys = initial_boot_params->boot_cpuid_phys;
-               boot_cpuid = 0;
        } else {
-               /* Check if it's the boot-cpu, set it's hw index in paca now */
-               if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) {
-                       prop = get_flat_dt_prop(node, "reg", NULL);
-                       set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop);
-                       boot_cpuid_phys = get_hard_smp_processor_id(0);
+               /* Check if it's the boot-cpu, set it's hw index now */
+               if (of_get_flat_dt_prop(node,
+                                       "linux,boot-cpu", NULL) != NULL) {
+                       prop = of_get_flat_dt_prop(node, "reg", NULL);
+                       if (prop != NULL)
+                               boot_cpuid_phys = *prop;
                }
        }
-#endif
+       set_hard_smp_processor_id(0, boot_cpuid_phys);
 
 #ifdef CONFIG_ALTIVEC
        /* Check if we have a VMX and eventually update CPU features */
-       prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", &size);
+       prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", &size);
        if (prop && (*prop) > 0) {
                cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
                cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
        }
 
        /* Same goes for Apple's "altivec" property */
-       prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL);
+       prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL);
        if (prop) {
                cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
                cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
@@ -1105,7 +1135,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
         * this by looking at the size of the ibm,ppc-interrupt-server#s
         * property
         */
-       prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
+       prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
                                       &size);
        cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
        if (prop && ((size / sizeof(u32)) > 1))
@@ -1123,36 +1153,39 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
 
        DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
 
-       if (depth != 1 || strcmp(uname, "chosen") != 0)
+       if (depth != 1 ||
+           (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
                return 0;
 
        /* get platform type */
-       prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL);
+       prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL);
        if (prop == NULL)
                return 0;
 #ifdef CONFIG_PPC64
        systemcfg->platform = *prop;
 #else
+#ifdef CONFIG_PPC_MULTIPLATFORM
        _machine = *prop;
 #endif
+#endif
 
 #ifdef CONFIG_PPC64
        /* check if iommu is forced on or off */
-       if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
+       if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
                iommu_is_off = 1;
-       if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
+       if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
                iommu_force_on = 1;
 #endif
 
-       lprop = get_flat_dt_prop(node, "linux,memory-limit", NULL);
+       lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
        if (lprop)
                memory_limit = *lprop;
 
 #ifdef CONFIG_PPC64
-       lprop = get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
+       lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
        if (lprop)
                tce_alloc_start = *lprop;
-       lprop = get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
+       lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
        if (lprop)
                tce_alloc_end = *lprop;
 #endif
@@ -1164,9 +1197,9 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
        {
                u64 *basep, *entryp;
 
-               basep = get_flat_dt_prop(node, "linux,rtas-base", NULL);
-               entryp = get_flat_dt_prop(node, "linux,rtas-entry", NULL);
-               prop = get_flat_dt_prop(node, "linux,rtas-size", NULL);
+               basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
+               entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
+               prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL);
                if (basep && entryp && prop) {
                        rtas.base = *basep;
                        rtas.entry = *entryp;
@@ -1187,11 +1220,11 @@ static int __init early_init_dt_scan_root(unsigned long node,
        if (depth != 0)
                return 0;
 
-       prop = get_flat_dt_prop(node, "#size-cells", NULL);
+       prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
        dt_root_size_cells = (prop == NULL) ? 1 : *prop;
        DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
 
-       prop = get_flat_dt_prop(node, "#address-cells", NULL);
+       prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
        dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
        DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
        
@@ -1226,7 +1259,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
 static int __init early_init_dt_scan_memory(unsigned long node,
                                            const char *uname, int depth, void *data)
 {
-       char *type = get_flat_dt_prop(node, "device_type", NULL);
+       char *type = of_get_flat_dt_prop(node, "device_type", NULL);
        cell_t *reg, *endp;
        unsigned long l;
 
@@ -1234,13 +1267,13 @@ static int __init early_init_dt_scan_memory(unsigned long node,
        if (type == NULL || strcmp(type, "memory") != 0)
                return 0;
 
-       reg = (cell_t *)get_flat_dt_prop(node, "reg", &l);
+       reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
        if (reg == NULL)
                return 0;
 
        endp = reg + (l / sizeof(cell_t));
 
-       DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n",
+       DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
            uname, l, reg[0], reg[1], reg[2], reg[3]);
 
        while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
@@ -1298,12 +1331,12 @@ void __init early_init_devtree(void *params)
         * device-tree, including the platform type, initrd location and
         * size, TCE reserve, and more ...
         */
-       scan_flat_dt(early_init_dt_scan_chosen, NULL);
+       of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
 
        /* Scan memory nodes and rebuild LMBs */
        lmb_init();
-       scan_flat_dt(early_init_dt_scan_root, NULL);
-       scan_flat_dt(early_init_dt_scan_memory, NULL);
+       of_scan_flat_dt(early_init_dt_scan_root, NULL);
+       of_scan_flat_dt(early_init_dt_scan_memory, NULL);
        lmb_enforce_memory_limit(memory_limit);
        lmb_analyze();
 #ifdef CONFIG_PPC64
@@ -1318,10 +1351,10 @@ void __init early_init_devtree(void *params)
 
        DBG("Scanning CPUs ...\n");
 
-       /* Retreive hash table size from flattened tree plus other
-        * CPU related informations (altivec support, boot CPU ID, ...)
+       /* Retreive CPU related informations from the flat tree
+        * (altivec support, boot CPU ID, ...)
         */
-       scan_flat_dt(early_init_dt_scan_cpus, NULL);
+       of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
 
        DBG(" <- early_init_devtree()\n");
 }
@@ -1368,15 +1401,13 @@ void __init prom_get_irq_senses(unsigned char *senses, int off, int max)
        int i, j;
 
        /* default to level-triggered */
-       memset(senses, 1, max - off);
+       memset(senses, IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, max - off);
 
        for (np = allnodes; np != 0; np = np->allnext) {
                for (j = 0; j < np->n_intrs; j++) {
                        i = np->intrs[j].line;
                        if (i >= off && i < max)
-                               senses[i-off] = np->intrs[j].sense ?
-                                       IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE :
-                                       IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE;
+                               senses[i-off] = np->intrs[j].sense;
                }
        }
 }
@@ -1943,14 +1974,29 @@ EXPORT_SYMBOL(get_property);
 /*
  * Add a property to a node
  */
-void prom_add_property(struct device_node* np, struct property* prop)
+int prom_add_property(struct device_node* np, struct property* prop)
 {
-       struct property **next = &np->properties;
+       struct property **next;
 
        prop->next = NULL;      
-       while (*next)
+       write_lock(&devtree_lock);
+       next = &np->properties;
+       while (*next) {
+               if (strcmp(prop->name, (*next)->name) == 0) {
+                       /* duplicate ! don't insert it */
+                       write_unlock(&devtree_lock);
+                       return -1;
+               }
                next = &(*next)->next;
+       }
        *next = prop;
+       write_unlock(&devtree_lock);
+
+       /* try to add to proc as well if it was initialized */
+       if (np->pde)
+               proc_device_tree_add_prop(np->pde, prop);
+
+       return 0;
 }
 
 /* I quickly hacked that one, check against spec ! */
@@ -1971,6 +2017,7 @@ bus_space_to_resource_flags(unsigned int bus_space)
        }
 }
 
+#ifdef CONFIG_PCI
 static struct resource *find_parent_pci_resource(struct pci_dev* pdev,
                                                 struct address_range *range)
 {
@@ -2123,3 +2170,4 @@ int release_OF_resource(struct device_node *node, int index)
        return 0;
 }
 EXPORT_SYMBOL(release_OF_resource);
+#endif /* CONFIG_PCI */