From: Robert Reif <reif@earthlink.net>
To: sparclinux@vger.kernel.org
Subject: [RFC PATCH] use sparc64 version of of_device.c
Date: Mon, 15 Dec 2008 01:09:42 +0000 [thread overview]
Message-ID: <4945AE56.2040503@earthlink.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 497 bytes --]
This patch creates a combined kernel/of_device.c by starting with the
sparc64 version and adding #ifdefs and sparc32 code.
The only sparc64 difference is a %llx printk change.
The sparc32 changes are:
change int rlen to unsigned int rlen in build_one_resource
keep the sparc64 op->resources[] array size check
I know #ifdefs are ugly but the files were so similar.
Is this acceptable?
Boot tested on sparc32.
Compile tested on sparc64.
Signed-off-by: Robert Reif <reif@earthlink.net>
[-- Attachment #2: of_device.diff.txt --]
[-- Type: text/plain, Size: 23006 bytes --]
arch/sparc/kernel/Makefile | 2 +-
arch/sparc/kernel/{of_device_64.c => of_device.c} | 133 ++++-
arch/sparc/kernel/of_device_32.c | 627 ---------------------
3 files changed, 127 insertions(+), 635 deletions(-)
rename arch/sparc/kernel/{of_device_64.c => of_device.c} (87%)
delete mode 100644 arch/sparc/kernel/of_device_32.c
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 59aab6a..b9861a4 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -37,7 +37,7 @@ obj-y += una_asm_$(BITS).o
obj-$(CONFIG_SPARC32) += muldiv.o
obj-y += prom_common.o
obj-y += prom_$(BITS).o
-obj-y += of_device_$(BITS).o
+obj-y += of_device.o
obj-$(CONFIG_SPARC64) += prom_irqtrans.o
obj-$(CONFIG_SPARC64) += reboot.o
diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device.c
similarity index 87%
rename from arch/sparc/kernel/of_device_64.c
rename to arch/sparc/kernel/of_device.c
index 0f616ae..625d605 100644
--- a/arch/sparc/kernel/of_device_64.c
+++ b/arch/sparc/kernel/of_device.c
@@ -10,6 +10,7 @@
#include <linux/of_device.h>
#include <linux/of_platform.h>
+#ifdef CONFIG_SPARC64
void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name)
{
unsigned long ret = res->start + offset;
@@ -34,6 +35,7 @@ void of_iounmap(struct resource *res, void __iomem *base, unsigned long size)
release_region((unsigned long) base, size);
}
EXPORT_SYMBOL(of_iounmap);
+#endif
static int node_match(struct device *dev, void *data)
{
@@ -192,12 +194,15 @@ static unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long fla
static int of_bus_pci_match(struct device_node *np)
{
+#ifdef CONFIG_SPARC32
+ if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
+#else
if (!strcmp(np->name, "pci")) {
const char *model = of_get_property(np, "model", NULL);
if (model && !strcmp(model, "SUNW,simba"))
return 0;
-
+#endif
/* Do not do PCI specific frobbing if the
* PCI bridge lacks a ranges property. We
* want to pass it through up to the next
@@ -213,6 +218,7 @@ static int of_bus_pci_match(struct device_node *np)
return 0;
}
+#ifdef CONFIG_SPARC64
static int of_bus_simba_match(struct device_node *np)
{
const char *model = of_get_property(np, "model", NULL);
@@ -236,6 +242,7 @@ static int of_bus_simba_map(u32 *addr, const u32 *range,
{
return 0;
}
+#endif
static void of_bus_pci_count_cells(struct device_node *np,
int *addrc, int *sizec)
@@ -314,6 +321,22 @@ static void of_bus_sbus_count_cells(struct device_node *child,
*sizec = 1;
}
+#ifdef CONFIG_SPARC32
+static int of_bus_sbus_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_sbus_get_flags(const u32 *addr, unsigned long flags)
+{
+ return IORESOURCE_MEM;
+}
+#else
+#define of_bus_sbus_map of_bus_default_map
+#define of_bus_sbus_get_flags of_bus_default_get_flags
+#endif
+
+#ifdef CONFIG_SPARC64
/*
* FHC/Central bus specific translator.
*
@@ -330,6 +353,7 @@ static int of_bus_fhc_match(struct device_node *np)
}
#define of_bus_fhc_count_cells of_bus_sbus_count_cells
+#endif
/*
* Array of bus specific translators
@@ -345,6 +369,7 @@ static struct of_bus of_busses[] = {
.map = of_bus_pci_map,
.get_flags = of_bus_pci_get_flags,
},
+#ifdef CONFIG_SPARC64
/* SIMBA */
{
.name = "simba",
@@ -354,15 +379,17 @@ static struct of_bus of_busses[] = {
.map = of_bus_simba_map,
.get_flags = of_bus_pci_get_flags,
},
+#endif
/* SBUS */
{
.name = "sbus",
.addr_prop_name = "reg",
.match = of_bus_sbus_match,
.count_cells = of_bus_sbus_count_cells,
- .map = of_bus_default_map,
- .get_flags = of_bus_default_get_flags,
+ .map = of_bus_sbus_map,
+ .get_flags = of_bus_sbus_get_flags,
},
+#ifdef CONFIG_SPARC64
/* FHC */
{
.name = "fhc",
@@ -372,6 +399,7 @@ static struct of_bus of_busses[] = {
.map = of_bus_default_map,
.get_flags = of_bus_default_get_flags,
},
+#endif
/* Default */
{
.name = "default",
@@ -425,13 +453,14 @@ static int __init build_one_resource(struct device_node *parent,
return 0;
}
+#ifdef CONFIG_SPARC64
/* When we miss an I/O space match on PCI, just pass it up
* to the next PCI bridge and/or controller.
*/
if (!strcmp(bus->name, "pci") &&
(addr[0] & 0x03000000) == 0x01000000)
return 0;
-
+#endif
return 1;
}
@@ -456,13 +485,14 @@ static int __init use_1to1_mapping(struct device_node *pp)
!strcmp(pp->name, "lebuffer"))
return 0;
+#ifdef _CONFIG_SPARC64
/* Similarly for all PCI bridges, if we get this far
* it lacks a ranges property, and this will include
* cases like Simba.
*/
if (!strcmp(pp->name, "pci"))
return 0;
-
+#endif
return 1;
}
@@ -554,22 +584,29 @@ static void __init build_device_resources(struct of_device *op,
memset(r, 0, sizeof(*r));
if (of_resource_verbose)
- printk("%s reg[%d] -> %lx\n",
+ printk("%s reg[%d] -> %llx\n",
op->node->full_name, index,
- result);
+ (unsigned long long)result);
if (result != OF_BAD_ADDR) {
+#ifdef CONFIG_SPARC32
+ r->start = result & 0xffffffff;
+ r->end = result + size - 1;
+ r->flags = flags | ((result >> 32ULL) & 0xffUL);
+#else
if (tlb_type == hypervisor)
result &= 0x0fffffffffffffffUL;
r->start = result;
r->end = result + size - 1;
r->flags = flags;
+#endif
}
r->name = op->node->name;
}
}
+#ifdef CONFIG_SPARC64
static struct device_node * __init
apply_interrupt_map(struct device_node *dp, struct device_node *pp,
const u32 *imap, int imlen, const u32 *imask,
@@ -785,12 +822,17 @@ out:
return irq;
}
+#endif
static struct of_device * __init scan_one_device(struct device_node *dp,
struct device *parent)
{
struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL);
+#ifdef CONFIG_SPARC32
+ const struct linux_prom_irqs *intr;
+#else
const unsigned int *irq;
+#endif
struct dev_archdata *sd;
int len, i;
@@ -809,6 +851,79 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
if (op->portid == -1)
op->portid = of_getintprop_default(dp, "portid", -1);
+#ifdef CONFIG_SPARC32
+ intr = of_get_property(dp, "intr", &len);
+ if (intr) {
+ op->num_irqs = len / sizeof(struct linux_prom_irqs);
+ for (i = 0; i < op->num_irqs; i++)
+ op->irqs[i] = intr[i].pri;
+ } else {
+ const unsigned int *irq =
+ of_get_property(dp, "interrupts", &len);
+
+ if (irq) {
+ op->num_irqs = len / sizeof(unsigned int);
+ for (i = 0; i < op->num_irqs; i++)
+ op->irqs[i] = irq[i];
+ } else {
+ op->num_irqs = 0;
+ }
+ }
+ if (sparc_cpu_model == sun4d) {
+ static int pil_to_sbus[] = {
+ 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
+ };
+ struct device_node *io_unit, *sbi = dp->parent;
+ const struct linux_prom_registers *regs;
+ int board, slot;
+
+ while (sbi) {
+ if (!strcmp(sbi->name, "sbi"))
+ break;
+
+ sbi = sbi->parent;
+ }
+ if (!sbi)
+ goto build_resources;
+
+ regs = of_get_property(dp, "reg", NULL);
+ if (!regs)
+ goto build_resources;
+
+ slot = regs->which_io;
+
+ /* If SBI's parent is not io-unit or the io-unit lacks
+ * a "board#" property, something is very wrong.
+ */
+ if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
+ printk("%s: Error, parent is not io-unit.\n",
+ sbi->full_name);
+ goto build_resources;
+ }
+ io_unit = sbi->parent;
+ board = of_getintprop_default(io_unit, "board#", -1);
+ if (board == -1) {
+ printk("%s: Error, lacks board# property.\n",
+ io_unit->full_name);
+ goto build_resources;
+ }
+
+ for (i = 0; i < op->num_irqs; i++) {
+ int this_irq = op->irqs[i];
+ int sbusl = pil_to_sbus[this_irq];
+
+ if (sbusl)
+ this_irq = (((board + 1) << 5) +
+ (sbusl << 2) +
+ slot);
+
+ op->irqs[i] = this_irq;
+ }
+ }
+
+build_resources:
+ build_device_resources(op, parent);
+#else
irq = of_get_property(dp, "interrupts", &len);
if (irq) {
memcpy(op->irqs, irq, len);
@@ -826,8 +941,10 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
}
build_device_resources(op, parent);
+
for (i = 0; i < op->num_irqs; i++)
op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]);
+#endif
op->dev.parent = parent;
op->dev.bus = &of_platform_bus_type;
@@ -890,8 +1007,10 @@ static int __init of_debug(char *str)
get_option(&str, &val);
if (val & 1)
of_resource_verbose = 1;
+#ifdef CONFIG_SPARC64
if (val & 2)
of_irq_verbose = 1;
+#endif
return 1;
}
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c
deleted file mode 100644
index 0a83bd7..0000000
--- a/arch/sparc/kernel/of_device_32.c
+++ /dev/null
@@ -1,627 +0,0 @@
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/of.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mod_devicetable.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-
-static int node_match(struct device *dev, void *data)
-{
- struct of_device *op = to_of_device(dev);
- struct device_node *dp = data;
-
- return (op->node == dp);
-}
-
-struct of_device *of_find_device_by_node(struct device_node *dp)
-{
- struct device *dev = bus_find_device(&of_platform_bus_type, NULL,
- dp, node_match);
-
- if (dev)
- return to_of_device(dev);
-
- return NULL;
-}
-EXPORT_SYMBOL(of_find_device_by_node);
-
-unsigned int irq_of_parse_and_map(struct device_node *node, int index)
-{
- struct of_device *op = of_find_device_by_node(node);
-
- if (!op || index >= op->num_irqs)
- return 0;
-
- return op->irqs[index];
-}
-EXPORT_SYMBOL(irq_of_parse_and_map);
-
-/* Take the archdata values for IOMMU, STC, and HOSTDATA found in
- * BUS and propagate to all child of_device objects.
- */
-void of_propagate_archdata(struct of_device *bus)
-{
- struct dev_archdata *bus_sd = &bus->dev.archdata;
- struct device_node *bus_dp = bus->node;
- struct device_node *dp;
-
- for (dp = bus_dp->child; dp; dp = dp->sibling) {
- struct of_device *op = of_find_device_by_node(dp);
-
- op->dev.archdata.iommu = bus_sd->iommu;
- op->dev.archdata.stc = bus_sd->stc;
- op->dev.archdata.host_controller = bus_sd->host_controller;
- op->dev.archdata.numa_node = bus_sd->numa_node;
-
- if (dp->child)
- of_propagate_archdata(op);
- }
-}
-
-struct bus_type of_platform_bus_type;
-EXPORT_SYMBOL(of_platform_bus_type);
-
-static inline u64 of_read_addr(const u32 *cell, int size)
-{
- u64 r = 0;
- while (size--)
- r = (r << 32) | *(cell++);
- return r;
-}
-
-static void __init get_cells(struct device_node *dp,
- int *addrc, int *sizec)
-{
- if (addrc)
- *addrc = of_n_addr_cells(dp);
- if (sizec)
- *sizec = of_n_size_cells(dp);
-}
-
-/* Max address size we deal with */
-#define OF_MAX_ADDR_CELLS 4
-
-struct of_bus {
- const char *name;
- const char *addr_prop_name;
- int (*match)(struct device_node *parent);
- void (*count_cells)(struct device_node *child,
- int *addrc, int *sizec);
- int (*map)(u32 *addr, const u32 *range,
- int na, int ns, int pna);
- unsigned long (*get_flags)(const u32 *addr, unsigned long);
-};
-
-/*
- * Default translator (generic bus)
- */
-
-static void of_bus_default_count_cells(struct device_node *dev,
- int *addrc, int *sizec)
-{
- get_cells(dev, addrc, sizec);
-}
-
-/* Make sure the least significant 64-bits are in-range. Even
- * for 3 or 4 cell values it is a good enough approximation.
- */
-static int of_out_of_range(const u32 *addr, const u32 *base,
- const u32 *size, int na, int ns)
-{
- u64 a = of_read_addr(addr, na);
- u64 b = of_read_addr(base, na);
-
- if (a < b)
- return 1;
-
- b += of_read_addr(size, ns);
- if (a >= b)
- return 1;
-
- return 0;
-}
-
-static int of_bus_default_map(u32 *addr, const u32 *range,
- int na, int ns, int pna)
-{
- u32 result[OF_MAX_ADDR_CELLS];
- int i;
-
- if (ns > 2) {
- printk("of_device: Cannot handle size cells (%d) > 2.", ns);
- return -EINVAL;
- }
-
- if (of_out_of_range(addr, range, range + na + pna, na, ns))
- return -EINVAL;
-
- /* Start with the parent range base. */
- memcpy(result, range + na, pna * 4);
-
- /* Add in the child address offset. */
- for (i = 0; i < na; i++)
- result[pna - 1 - i] +=
- (addr[na - 1 - i] -
- range[na - 1 - i]);
-
- memcpy(addr, result, pna * 4);
-
- return 0;
-}
-
-static unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long flags)
-{
- if (flags)
- return flags;
- return IORESOURCE_MEM;
-}
-
-/*
- * PCI bus specific translator
- */
-
-static int of_bus_pci_match(struct device_node *np)
-{
- if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
- /* Do not do PCI specific frobbing if the
- * PCI bridge lacks a ranges property. We
- * want to pass it through up to the next
- * parent as-is, not with the PCI translate
- * method which chops off the top address cell.
- */
- if (!of_find_property(np, "ranges", NULL))
- return 0;
-
- return 1;
- }
-
- return 0;
-}
-
-static void of_bus_pci_count_cells(struct device_node *np,
- int *addrc, int *sizec)
-{
- if (addrc)
- *addrc = 3;
- if (sizec)
- *sizec = 2;
-}
-
-static int of_bus_pci_map(u32 *addr, const u32 *range,
- int na, int ns, int pna)
-{
- u32 result[OF_MAX_ADDR_CELLS];
- int i;
-
- /* Check address type match */
- if ((addr[0] ^ range[0]) & 0x03000000)
- return -EINVAL;
-
- if (of_out_of_range(addr + 1, range + 1, range + na + pna,
- na - 1, ns))
- return -EINVAL;
-
- /* Start with the parent range base. */
- memcpy(result, range + na, pna * 4);
-
- /* Add in the child address offset, skipping high cell. */
- for (i = 0; i < na - 1; i++)
- result[pna - 1 - i] +=
- (addr[na - 1 - i] -
- range[na - 1 - i]);
-
- memcpy(addr, result, pna * 4);
-
- return 0;
-}
-
-static unsigned long of_bus_pci_get_flags(const u32 *addr, unsigned long flags)
-{
- u32 w = addr[0];
-
- /* For PCI, we override whatever child busses may have used. */
- flags = 0;
- switch((w >> 24) & 0x03) {
- case 0x01:
- flags |= IORESOURCE_IO;
- break;
-
- case 0x02: /* 32 bits */
- case 0x03: /* 64 bits */
- flags |= IORESOURCE_MEM;
- break;
- }
- if (w & 0x40000000)
- flags |= IORESOURCE_PREFETCH;
- return flags;
-}
-
-/*
- * SBUS bus specific translator
- */
-
-static int of_bus_sbus_match(struct device_node *np)
-{
- return !strcmp(np->name, "sbus") ||
- !strcmp(np->name, "sbi");
-}
-
-static void of_bus_sbus_count_cells(struct device_node *child,
- int *addrc, int *sizec)
-{
- if (addrc)
- *addrc = 2;
- if (sizec)
- *sizec = 1;
-}
-
-static int of_bus_sbus_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_sbus_get_flags(const u32 *addr, unsigned long flags)
-{
- return IORESOURCE_MEM;
-}
-
-
-/*
- * Array of bus specific translators
- */
-
-static struct of_bus of_busses[] = {
- /* PCI */
- {
- .name = "pci",
- .addr_prop_name = "assigned-addresses",
- .match = of_bus_pci_match,
- .count_cells = of_bus_pci_count_cells,
- .map = of_bus_pci_map,
- .get_flags = of_bus_pci_get_flags,
- },
- /* SBUS */
- {
- .name = "sbus",
- .addr_prop_name = "reg",
- .match = of_bus_sbus_match,
- .count_cells = of_bus_sbus_count_cells,
- .map = of_bus_sbus_map,
- .get_flags = of_bus_sbus_get_flags,
- },
- /* Default */
- {
- .name = "default",
- .addr_prop_name = "reg",
- .match = NULL,
- .count_cells = of_bus_default_count_cells,
- .map = of_bus_default_map,
- .get_flags = of_bus_default_get_flags,
- },
-};
-
-static struct of_bus *of_match_bus(struct device_node *np)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(of_busses); i ++)
- if (!of_busses[i].match || of_busses[i].match(np))
- return &of_busses[i];
- BUG();
- return NULL;
-}
-
-static int __init build_one_resource(struct device_node *parent,
- struct of_bus *bus,
- struct of_bus *pbus,
- u32 *addr,
- int na, int ns, int pna)
-{
- const u32 *ranges;
- unsigned int rlen;
- int rone;
-
- ranges = of_get_property(parent, "ranges", &rlen);
- if (ranges == NULL || rlen == 0) {
- u32 result[OF_MAX_ADDR_CELLS];
- int i;
-
- memset(result, 0, pna * 4);
- for (i = 0; i < na; i++)
- result[pna - 1 - i] =
- addr[na - 1 - i];
-
- memcpy(addr, result, pna * 4);
- return 0;
- }
-
- /* Now walk through the ranges */
- rlen /= 4;
- rone = na + pna + ns;
- for (; rlen >= rone; rlen -= rone, ranges += rone) {
- if (!bus->map(addr, ranges, na, ns, pna))
- return 0;
- }
-
- return 1;
-}
-
-static int __init use_1to1_mapping(struct device_node *pp)
-{
- /* If we have a ranges property in the parent, use it. */
- if (of_find_property(pp, "ranges", NULL) != NULL)
- return 0;
-
- /* Some SBUS devices use intermediate nodes to express
- * hierarchy within the device itself. These aren't
- * real bus nodes, and don't have a 'ranges' property.
- * But, we should still pass the translation work up
- * to the SBUS itself.
- */
- if (!strcmp(pp->name, "dma") ||
- !strcmp(pp->name, "espdma") ||
- !strcmp(pp->name, "ledma") ||
- !strcmp(pp->name, "lebuffer"))
- return 0;
-
- return 1;
-}
-
-static int of_resource_verbose;
-
-static void __init build_device_resources(struct of_device *op,
- struct device *parent)
-{
- struct of_device *p_op;
- struct of_bus *bus;
- int na, ns;
- int index, num_reg;
- const void *preg;
-
- if (!parent)
- return;
-
- p_op = to_of_device(parent);
- bus = of_match_bus(p_op->node);
- bus->count_cells(op->node, &na, &ns);
-
- preg = of_get_property(op->node, bus->addr_prop_name, &num_reg);
- if (!preg || num_reg == 0)
- return;
-
- /* Convert to num-cells. */
- num_reg /= 4;
-
- /* Conver to num-entries. */
- num_reg /= na + ns;
-
- for (index = 0; index < num_reg; index++) {
- struct resource *r = &op->resource[index];
- u32 addr[OF_MAX_ADDR_CELLS];
- const u32 *reg = (preg + (index * ((na + ns) * 4)));
- struct device_node *dp = op->node;
- struct device_node *pp = p_op->node;
- struct of_bus *pbus, *dbus;
- u64 size, result = OF_BAD_ADDR;
- unsigned long flags;
- int dna, dns;
- int pna, pns;
-
- size = of_read_addr(reg + na, ns);
-
- memcpy(addr, reg, na * 4);
-
- flags = bus->get_flags(reg, 0);
-
- if (use_1to1_mapping(pp)) {
- result = of_read_addr(addr, na);
- goto build_res;
- }
-
- dna = na;
- dns = ns;
- dbus = bus;
-
- while (1) {
- dp = pp;
- pp = dp->parent;
- if (!pp) {
- result = of_read_addr(addr, dna);
- break;
- }
-
- pbus = of_match_bus(pp);
- pbus->count_cells(dp, &pna, &pns);
-
- if (build_one_resource(dp, dbus, pbus, addr,
- dna, dns, pna))
- break;
-
- flags = pbus->get_flags(addr, flags);
-
- dna = pna;
- dns = pns;
- dbus = pbus;
- }
-
- build_res:
- memset(r, 0, sizeof(*r));
-
- if (of_resource_verbose)
- printk("%s reg[%d] -> %llx\n",
- op->node->full_name, index,
- result);
-
- if (result != OF_BAD_ADDR) {
- r->start = result & 0xffffffff;
- r->end = result + size - 1;
- r->flags = flags | ((result >> 32ULL) & 0xffUL);
- }
- r->name = op->node->name;
- }
-}
-
-static struct of_device * __init scan_one_device(struct device_node *dp,
- struct device *parent)
-{
- struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL);
- const struct linux_prom_irqs *intr;
- struct dev_archdata *sd;
- int len, i;
-
- if (!op)
- return NULL;
-
- sd = &op->dev.archdata;
- sd->prom_node = dp;
- sd->op = op;
-
- op->node = dp;
-
- op->clock_freq = of_getintprop_default(dp, "clock-frequency",
- (25*1000*1000));
- op->portid = of_getintprop_default(dp, "upa-portid", -1);
- if (op->portid == -1)
- op->portid = of_getintprop_default(dp, "portid", -1);
-
- intr = of_get_property(dp, "intr", &len);
- if (intr) {
- op->num_irqs = len / sizeof(struct linux_prom_irqs);
- for (i = 0; i < op->num_irqs; i++)
- op->irqs[i] = intr[i].pri;
- } else {
- const unsigned int *irq =
- of_get_property(dp, "interrupts", &len);
-
- if (irq) {
- op->num_irqs = len / sizeof(unsigned int);
- for (i = 0; i < op->num_irqs; i++)
- op->irqs[i] = irq[i];
- } else {
- op->num_irqs = 0;
- }
- }
- if (sparc_cpu_model == sun4d) {
- static int pil_to_sbus[] = {
- 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
- };
- struct device_node *io_unit, *sbi = dp->parent;
- const struct linux_prom_registers *regs;
- int board, slot;
-
- while (sbi) {
- if (!strcmp(sbi->name, "sbi"))
- break;
-
- sbi = sbi->parent;
- }
- if (!sbi)
- goto build_resources;
-
- regs = of_get_property(dp, "reg", NULL);
- if (!regs)
- goto build_resources;
-
- slot = regs->which_io;
-
- /* If SBI's parent is not io-unit or the io-unit lacks
- * a "board#" property, something is very wrong.
- */
- if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
- printk("%s: Error, parent is not io-unit.\n",
- sbi->full_name);
- goto build_resources;
- }
- io_unit = sbi->parent;
- board = of_getintprop_default(io_unit, "board#", -1);
- if (board == -1) {
- printk("%s: Error, lacks board# property.\n",
- io_unit->full_name);
- goto build_resources;
- }
-
- for (i = 0; i < op->num_irqs; i++) {
- int this_irq = op->irqs[i];
- int sbusl = pil_to_sbus[this_irq];
-
- if (sbusl)
- this_irq = (((board + 1) << 5) +
- (sbusl << 2) +
- slot);
-
- op->irqs[i] = this_irq;
- }
- }
-
-build_resources:
- build_device_resources(op, parent);
-
- op->dev.parent = parent;
- op->dev.bus = &of_platform_bus_type;
- if (!parent)
- dev_set_name(&op->dev, "root");
- else
- dev_set_name(&op->dev, "%08x", dp->node);
-
- if (of_device_register(op)) {
- printk("%s: Could not register of device.\n",
- dp->full_name);
- kfree(op);
- op = NULL;
- }
-
- return op;
-}
-
-static void __init scan_tree(struct device_node *dp, struct device *parent)
-{
- while (dp) {
- struct of_device *op = scan_one_device(dp, parent);
-
- if (op)
- scan_tree(dp->child, &op->dev);
-
- dp = dp->sibling;
- }
-}
-
-static void __init scan_of_devices(void)
-{
- struct device_node *root = of_find_node_by_path("/");
- struct of_device *parent;
-
- parent = scan_one_device(root, NULL);
- if (!parent)
- return;
-
- scan_tree(root->child, &parent->dev);
-}
-
-static int __init of_bus_driver_init(void)
-{
- int err;
-
- err = of_bus_type_init(&of_platform_bus_type, "of");
- if (!err)
- scan_of_devices();
-
- return err;
-}
-
-postcore_initcall(of_bus_driver_init);
-
-static int __init of_debug(char *str)
-{
- int val = 0;
-
- get_option(&str, &val);
- if (val & 1)
- of_resource_verbose = 1;
- return 1;
-}
-
-__setup("of_debug=", of_debug);
next reply other threads:[~2008-12-15 1:09 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-12-15 1:09 Robert Reif [this message]
2008-12-15 18:52 ` [RFC PATCH] use sparc64 version of of_device.c Sam Ravnborg
2008-12-15 22:52 ` David Miller
2008-12-15 22:57 ` Julian Calaby
2008-12-21 20:47 ` Sam Ravnborg
2009-01-01 7:10 ` Robert Reif
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4945AE56.2040503@earthlink.net \
--to=reif@earthlink.net \
--cc=sparclinux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.