mirror of
https://github.com/torvalds/linux.git
synced 2024-12-02 09:01:34 +00:00
sparc,leon: Added support for AMBAPP bus.
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>
This commit is contained in:
parent
0fd7ef1fe0
commit
e63829de3d
@ -9,6 +9,8 @@
|
|||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
|
#include <asm/leon.h>
|
||||||
|
#include <asm/leon_amba.h>
|
||||||
|
|
||||||
#include "of_device_common.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;
|
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
|
* Array of bus specific translators
|
||||||
@ -121,6 +152,15 @@ static struct of_bus of_busses[] = {
|
|||||||
.map = of_bus_default_map,
|
.map = of_bus_default_map,
|
||||||
.get_flags = of_bus_sbus_get_flags,
|
.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 */
|
/* Default */
|
||||||
{
|
{
|
||||||
.name = "default",
|
.name = "default",
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include <asm/prom.h>
|
#include <asm/prom.h>
|
||||||
#include <asm/oplib.h>
|
#include <asm/oplib.h>
|
||||||
|
#include <asm/leon.h>
|
||||||
|
#include <asm/leon_amba.h>
|
||||||
|
|
||||||
#include "prom.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);
|
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)
|
static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
|
||||||
{
|
{
|
||||||
struct device_node *parent = dp->parent;
|
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);
|
return sbus_path_component(dp, tmp_buf);
|
||||||
if (!strcmp(parent->type, "ebus"))
|
if (!strcmp(parent->type, "ebus"))
|
||||||
return ebus_path_component(dp, tmp_buf);
|
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 */
|
/* "isa" is handled with platform naming */
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,12 @@
|
|||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <asm/prom.h>
|
#include <asm/prom.h>
|
||||||
#include <asm/oplib.h>
|
#include <asm/oplib.h>
|
||||||
|
#include <asm/leon.h>
|
||||||
|
|
||||||
#include "prom.h"
|
#include "prom.h"
|
||||||
|
|
||||||
|
void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp);
|
||||||
|
|
||||||
struct device_node *of_console_device;
|
struct device_node *of_console_device;
|
||||||
EXPORT_SYMBOL(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);
|
name = prom_nextprop(node, prev, p->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(name) == 0) {
|
if (!name || strlen(name) == 0) {
|
||||||
tmp = p;
|
tmp = p;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -242,7 +245,7 @@ static struct device_node * __init prom_create_node(phandle node,
|
|||||||
return dp;
|
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;
|
int len, ourlen, plen;
|
||||||
char *n;
|
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);
|
dp->child = prom_build_tree(dp, prom_getchild(node), nextp);
|
||||||
|
|
||||||
|
if (prom_build_more)
|
||||||
|
prom_build_more(dp, nextp);
|
||||||
|
|
||||||
node = prom_getsibling(node);
|
node = prom_getsibling(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user