sparc,leon: Added support for AMBAPP bus.
authorKonrad Eisele <konrad@gaisler.com>
Mon, 17 Aug 2009 00:13:32 +0000 (00:13 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 18 Aug 2009 01:32:10 +0000 (18:32 -0700)
The device is a AMBA bus if it is a child of prom node "ambapp" (AMBA
plug and play). Two functions
leon_trans_init() and leon_node_init() (defined in
sparc/kernel/leon_kernel.c) are called in the
prom_build_tree() path if CONFIG_SPARC_LEON is
defined. leon_node_init() will build up the device
tree using AMBA plug and play. Also: a extra check was addes to
prom_common.c:build_one_prop()
in case a rom-node is undefined which can happen for SPARC-LEON
because it creates only a minimum
nodes to emulate sparc behaviour.

Signed-off-by: Konrad Eisele <konrad@gaisler.com>
Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
arch/sparc/kernel/of_device_32.c
arch/sparc/kernel/prom_32.c
arch/sparc/kernel/prom_common.c

index 9039670..4c26eb5 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/irq.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <asm/leon.h>
+#include <asm/leon_amba.h>
 
 #include "of_device_common.h"
 
@@ -97,6 +99,35 @@ static unsigned long of_bus_sbus_get_flags(const u32 *addr, unsigned long flags)
        return IORESOURCE_MEM;
 }
 
+ /*
+ * AMBAPP bus specific translator
+ */
+
+static int of_bus_ambapp_match(struct device_node *np)
+{
+       return !strcmp(np->name, "ambapp");
+}
+
+static void of_bus_ambapp_count_cells(struct device_node *child,
+                                     int *addrc, int *sizec)
+{
+       if (addrc)
+               *addrc = 1;
+       if (sizec)
+               *sizec = 1;
+}
+
+static int of_bus_ambapp_map(u32 *addr, const u32 *range,
+                            int na, int ns, int pna)
+{
+       return of_bus_default_map(addr, range, na, ns, pna);
+}
+
+static unsigned long of_bus_ambapp_get_flags(const u32 *addr,
+                                            unsigned long flags)
+{
+       return IORESOURCE_MEM;
+}
 
 /*
  * Array of bus specific translators
@@ -121,6 +152,15 @@ static struct of_bus of_busses[] = {
                .map = of_bus_default_map,
                .get_flags = of_bus_sbus_get_flags,
        },
+       /* AMBA */
+       {
+               .name = "ambapp",
+               .addr_prop_name = "reg",
+               .match = of_bus_ambapp_match,
+               .count_cells = of_bus_ambapp_count_cells,
+               .map = of_bus_ambapp_map,
+               .get_flags = of_bus_ambapp_get_flags,
+       },
        /* Default */
        {
                .name = "default",
index fe43e80..0a37e8c 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <asm/prom.h>
 #include <asm/oplib.h>
+#include <asm/leon.h>
+#include <asm/leon_amba.h>
 
 #include "prom.h"
 
@@ -131,6 +133,35 @@ static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
                regs->which_io, regs->phys_addr);
 }
 
+/* "name:vendor:device@irq,addrlo" */
+static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct amba_prom_registers *regs; unsigned int *intr;
+       unsigned int *device, *vendor;
+       struct property *prop;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+       regs = prop->value;
+       prop = of_find_property(dp, "interrupts", NULL);
+       if (!prop)
+               return;
+       intr = prop->value;
+       prop = of_find_property(dp, "vendor", NULL);
+       if (!prop)
+               return;
+       vendor = prop->value;
+       prop = of_find_property(dp, "device", NULL);
+       if (!prop)
+               return;
+       device = prop->value;
+
+       sprintf(tmp_buf, "%s:%d:%d@%x,%x",
+               dp->name, *vendor, *device,
+               *intr, regs->phys_addr);
+}
+
 static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
 {
        struct device_node *parent = dp->parent;
@@ -143,6 +174,8 @@ static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
                        return sbus_path_component(dp, tmp_buf);
                if (!strcmp(parent->type, "ebus"))
                        return ebus_path_component(dp, tmp_buf);
+               if (!strcmp(parent->type, "ambapp"))
+                       return ambapp_path_component(dp, tmp_buf);
 
                /* "isa" is handled with platform naming */
        }
index 0fb5789..138910c 100644 (file)
 #include <linux/of.h>
 #include <asm/prom.h>
 #include <asm/oplib.h>
+#include <asm/leon.h>
 
 #include "prom.h"
 
+void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp);
+
 struct device_node *of_console_device;
 EXPORT_SYMBOL(of_console_device);
 
@@ -161,7 +164,7 @@ static struct property * __init build_one_prop(phandle node, char *prev,
                        name = prom_nextprop(node, prev, p->name);
                }
 
-               if (strlen(name) == 0) {
+               if (!name || strlen(name) == 0) {
                        tmp = p;
                        return NULL;
                }
@@ -242,7 +245,7 @@ static struct device_node * __init prom_create_node(phandle node,
        return dp;
 }
 
-static char * __init build_full_name(struct device_node *dp)
+char * __init build_full_name(struct device_node *dp)
 {
        int len, ourlen, plen;
        char *n;
@@ -289,6 +292,9 @@ static struct device_node * __init prom_build_tree(struct device_node *parent,
 
                dp->child = prom_build_tree(dp, prom_getchild(node), nextp);
 
+               if (prom_build_more)
+                       prom_build_more(dp, nextp);
+
                node = prom_getsibling(node);
        }