All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnd Bergmann <arnd@arndb.de>
To: Paul Mackerras <paulus@samba.org>
Cc: Arnd Bergmann <arnd.bergmann@de.ibm.com>,
	linuxppc-dev@ozlabs.org, cbe-oss-dev@ozlabs.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 10/14] spufs: support new OF device tree format
Date: Wed, 04 Oct 2006 17:26:20 +0200	[thread overview]
Message-ID: <20061004161507.554879000@arndb.de> (raw)
In-Reply-To: 20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com

The properties we used traditionally in the device tree
are somewhat nonstandard, this adds support for a more
conventional format using 'interrupts' and 'reg'
properties.

The interrupts are specified in three cells (class 0,
1 and 2) and registered at the interrupt-parent.

The reg property contains either three or four register
areas in the order 'local-store', 'problem', 'priv2',
and 'priv1', so the priv1 one can be left out in
case of hypervisor driven systems that access these
through hcalls.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

Index: linux-2.6/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spu_base.c
+++ linux-2.6/arch/powerpc/platforms/cell/spu_base.c
@@ -25,11 +25,13 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <linux/poll.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
 
+#include <asm/firmware.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <linux/mutex.h>
@@ -576,7 +578,7 @@ static void spu_unmap(struct spu *spu)
 }
 
 /* This function shall be abstracted for HV platforms */
-static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
+static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np)
 {
 	unsigned int isrc;
 	const u32 *tmp;
@@ -600,7 +602,7 @@ static int __init spu_map_interrupts(str
 	return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
 }
 
-static int __init spu_map_device(struct spu *spu, struct device_node *node)
+static int __init spu_map_device_old(struct spu *spu, struct device_node *node)
 {
 	const char *prop;
 	int ret;
@@ -645,6 +647,88 @@ out:
 	return ret;
 }
 
+static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
+{
+	struct of_irq oirq;
+	int ret;
+	int i;
+
+	for (i=0; i < 3; i++) {
+		ret = of_irq_map_one(np, i, &oirq);
+		if (ret)
+			goto err;
+
+		ret = -EINVAL;
+		spu->irqs[i] = irq_create_of_mapping(oirq.controller,
+					oirq.specifier, oirq.size);
+		if (spu->irqs[i] == NO_IRQ)
+			goto err;
+	}
+	return 0;
+
+err:
+	pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, spu->name);
+	for (; i >= 0; i--) {
+		if (spu->irqs[i] != NO_IRQ)
+			irq_dispose_mapping(spu->irqs[i]);
+	}
+	return ret;
+}
+
+static int spu_map_resource(struct device_node *node, int nr,
+		void __iomem** virt, unsigned long *phys)
+{
+	struct resource resource = { };
+	int ret;
+
+	ret = of_address_to_resource(node, 0, &resource);
+	if (ret)
+		goto out;
+
+	if (phys)
+		*phys = resource.start;
+	*virt = ioremap(resource.start, resource.end - resource.start);
+	if (!*virt)
+		ret = -EINVAL;
+
+out:
+	return ret;
+}
+
+static int __init spu_map_device(struct spu *spu, struct device_node *node)
+{
+	int ret = -ENODEV;
+	spu->name = get_property(node, "name", NULL);
+	if (!spu->name)
+		goto out;
+
+	ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store,
+					&spu->local_store_phys);
+	if (ret)
+		goto out;
+	ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem,
+					&spu->problem_phys);
+	if (ret)
+		goto out_unmap;
+	ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2,
+					NULL);
+	if (ret)
+		goto out_unmap;
+
+	if (!firmware_has_feature(FW_FEATURE_LPAR))
+		ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1,
+					NULL);
+	if (ret)
+		goto out_unmap;
+	return 0;
+
+out_unmap:
+	spu_unmap(spu);
+out:
+	pr_debug("failed to map spe %s: %d\n", spu->name, ret);
+	return ret;
+}
+
 struct sysdev_class spu_sysdev_class = {
 	set_kset_name("spu")
 };
@@ -698,6 +782,9 @@ static int __init create_spu(struct devi
 		goto out;
 
 	ret = spu_map_device(spu, spe);
+	/* try old method */
+	if (ret)
+		ret = spu_map_device_old(spu, spe);
 	if (ret)
 		goto out_free;
 
@@ -707,6 +794,8 @@ static int __init create_spu(struct devi
 		spu->nid = 0;
 	ret = spu_map_interrupts(spu, spe);
 	if (ret)
+		ret = spu_map_interrupts_old(spu, spe);
+	if (ret)
 		goto out_unmap;
 	spin_lock_init(&spu->register_lock);
 	spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
@@ -716,7 +805,7 @@ static int __init create_spu(struct devi
 	spu->number = number++;
 	ret = spu_request_irqs(spu);
 	if (ret)
-		goto out_unmap;
+		goto out_unlock;
 
 	ret = spu_create_sysdev(spu);
 	if (ret)
@@ -732,9 +821,9 @@ static int __init create_spu(struct devi
 
 out_free_irqs:
 	spu_free_irqs(spu);
-
-out_unmap:
+out_unlock:
 	mutex_unlock(&spu_mutex);
+out_unmap:
 	spu_unmap(spu);
 out_free:
 	kfree(spu);

--

WARNING: multiple messages have this Message-ID (diff)
From: Arnd Bergmann <arnd@arndb.de>
To: Paul Mackerras <paulus@samba.org>
Cc: cbe-oss-dev@ozlabs.org, linuxppc-dev@ozlabs.org,
	linux-kernel@vger.kernel.org, benh@kernel.crashing.org,
	Arnd Bergmann <arnd.bergmann@de.ibm.com>
Subject: [PATCH 10/14] spufs: support new OF device tree format
Date: Wed, 04 Oct 2006 17:26:20 +0200	[thread overview]
Message-ID: <20061004161507.554879000@arndb.de> (raw)
In-Reply-To: 20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com

[-- Attachment #1: spufs-new-devnode.diff --]
[-- Type: text/plain, Size: 4600 bytes --]

The properties we used traditionally in the device tree
are somewhat nonstandard, this adds support for a more
conventional format using 'interrupts' and 'reg'
properties.

The interrupts are specified in three cells (class 0,
1 and 2) and registered at the interrupt-parent.

The reg property contains either three or four register
areas in the order 'local-store', 'problem', 'priv2',
and 'priv1', so the priv1 one can be left out in
case of hypervisor driven systems that access these
through hcalls.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

Index: linux-2.6/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spu_base.c
+++ linux-2.6/arch/powerpc/platforms/cell/spu_base.c
@@ -25,11 +25,13 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <linux/poll.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
 
+#include <asm/firmware.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <linux/mutex.h>
@@ -576,7 +578,7 @@ static void spu_unmap(struct spu *spu)
 }
 
 /* This function shall be abstracted for HV platforms */
-static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
+static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np)
 {
 	unsigned int isrc;
 	const u32 *tmp;
@@ -600,7 +602,7 @@ static int __init spu_map_interrupts(str
 	return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
 }
 
-static int __init spu_map_device(struct spu *spu, struct device_node *node)
+static int __init spu_map_device_old(struct spu *spu, struct device_node *node)
 {
 	const char *prop;
 	int ret;
@@ -645,6 +647,88 @@ out:
 	return ret;
 }
 
+static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
+{
+	struct of_irq oirq;
+	int ret;
+	int i;
+
+	for (i=0; i < 3; i++) {
+		ret = of_irq_map_one(np, i, &oirq);
+		if (ret)
+			goto err;
+
+		ret = -EINVAL;
+		spu->irqs[i] = irq_create_of_mapping(oirq.controller,
+					oirq.specifier, oirq.size);
+		if (spu->irqs[i] == NO_IRQ)
+			goto err;
+	}
+	return 0;
+
+err:
+	pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, spu->name);
+	for (; i >= 0; i--) {
+		if (spu->irqs[i] != NO_IRQ)
+			irq_dispose_mapping(spu->irqs[i]);
+	}
+	return ret;
+}
+
+static int spu_map_resource(struct device_node *node, int nr,
+		void __iomem** virt, unsigned long *phys)
+{
+	struct resource resource = { };
+	int ret;
+
+	ret = of_address_to_resource(node, 0, &resource);
+	if (ret)
+		goto out;
+
+	if (phys)
+		*phys = resource.start;
+	*virt = ioremap(resource.start, resource.end - resource.start);
+	if (!*virt)
+		ret = -EINVAL;
+
+out:
+	return ret;
+}
+
+static int __init spu_map_device(struct spu *spu, struct device_node *node)
+{
+	int ret = -ENODEV;
+	spu->name = get_property(node, "name", NULL);
+	if (!spu->name)
+		goto out;
+
+	ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store,
+					&spu->local_store_phys);
+	if (ret)
+		goto out;
+	ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem,
+					&spu->problem_phys);
+	if (ret)
+		goto out_unmap;
+	ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2,
+					NULL);
+	if (ret)
+		goto out_unmap;
+
+	if (!firmware_has_feature(FW_FEATURE_LPAR))
+		ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1,
+					NULL);
+	if (ret)
+		goto out_unmap;
+	return 0;
+
+out_unmap:
+	spu_unmap(spu);
+out:
+	pr_debug("failed to map spe %s: %d\n", spu->name, ret);
+	return ret;
+}
+
 struct sysdev_class spu_sysdev_class = {
 	set_kset_name("spu")
 };
@@ -698,6 +782,9 @@ static int __init create_spu(struct devi
 		goto out;
 
 	ret = spu_map_device(spu, spe);
+	/* try old method */
+	if (ret)
+		ret = spu_map_device_old(spu, spe);
 	if (ret)
 		goto out_free;
 
@@ -707,6 +794,8 @@ static int __init create_spu(struct devi
 		spu->nid = 0;
 	ret = spu_map_interrupts(spu, spe);
 	if (ret)
+		ret = spu_map_interrupts_old(spu, spe);
+	if (ret)
 		goto out_unmap;
 	spin_lock_init(&spu->register_lock);
 	spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
@@ -716,7 +805,7 @@ static int __init create_spu(struct devi
 	spu->number = number++;
 	ret = spu_request_irqs(spu);
 	if (ret)
-		goto out_unmap;
+		goto out_unlock;
 
 	ret = spu_create_sysdev(spu);
 	if (ret)
@@ -732,9 +821,9 @@ static int __init create_spu(struct devi
 
 out_free_irqs:
 	spu_free_irqs(spu);
-
-out_unmap:
+out_unlock:
 	mutex_unlock(&spu_mutex);
+out_unmap:
 	spu_unmap(spu);
 out_free:
 	kfree(spu);

--


  parent reply	other threads:[~2006-10-04 15:26 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-10-04 15:26 [PATCH 00/14] spufs/cell updates for 2.6.19 Arnd Bergmann
2006-10-04 15:26 ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 01/14] spufs: cell spu problem state mapping updates Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 02/14] spufs: scheduler support for NUMA Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 03/14] spufs: fix context switch during page fault Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 04/14] spufs: implement error event delivery to user space Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 05/14] spufs: Add infrastructure needed for gang scheduling Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 06/14] spufs: use correct pg_prot for mapping spu LS Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 07/14] spufs: make mailbox functions handle multiple elements Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 08/14] spufs: remove support for ancient firmware Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 09/14] spufs: add support for read/write on cntl Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` Arnd Bergmann [this message]
2006-10-04 15:26   ` [PATCH 10/14] spufs: support new OF device tree format Arnd Bergmann
2006-10-04 15:26 ` [PATCH 11/14] spufs: add infrastructure for finding elf objects Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 12/14] powerpc: update cell_defconfig Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 13/14] spiderpic: enable new style devtree support Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann
2006-10-04 15:26 ` [PATCH 14/14] cell: fix bugs found by sparse Arnd Bergmann
2006-10-04 15:26   ` Arnd Bergmann

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=20061004161507.554879000@arndb.de \
    --to=arnd@arndb.de \
    --cc=arnd.bergmann@de.ibm.com \
    --cc=cbe-oss-dev@ozlabs.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@ozlabs.org \
    --cc=paulus@samba.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.