LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC/PATCH 5/7] Enable MSI on Powerpc
From: Michael Ellerman @ 2006-09-28 21:53 UTC (permalink / raw)
  To: linux-kernel; +Cc: Eric W. Biederman, linuxppc-dev
In-Reply-To: <1159480412.269240.988552559176.qpush@concordia>

Allow PCI_MSI to build on Powerpc.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 arch/powerpc/kernel/Makefile |    4 ++++
 drivers/pci/Kconfig          |    2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

Index: to-merge/arch/powerpc/kernel/Makefile
===================================================================
--- to-merge.orig/arch/powerpc/kernel/Makefile
+++ to-merge/arch/powerpc/kernel/Makefile
@@ -67,6 +67,10 @@ pci64-$(CONFIG_PPC64)		+= pci_64.o pci_d
 				   pci_direct_iommu.o iomap.o
 pci32-$(CONFIG_PPC32)		:= pci_32.o
 obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32-y)
+
+msiobj-y			:= msi.o
+obj-$(CONFIG_PCI_MSI)		+= $(msiobj-y)
+
 kexec-$(CONFIG_PPC64)		:= machine_kexec_64.o
 kexec-$(CONFIG_PPC32)		:= machine_kexec_32.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o crash.o $(kexec-y)
Index: to-merge/drivers/pci/Kconfig
===================================================================
--- to-merge.orig/drivers/pci/Kconfig
+++ to-merge/drivers/pci/Kconfig
@@ -4,7 +4,7 @@
 config PCI_MSI
 	bool "Message Signaled Interrupts (MSI and MSI-X)"
 	depends on PCI
-	depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64
+	depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 || PPC
 	help
 	   This allows device drivers to enable MSI (Message Signaled
 	   Interrupts).  Message Signaled Interrupts enable a device to

^ permalink raw reply

* [RFC/PATCH 6/7] RTAS MSI implementation
From: Michael Ellerman @ 2006-09-28 21:53 UTC (permalink / raw)
  To: linux-kernel; +Cc: Eric W. Biederman, linuxppc-dev
In-Reply-To: <1159480412.269240.988552559176.qpush@concordia>

Powerpc MSI support via RTAS. Based on Jake's code.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 arch/powerpc/kernel/Makefile   |    1 
 arch/powerpc/kernel/msi-rtas.c |  246 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 247 insertions(+)

Index: to-merge/arch/powerpc/kernel/Makefile
===================================================================
--- to-merge.orig/arch/powerpc/kernel/Makefile
+++ to-merge/arch/powerpc/kernel/Makefile
@@ -69,6 +69,7 @@ pci32-$(CONFIG_PPC32)		:= pci_32.o
 obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32-y)
 
 msiobj-y			:= msi.o
+msiobj-$(CONFIG_PPC_PSERIES)	+= msi-rtas.o
 obj-$(CONFIG_PCI_MSI)		+= $(msiobj-y)
 
 kexec-$(CONFIG_PPC64)		:= machine_kexec_64.o
Index: to-merge/arch/powerpc/kernel/msi-rtas.c
===================================================================
--- /dev/null
+++ to-merge/arch/powerpc/kernel/msi-rtas.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2006 Jake Moilanen <moilanen@austin.ibm.com>, IBM Corp.
+ * Copyright (C) 2006 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#define DEBUG 1
+
+#include <linux/irq.h>
+#include <asm/msi.h>
+#include <asm/rtas.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+static int query_token, change_token;
+
+#define RTAS_QUERY_MSI_FN	0
+#define RTAS_CHANGE_MSI_FN	1
+#define RTAS_RESET_MSI_FN	2
+
+
+/* RTAS Helpers */
+
+static int rtas_change_msi(struct pci_dn *pdn, u32 function, u32 num_irqs)
+{
+	u32 addr, seq_num, rtas_ret[2];
+	unsigned long buid;
+	int rc;
+
+	addr = rtas_config_addr(pdn->busno, pdn->devfn, 0);
+	buid = pdn->phb->buid;
+
+	seq_num = 1;
+	do {
+		rc = rtas_call(change_token, 6, 3, rtas_ret, addr,
+				BUID_HI(buid), BUID_LO(buid),
+				function, num_irqs, seq_num);
+
+		seq_num = rtas_ret[1];
+	} while (rtas_busy_delay(rc));
+
+	if (rc) {
+		printk(KERN_WARNING "Error[%d]: getting the number of"
+			" MSI interrupts for %s\n", rc, pci_name(pdn->pcidev));
+		return rc;
+	}
+
+	return rtas_ret[0];
+}
+
+static int rtas_query_irq_number(struct pci_dn *pdn, int offset)
+{
+	u32 addr, rtas_ret[2];
+	unsigned long buid;
+	int rc;
+
+	addr = rtas_config_addr(pdn->busno, pdn->devfn, 0);
+	buid = pdn->phb->buid;
+
+	do {
+		rc = rtas_call(query_token, 4, 3, rtas_ret, addr,
+			       BUID_HI(buid), BUID_LO(buid), offset);
+	} while (rtas_busy_delay(rc));
+
+	if (rc) {
+		printk(KERN_WARNING "Error[%d]: Querying irq source number "
+				"for %s\n", rc, pci_name(pdn->pcidev));
+		return rc;
+	}
+
+	return rtas_ret[0];
+}
+
+/*
+ * The spec gives firmware the option to enable either MSI or MSI-X,
+ * this doesn't wash with the Linux API. For the time beinging, we
+ * kludge around that by checking ourselves the right type is enabled.
+ */
+static int check_msi_type(struct pci_dev *pdev, int type)
+{
+	int pos, msi_enabled, msix_enabled;
+	u16 reg;
+
+	pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+	if (!pos)
+		return -1;
+
+	pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &reg);
+
+	msi_enabled = msix_enabled = 0;
+
+	if (reg & PCI_MSI_FLAGS_ENABLE)
+		msi_enabled = 1;
+
+	if (reg & PCI_MSIX_FLAGS_ENABLE)
+		msix_enabled = 1;
+
+	if (type == PCI_CAP_ID_MSI && (msix_enabled || !msi_enabled)) {
+		pr_debug("check_msi_type: Expected MSI but got %s.\n",
+			msix_enabled ? "MSI-X" : "none");
+		return -1;
+	}
+
+	if (type == PCI_CAP_ID_MSIX && (msi_enabled || !msix_enabled)) {
+		pr_debug("check_msi_type: Expected MSI-X but got %s.\n",
+			msi_enabled ? "MSI" : "none");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void msi_rtas_free(struct pci_dev *pdev, int num,
+			struct msix_entry *entries, int type)
+{
+	struct device_node *dn;
+	struct pci_dn *pdn;
+	int i;
+
+	dn = pci_device_to_OF_node(pdev);
+	if (!dn) {
+		pr_debug("msi_rtas_free: No OF device node for %s\n",
+				pci_name(pdev));
+		return;
+	}
+
+	pdn = PCI_DN(dn);
+	if (!pdn) {
+		pr_debug("msi_rtas_free: No PCI DN for %s\n",
+				pci_name(pdev));
+		return;
+	}
+
+	for (i = 0; i < num; i++) {
+		irq_dispose_mapping(entries[i].vector);
+	}
+
+	/* XXX can we do anything sane if this fails? */
+	rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, 0);
+}
+
+static int msi_rtas_check(struct pci_dev *pdev, int num,
+			struct msix_entry *entries, int type)
+{
+	struct device_node *dn;
+	int i;
+
+	dn = pci_device_to_OF_node(pdev);
+
+	if (!of_find_property(dn, "ibm,req#msi", NULL)) {
+		pr_debug("msi_rtas_check: No ibm,req#msi for %s\n",
+				pci_name(pdev));
+		return -1;
+	}
+
+	/*
+	 * Firmware gives us no control over which entries are allocated
+	 * for MSI-X, it seems to assume we want 0 - n. For now just insist
+	 * that the entries array entry members are 0 - n.
+	 */
+	for (i = 0; i < num; i++) {
+		if (entries[i].entry != i) {
+			pr_debug("msi_rtas_check: entries[i].entry != i\n");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int msi_rtas_alloc(struct pci_dev *pdev, int num,
+			struct msix_entry *entries, int type)
+{
+	struct pci_dn *pdn;
+	int hwirq, virq, i;
+
+	pdn = PCI_DN(pci_device_to_OF_node(pdev));
+
+	/*
+	 * In the case of an error it's not clear whether the device is left
+	 * with MSI enabled or not, I think we should explicitly disable.
+	 */
+	if (rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, num) != num)
+		goto out_free;
+
+	if (check_msi_type(pdev, type))
+		goto out_free;
+
+	for (i = 0; i < num; i++) {
+		hwirq = rtas_query_irq_number(pdn, i);
+		if (hwirq < 0)
+			goto out_free;
+
+		virq = irq_create_mapping(NULL, hwirq);
+
+		if (virq == NO_IRQ) {
+			pr_debug("msi_rtas_alloc: Failed mapping hwirq %d\n",
+				hwirq);
+			goto out_free;
+		}
+
+		entries[i].vector = virq;
+	}
+
+	return 0;
+
+ out_free:
+	msi_rtas_free(pdev, num, entries, type);
+	return -1;
+}
+
+static struct ppc_msi_ops rtas_msi_ops = {
+	.check = msi_rtas_check,
+	.alloc = msi_rtas_alloc,
+	.free  = msi_rtas_free
+};
+
+static struct ppc_msi_ops *rtas_get_msi_ops(struct pci_dev *pdev)
+{
+	return &rtas_msi_ops;
+}
+
+static int msi_rtas_init(void)
+{
+	query_token  = rtas_token("ibm,query-interrupt-source-number");
+	change_token = rtas_token("ibm,change-msi");
+
+	if ((query_token == RTAS_UNKNOWN_SERVICE) ||
+			(change_token == RTAS_UNKNOWN_SERVICE)) {
+		pr_debug("rtas_msi_init: Couldn't find RTAS tokens, no "
+				"MSI support available.\n");
+		return 0;
+	}
+
+	pr_debug("rtas_msi_init: Registering RTAS MSI ops.\n");
+
+	ppc_md.get_msi_ops = rtas_get_msi_ops;
+
+	return 0;
+}
+__initcall(msi_rtas_init);

^ permalink raw reply

* [RFC/PATCH 7/7] Preliminary MPIC MSI backend
From: Michael Ellerman @ 2006-09-28 21:53 UTC (permalink / raw)
  To: linux-kernel; +Cc: Eric W. Biederman, linuxppc-dev
In-Reply-To: <1159480412.269240.988552559176.qpush@concordia>

A pretty hackish MPIC backend, just enough to flesh out the design.
Based on code from Segher.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 arch/powerpc/kernel/Makefile   |    1 
 arch/powerpc/kernel/msi-mpic.c |   90 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)

Index: to-merge/arch/powerpc/kernel/Makefile
===================================================================
--- to-merge.orig/arch/powerpc/kernel/Makefile
+++ to-merge/arch/powerpc/kernel/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32
 
 msiobj-y			:= msi.o
 msiobj-$(CONFIG_PPC_PSERIES)	+= msi-rtas.o
+msiobj-$(CONFIG_PPC_PMAC)	+= msi-mpic.o
 obj-$(CONFIG_PCI_MSI)		+= $(msiobj-y)
 
 kexec-$(CONFIG_PPC64)		:= machine_kexec_64.o
Index: to-merge/arch/powerpc/kernel/msi-mpic.c
===================================================================
--- /dev/null
+++ to-merge/arch/powerpc/kernel/msi-mpic.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2006 Segher Boessenkool, IBM Corp.
+ * Copyright (C) 2006 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#define DEBUG 1
+
+#include <linux/irq.h>
+#include <asm/msi.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+static int msi_mpic_check(struct pci_dev *pdev, int num,
+			struct msix_entry *entries, int type)
+{
+	/* The irq allocator needs more work to support MSI-X/multi-MSI */
+	if (type == PCI_CAP_ID_MSIX || num != 1)
+		return 1;
+
+	return 0;
+}
+
+static void msi_mpic_free(struct pci_dev *pdev, int num,
+			struct msix_entry *entries, int type)
+{
+	for (i = 0; i < num; i++)
+		irq_dispose_mapping(entries[i].vector);
+}
+
+static int msi_mpic_alloc(struct pci_dev *pdev, int num,
+			struct msix_entry *entries, int type)
+{
+	irq_hw_number_t hwirq;
+	unsigned int virq;
+
+	/* We need a smarter allocator for MSI-X/multi-MSI */
+	hwirq = irq_map[pdev->irq].hwirq;
+	hwirq += 100;
+
+	virq = irq_create_mapping(NULL, hwirq);
+	if (virq == NO_IRQ) {
+		pr_debug("msi_mpic_alloc: Failed mapping hwirq %d\n", hwirq);
+		return -1;
+	}
+
+	set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
+	entries[i].vector = virq;
+
+	return 0;
+}
+
+static int msi_mpic_setup_msi_msg(struct pci_dev *pdev,
+		struct msix_entry *entry, struct msi_msg *msg, int type)
+{
+	msg->address_lo = 0xfee00000;	/* XXX What is this value? */
+	msg->address_hi = 0;
+	msg->data = pdev->irq | 0x8000;
+
+	return 0;
+}
+
+static struct ppc_msi_ops mpic_msi_ops = {
+	.check = msi_mpic_check,
+	.alloc = msi_mpic_alloc,
+	.free = msi_mpic_free
+	.enable = msi_raw_enable,
+	.disable = msi_raw_disable,
+	.setup_msi_msg = msi_mpic_setup_msi_msg,
+};
+
+static struct ppc_msi_ops *mpic_get_msi_ops(struct pci_dev *pdev)
+{
+	return &mpic_msi_ops;
+}
+
+static int msi_mpic_init(void)
+{
+	/* XXX Do this in mpic_init ? */
+	pr_debug("mpic_msi_init: Registering MPIC MSI ops.\n");
+	ppc_md.get_msi_ops = mpic_get_msi_ops;
+
+	return 0;
+}
+__initcall(msi_mpic_init);

^ permalink raw reply

* mount-  crashes with sig-11 error - linux-2.6.16.2
From: agnel juni @ 2006-09-28 22:51 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <45179FF7.3000400@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 6722 bytes --]


Hi
 
 We are using linux-2.6.16.2. We are trying to mount the compact flash (64MB) with FAT16 filesystem, using system ACE driver.
 
 We are able to run filesystem check, partition the CF etc, but the issue is with mount.
 
 'Mount' shows inconsistent results, meaning mount crashes with sig-11 error. Sametime when it succeeds we are able to copy/read/ and remove files from the CF.
 
 Please find the screen-dump of the kernel oops below:
 
 Any help is greatly appreciated.
 
 /******************* screen-dump*******************/
 Oops: kernel access of bad area, sig: 11 [#1]
 NIP: C004AD4C LR: C004CF98 CTR: 0FF050A0
 REGS: dfd8ddf8 TRAP: 0300   Not tainted  (2.6.16.2)
 MSR: 00029000 <EE,ME>  CR: 84004024  XER: 20000000
 DAR: 00000008, DSISR: 00000000
 TASK = dfc93450[620] 'exe' THREAD: dfd8c000
 GPR00: C004CF98 DFD8DEA8 DFC93450 DFD610CC DFF7D000 00000000 00029000 DFD8C000
 GPR08: C024D1F4 00000004 00000007 DFF7D090 24004022 10062C0C 00000000 00000000
 GPR16: 00000000 7FE73BA0 10060000 10060000 1006F650 10060000 1006F520 00000000
 GPR24: 1005AC48 10036970 00000005 1003EE68 DFC93450 00000000 00000000 DFD610CC
 NIP [C004AD4C] remove_vma+0x24/0x9c
 LR [C004CF98] exit_mmap+0xb4/0xec
 Call Trace:
 [DFD8DEA8] [C004ADA0] remove_vma+0x78/0x9c (unreliable)
 [DFD8DEB8] [C004CF98] exit_mmap+0xb4/0xec
 [DFD8DED8] [C0016CEC] mmput+0x50/0xd4
 [DFD8DEE8] [C001B2D8] exit_mm+0x120/0x1a0
 [DFD8DF00] [C001B914] do_exit+0x11c/0x77c
 [DFD8DF38] [C001BFB0] do_group_exit+0x0/0x80
 [DFD8DF40] [C0001BC4] ret_from_syscall+0x0/0x3c
 Instruction dump:
 4d9e0020 80a40080 4bffff58 7c0802a6 9421fff0 bfc10008 7c7f1b78 90010014
 81230044 83c3000c 2f890000 419e0010 <80090004> 2f800000 409e0064 807f004c
 Fixing recursive fault but reboot is needed!
 Oops: kernel access of bad area, sig: 11 [#2]
 NIP: C00556B8 LR: C00557E4 CTR: 00000000
 REGS: dfdbfe08 TRAP: 0300   Not tainted  (2.6.16.2)
 MSR: 00021000 <ME>  CR: 22008028  XER: 00000000
 DAR: 00000000, DSISR: 00800000
 TASK = dff6c030[4] 'events/0' THREAD: dfdbe000
 GPR00: 00100100 DFDBFEB8 DFF6C030 C0258D20 DFF7D010 00000018 DFD61000 C0256E20
 GPR08: 00000000 00200200 DFD61EE4 C0256E28 C0220000 10062C0C 1FFB9700 00000000
 GPR16: 00000001 FFFFFFFF 00000000 007FFF00 1FFB3604 1FF63CE0 1FFCEF78 C01F0000
 GPR24: C0240000 00100100 C0240000 00000000 DFF7D010 00000018 00000002 C0258D20
 NIP [C00556B8] free_block+0xa8/0x148
 LR [C00557E4] drain_array_locked+0x8c/0xd8
 Call Trace:
 [DFDBFEB8] [C0055338] kmem_freepages+0x98/0xdc (unreliable)
 [DFDBFED8] [C00557E4] drain_array_locked+0x8c/0xd8
 [DFDBFEF0] [C0056F80] cache_reap+0x74/0x18c
 [DFDBFF28] [C002B578] run_workqueue+0x9c/0x110
 [DFDBFF48] [C002B6E4] worker_thread+0xf8/0x13c
 [DFDBFFC0] [C002F6F0] kthread+0xf4/0x130
 [DFDBFFF0] [C000413C] kernel_thread+0x44/0x60
 Instruction dump:
 7cfbfa14 3c000010 80e70014 3d2a4000 60000100 5529c9f4 7d295a14 80c9001c
 3d200020 61290200 81060004 81660000 <91680000> 910b0004 3966001c 90060000
 BUG: events/0/4, lock held at task exit time!
  [c01f5d60] {cache_chain_mutex}
 .. held by:          events/0:    4 [dff6c030, 110]
 ... acquired at:               cache_reap+0x1c/0x18c
 
 
 Thanks
 Junita
 
 
 
 
Ameet Patil <ammubhai@gmail.com> wrote: agnel juni wrote:
> Hi Ameet
>
> I have posted a few messages regarding Ssytem ACE driver for Linux-2.6.
>
> We are working on a AMCC 440SPe based custom board.
>
> We applied the patch from
> //http://www.cs.york.ac.uk/rtslab/demos/amos/xupv2pro/patches/linuxppc-2.6.17.1-sysace-1.2.patch
>  //and applied against 2.6.16-2 kernel.
>
> We are trying to make the driver work in interrupt mode.
>
> First, I would like to know if the driver tested in interrupt mode.
>
> We are able to mount the CF, but it is very inconsistent.
>
> Same is the case with fdisk command. When it fails,we get errors which you could see in the screen-dump below.//
> //
> Are we missing to apply the right patch? Please let us know your 
> inputs to go forward.
> Looking forwards for your reply.
>
> Thanks
> Junita
>
> /*************** Screen dump ********************/
> # fdisk /dev/xsysace
> 1. sector = 0 xsa_cur_req->sector=0
> System ACE: Error 0 when reading sector 2.
> 2. sector = 2 xsa_cur_req->sector=16
> end_request: I/O error, System ACE: Error 0 when reading sectoru dev 
> xsa, sector 16
> Buffer I/O error on device xsa, logical block 2
> 1. sector = 184 xsa_cur_req->sector=184
>  
> Command (m for help): p
>  
> Disk /dev/xsysace: 524 MB, 524869632 bytes
> 17 heads, 59 sectors/track, 1022 cylinders
> Units = cylinders of 1003 * 512 = 513536 bytes
>  
>        Device Boot      Start         End      Blocks   Id  System
> /dev/xsysace1               1        1022      512503+   6  FAT16
>  
> Command (m for help): q
> And for 'mount'
> #
> #
> # mount -t msdos /dev/xsysace /root/cf
> 1. sector = 0 xsa_cur_req->sector=0
> 1. sector = 503 xsa_cur_req->sector=503
> 1. sector = 504 xsa_cur_req->sector=504
> 1. sector = 506 xsa_cur_req->sector=506
> 1. sector = 508 xsa_cur_req->sector=508
> 1. sector = 510 xsa_cur_req->sector=510
> # cd /root/cf
> < Here Prints Some Symbols like + - etc, which i am
>   not able to capture/copy -------------ERROR
> b: No such file or directory--------------------------------ERROR
> pci.h
> #
> Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.n0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.0Minicom2.00.d#
> # cp pci.h /root/
> # cd ../
> # ls
> app     cf      hello1  pci.h
> #
> #/root
>  /dev/xsysace /root/cf
> FAT: bogus number of reserved sectors
> VFS: Can't find a valid FAT filesystem on dev xsa.
> mount: Mounting /dev/xsysace on /root/cf failed: Invalid argument
> #
>  
>
>
> //
>
>
>
> //
>
> ------------------------------------------------------------------------
> Find out what India is talking about on - Yahoo! Answers India 
> 
> Send FREE SMS to your friend's mobile from Yahoo! Messenger Version 8. 
> Get it NOW 
>  


Hi Agnel,
    The driver was last tested with 2.6.17 kernel and till date works 
fine in the interrupt mode. I have been using it since the last 4 months 
now. It should also work on 2.6.16-2 kernel I think, but I have not 
tested this. Have you made any changes to the driver? If so... please 
give the details so I can give you better feedback as to where things 
might have gone wrong. When time permits I shall try my patch on the 
2.6.16-2 kernel and let you know if it works for me.

Thanks,
-Ameet


 				
---------------------------------
 Find out what India is talking about on  - Yahoo! Answers India 
 Send FREE SMS to your friend's mobile from Yahoo! Messenger Version 8. Get it NOW

[-- Attachment #2: Type: text/html, Size: 8109 bytes --]

^ permalink raw reply

* Support for Linux Trace Tool (ltt)
From: Bizhan Gholikhamseh (bgholikh) @ 2006-09-28 23:01 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 123 bytes --]

Hi All,
Is there any support for Linux ltt on Linux 2.6 (perfably 2.6.11) for
ppc architecture (MPC8541E)?
Thanks,
BG

[-- Attachment #2: Type: text/html, Size: 684 bytes --]

^ permalink raw reply

* Re: [RFC/PATCH 7/7] Preliminary MPIC MSI backend
From: Michael Ellerman @ 2006-09-28 23:37 UTC (permalink / raw)
  To: linux-kernel; +Cc: linuxppc-dev, Eric W. Biederman
In-Reply-To: <20060928215349.45C0667C47@ozlabs.org>

[-- Attachment #1: Type: text/plain, Size: 530 bytes --]

On Fri, 2006-09-29 at 07:53 +1000, Michael Ellerman wrote:
> A pretty hackish MPIC backend, just enough to flesh out the design.
> Based on code from Segher.
> 
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>

Missing a quilt ref, new one coming RSN.

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 191 bytes --]

^ permalink raw reply

* [PATCH] Preliminary MPIC MSI backend
From: Michael Ellerman @ 2006-09-29  0:16 UTC (permalink / raw)
  To: linux-kernel; +Cc: linuxppc-dev, Eric W. Biederman
In-Reply-To: <1159486661.25820.1.camel@localhost.localdomain>

A pretty hackish MPIC backend, just enough to flesh out the design.
Based on code from Segher.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 arch/powerpc/kernel/Makefile   |    1 
 arch/powerpc/kernel/msi-mpic.c |   92 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)

Index: to-merge/arch/powerpc/kernel/Makefile
===================================================================
--- to-merge.orig/arch/powerpc/kernel/Makefile
+++ to-merge/arch/powerpc/kernel/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32
 
 msiobj-y			:= msi.o
 msiobj-$(CONFIG_PPC_PSERIES)	+= msi-rtas.o
+msiobj-$(CONFIG_PPC_PMAC)	+= msi-mpic.o
 obj-$(CONFIG_PCI_MSI)		+= $(msiobj-y)
 
 kexec-$(CONFIG_PPC64)		:= machine_kexec_64.o
Index: to-merge/arch/powerpc/kernel/msi-mpic.c
===================================================================
--- /dev/null
+++ to-merge/arch/powerpc/kernel/msi-mpic.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2006 Segher Boessenkool, IBM Corp.
+ * Copyright (C) 2006 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#define DEBUG 1
+
+#include <linux/irq.h>
+#include <asm/msi.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+static int msi_mpic_check(struct pci_dev *pdev, int num,
+			struct msix_entry *entries, int type)
+{
+	/* The irq allocator needs more work to support MSI-X/multi-MSI */
+	if (type == PCI_CAP_ID_MSIX || num != 1)
+		return 1;
+
+	return 0;
+}
+
+static void msi_mpic_free(struct pci_dev *pdev, int num,
+			struct msix_entry *entries, int type)
+{
+	int i;
+
+	for (i = 0; i < num; i++)
+		irq_dispose_mapping(entries[i].vector);
+}
+
+static int msi_mpic_alloc(struct pci_dev *pdev, int num,
+			struct msix_entry *entries, int type)
+{
+	irq_hw_number_t hwirq;
+	unsigned int virq;
+
+	/* We need a smarter allocator for MSI-X/multi-MSI */
+	hwirq = irq_map[pdev->irq].hwirq;
+	hwirq += 100;
+
+	virq = irq_create_mapping(NULL, hwirq);
+	if (virq == NO_IRQ) {
+		pr_debug("msi_mpic_alloc: Failed mapping hwirq %lu\n", hwirq);
+		return -1;
+	}
+
+	set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
+	entries[0].vector = virq;
+
+	return 0;
+}
+
+static int msi_mpic_setup_msi_msg(struct pci_dev *pdev,
+		struct msix_entry *entry, struct msi_msg *msg, int type)
+{
+	msg->address_lo = 0xfee00000;	/* XXX What is this value? */
+	msg->address_hi = 0;
+	msg->data = pdev->irq | 0x8000;
+
+	return 0;
+}
+
+static struct ppc_msi_ops mpic_msi_ops = {
+	.check = msi_mpic_check,
+	.alloc = msi_mpic_alloc,
+	.free = msi_mpic_free,
+	.enable = msi_raw_enable,
+	.disable = msi_raw_disable,
+	.setup_msi_msg = msi_mpic_setup_msi_msg,
+};
+
+static struct ppc_msi_ops *mpic_get_msi_ops(struct pci_dev *pdev)
+{
+	return &mpic_msi_ops;
+}
+
+static int msi_mpic_init(void)
+{
+	/* XXX Do this in mpic_init ? */
+	pr_debug("mpic_msi_init: Registering MPIC MSI ops.\n");
+	ppc_md.get_msi_ops = mpic_get_msi_ops;
+
+	return 0;
+}
+__initcall(msi_mpic_init);

^ permalink raw reply

* About cache
From: enorm @ 2006-09-29  1:25 UTC (permalink / raw)
  To: linuxppc-embedded

Hi,

I found in mpc85xx start.s, before doing any initialization it disabled 
 i-cache & d-cache. Must we do so? If we don't disable them what will it 
 cause? 

Best Regards
Enorm

^ permalink raw reply

* Trouble with 2.6 Kernel
From: Glenn.G.Hart @ 2006-09-29  2:35 UTC (permalink / raw)
  To: linuxppc-embedded

I am trying to get Linux PPC 2.6.17.1 up and running on a Xilinx Virtex-4
FX 12 FPGA.  Everything appears to proceed normally, but at the end of the
kernel initialization it gives me a scheduling while atomic error.  I have
found on the web others having this problem, but without a good solution.
Do I have something configured wrong or do I need a patch.  The output of
the kernel is shown below.

  Thanks,
  Glenn

loaded at:     00400000 004E113C
board data at: 004DF124 004DF13C
relocated to:  004050EC 00405104
zimage at:     00405801 004DEC72
avail ram:     004E2000 10000000

Linux/PPC load: console=ttyS0,9600 console=tty0 root=/dev/sda2
Uncompressing Linux...done.
Now booting the kernel
Linux version 2.6.17.1 (root@AFedora3) (gcc version 3.4.5) #18 PREEMPT Thu
Sep 28 02:29:45 EDT 2006
Xilinx Virtex-II Pro port
Port by MontaVista Software, Inc. (source@mvista.com)
Built 1 zonelists
Kernel command line: console=ttyS0,9600 console=tty0 root=/dev/sda2
Xilinx INTC #0 at 0x41200000 mapped to 0xFDFFE000
PID hash table entries: 2048 (order: 11, 8192 bytes)
Console: colour dummy device 80x25
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 257792k available (1528k kernel code, 400k data, 84k init, 0k
highmem)
Mount-cache hash table entries: 512
NET: Registered protocol family 16
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 8192 bind 4096)
TCP reno registered
io scheduler noop registered (default)
Serial: 8250/16550 driver $Revision: 1.90 $ 1 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0x40401003 (irq = 1) is a 16450
RAMDISK driver initialized: 1 RAM disks of 4096K size 1024 blocksize
loop: loaded (max 8 devices)
nbd: registered device at major 43
eth0: using fifo mode.
eth0: Xilinx EMAC #0 at 0x80400000 mapped to 0xD1000000, irq=0
eth0: id 2.0a; block id 0, type 8
mice: PS/2 mouse device common for all mice
ip_conntrack version 2.4 (2048 buckets, 16384 max) - 188 bytes per
conntrack
BUG: scheduling while atomic: swapper/0xffffffff/1
Call Trace:
[C0451E50] [C0008F20] show_stack+0x58/0x180 (unreliable)
[C0451E80] [C017AAC0] schedule+0x48/0x6e4
[C0451EB0] [C017B340] wait_for_completion+0xbc/0x158
[C0451EF0] [C003400C] synchronize_rcu+0x38/0x48
[C0451F30] [C01140D4] synchronize_net+0x10/0x20
[C0451F40] [C0124760] nf_register_hook+0xac/0xc0
[C0451F50] [C0124860] nf_register_hooks+0x34/0x7c
[C0451F70] [C01DD3C0] ip_conntrack_standalone_init+0xb8/0x154
[C0451F90] [C0002470] init+0xa4/0x280
[C0451FF0] [C00051FC] kernel_thread+0x44/0x60

^ permalink raw reply

* RE: [PATCH 0/12] Add support for QE and 8360EMDS board -v2
From: Li Yang-r58472 @ 2006-09-29  3:21 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, paulus
In-Reply-To: <98C2C73A-F57B-49A6-9727-D76A1AE9746C@kernel.crashing.org>

> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]
> Sent: Friday, September 29, 2006 12:37 AM
> To: Li Yang-r58472
> Cc: linuxppc-dev@ozlabs.org; paulus@samba.org
> Subject: Re: [PATCH 0/12] Add support for QE and 8360EMDS board -v2
>=20
>=20
> On Sep 28, 2006, at 11:09 AM, Li Yang wrote:
>=20
> > On 9/28/06, Kumar Gala <galak@kernel.crashing.org> wrote:
> >>
> >> On Sep 28, 2006, at 3:18 AM, Li Yang wrote:
> >>
> >> > Paul,
> >> >
> >> > The series of patches add generic QE infrastructure called
> >> > qe_lib, and MPC8360EMDS board support.  Qe_lib is used by
> >> > QE device drivers such as ucc_geth driver.
> >> >
> >> > This version updates QE interrupt controller to use new irq
> >> > mapping mechanism, addresses all the comments received with
> >> > last submission and includes some style fixes.
> >> >
> >> > v2 change: Change to use device tree for BCSR and MURAM;
> >> > Remove I/O port interrupt handling code as it is not generic
> >> > enough.
> >>
> >> Before accepting any of this code, I'd like to see what the drivers
> >> look like that are using it.  Its hard to make significant
> >> comments w/
> >> o seeing what the consumers of all the 'lib' code look like.
> >
> > Current in-tree user of the lib is driver/net/ucc_geth.c.  There is
> > also QE ATM driver which is included in Alex's 8360sar project.  QE
> > USB host/client drivers are in Freescale LTIB BSP.
>=20
> is there a serial driver?

No.  It is not very necessary to have serial support for QE, as there is
separate DUART SoC.  We can use 8250 serial driver for that.

- Leo

^ permalink raw reply

* scc ethernet driver error - bus contention?
From: Lichang Che @ 2006-09-29  3:07 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 620 bytes --]

Hello,

 

I'm using Linux 2.6.16 + uboot on MPC8250 - SMC2 for UART and SCC4 for 10M
Ethernet. The problem I got is as follows:

 

1. If the GBL bit is set (with address snooping), an underrun happens for
each frame transmission.

 

2. If the GBL bit is disabled, the underrun problem disappears but nearly
all frames are corrupted - the frame can be received (without CRC etc) by
another machine but the data is not correct.

 

3. If the frame to be sent is copied into the dual port ram first and the
transmission is triggered, the frame can be successfully received.

 

Can anyone give me some hint?

 

Cheers


[-- Attachment #2: Type: text/html, Size: 3521 bytes --]

^ permalink raw reply

* RE: About cache
From: Xu, Li (GE, Research) @ 2006-09-29  4:45 UTC (permalink / raw)
  To: enorm, linuxppc-embedded
In-Reply-To: <00a901c6e366$1d3e4f70$a309a8c0@enorm>

WW91IGhhdmUgdG8gZG8gc28uDQpUaGF0IHdpbGwgcHJldmVudCBDUFUgZnJvbSBmZXRjaGluZyBk
YXRhIG9yIGluc3RydWN0aW9ucyBmcm9tIGktY2FjaGUgYW5kIGQtY2FjaGUNCmF0IHRoZSBpbml0
aWFsaXphdGlvbiB0aW1lIHNpbmNlIHRoZSBjYWNoZSBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0Lg0K
DQoJLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0gDQoJRnJvbTogbGludXhwcGMtZW1iZWRkZWQt
Ym91bmNlcytsaS54dT1nZS5jb21Ab3psYWJzLm9yZyBvbiBiZWhhbGYgb2YgZW5vcm0gDQoJU2Vu
dDogRnJpIDkvMjkvMjAwNiA5OjI1IEFNIA0KCVRvOiBsaW51eHBwYy1lbWJlZGRlZEBvemxhYnMu
b3JnIA0KCUNjOiANCglTdWJqZWN0OiBBYm91dCBjYWNoZQ0KCQ0KCQ0KDQoJSGksDQoJDQoJSSBm
b3VuZCBpbiBtcGM4NXh4IHN0YXJ0LnMsIGJlZm9yZSBkb2luZyBhbnkgaW5pdGlhbGl6YXRpb24g
aXQgZGlzYWJsZWQNCgkgaS1jYWNoZSAmIGQtY2FjaGUuIE11c3Qgd2UgZG8gc28/IElmIHdlIGRv
bid0IGRpc2FibGUgdGhlbSB3aGF0IHdpbGwgaXQNCgkgY2F1c2U/DQoJDQoJQmVzdCBSZWdhcmRz
DQoJRW5vcm0NCgkNCgkNCgkNCgkNCg0K

^ permalink raw reply

* LSP for MPC8247
From: Akhilesh Soni @ 2006-09-29  4:56 UTC (permalink / raw)
  To: linuxppc-embedded; +Cc: linuxppc-embedded-request

[-- Attachment #1: Type: text/plain, Size: 297 bytes --]

Hi,

Is there any open soure LSP for freescale MPC8247 available. 

I've an LSP for MPC8245 and I need for MPC8247. How much effort would be required to change from 8245 to 8247. Is somebody already done this ?

Any pointer or suggestions would be highly appreciated.

Regards,
Akhilesh

[-- Attachment #2: Type: text/html, Size: 1015 bytes --]

^ permalink raw reply

* [PATCH] Cell interrupt rework (final)
From: Benjamin Herrenschmidt @ 2006-09-29  5:00 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev list, Paul Mackerras, cbe-oss-dev@ozlabs.org

This patch reworks the cell iic interrupt handling so that:

 - Node ID is back in the interrupt number (only one IRQ host is created
for all nodes). This allows interrupts from sources on another node to
be routed non-locally. This will allow possibly one day to fix maxcpus=1
or 2 and still get interrupts from devices on BE 1. (A bit more fixing
is needed for that) and it will allow us to implement actual affinity
control of external interrupts.

 - Added handling of the IO exceptions interrupts (badly named, but I
re-used the name initially used by STI). Those are the interrupts
exposed by IIC_ISR and IIC_IRR, such as the IOC translation exception,
performance monitor, etc... Those get their special numbers in the IRQ
number space and are internally implemented as a cascade on unit 0xe,
class 1 of each node.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

Hi Arnd !

It occurred to me that the version of the Cell interrupt rework I sent
you was still not the latest one ! In fact, I wasn't using the latest
one myself, only Jeremy was :) I messed up with my patch handling
locally. The result is that the version you have is causing occasional
loss of interrupts, typically the case where IDE disappears after
loading the SPUs a bit.

This is the real latest version that works and that survives parallel
SPU torture and hard disk activity. The problem was that unexepcted
interrupts wouldn't be ack'ed (the priority register wouldn't be put
back to 0xff). The bug was in the original code but it would somewhat
recover after some fairly high latency by getting some even higher
priority interrupt since it's eoi would unconditionally set back the
priority to 0xff. The new code implements a nice prio stack however, and
thus ends up with the priority never going back down.

Paulus: please merge upstream too.

Index: linux-cell/arch/powerpc/platforms/cell/interrupt.c
===================================================================
--- linux-cell.orig/arch/powerpc/platforms/cell/interrupt.c	2006-09-08 17:17:10.000000000 +1000
+++ linux-cell/arch/powerpc/platforms/cell/interrupt.c	2006-09-29 14:36:23.000000000 +1000
@@ -21,6 +21,12 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * TODO:
+ * - Fix various assumptions related to HW CPU numbers vs. linux CPU numbers
+ *   vs node numbers in the setup code
+ * - Implement proper handling of maxcpus=1/2 (that is, routing of irqs from
+ *   a non-active node to the active node)
  */
 
 #include <linux/interrupt.h>
@@ -44,24 +50,25 @@ struct iic {
 	u8 target_id;
 	u8 eoi_stack[16];
 	int eoi_ptr;
-	struct irq_host *host;
+	struct device_node *node;
 };
 
 static DEFINE_PER_CPU(struct iic, iic);
 #define IIC_NODE_COUNT	2
-static struct irq_host *iic_hosts[IIC_NODE_COUNT];
+static struct irq_host *iic_host;
 
 /* Convert between "pending" bits and hw irq number */
 static irq_hw_number_t iic_pending_to_hwnum(struct cbe_iic_pending_bits bits)
 {
 	unsigned char unit = bits.source & 0xf;
+	unsigned char node = bits.source >> 4;
+	unsigned char class = bits.class & 3;
 
+	/* Decode IPIs */
 	if (bits.flags & CBE_IIC_IRQ_IPI)
-		return IIC_IRQ_IPI0 | (bits.prio >> 4);
-	else if (bits.class <= 3)
-		return (bits.class << 4) | unit;
+		return IIC_IRQ_TYPE_IPI | (bits.prio >> 4);
 	else
-		return IIC_IRQ_INVALID;
+		return (node << IIC_IRQ_NODE_SHIFT) | (class << 4) | unit;
 }
 
 static void iic_mask(unsigned int irq)
@@ -86,21 +93,70 @@ static struct irq_chip iic_chip = {
 	.eoi = iic_eoi,
 };
 
+
+static void iic_ioexc_eoi(unsigned int irq)
+{
+}
+
+static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc,
+			    struct pt_regs *regs)
+{
+	struct cbe_iic_regs *node_iic = desc->handler_data;
+	unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC;
+	unsigned long bits, ack;
+	int cascade;
+
+	for (;;) {
+		bits = in_be64(&node_iic->iic_is);
+		if (bits == 0)
+			break;
+		/* pre-ack edge interrupts */
+		ack = bits & IIC_ISR_EDGE_MASK;
+		if (ack)
+			out_be64(&node_iic->iic_is, ack);
+		/* handle them */
+		for (cascade = 63; cascade >= 0; cascade--)
+			if (bits & (0x8000000000000000UL >> cascade)) {
+				unsigned int cirq =
+					irq_linear_revmap(iic_host,
+							  base | cascade);
+				if (cirq != NO_IRQ)
+					generic_handle_irq(cirq, regs);
+			}
+		/* post-ack level interrupts */
+		ack = bits & ~IIC_ISR_EDGE_MASK;
+		if (ack)
+			out_be64(&node_iic->iic_is, ack);
+	}
+	desc->chip->eoi(irq);
+}
+
+
+static struct irq_chip iic_ioexc_chip = {
+	.typename = " CELL-IOEX",
+	.mask = iic_mask,
+	.unmask = iic_unmask,
+	.eoi = iic_ioexc_eoi,
+};
+
 /* Get an IRQ number from the pending state register of the IIC */
 static unsigned int iic_get_irq(struct pt_regs *regs)
 {
   	struct cbe_iic_pending_bits pending;
  	struct iic *iic;
+	unsigned int virq;
 
  	iic = &__get_cpu_var(iic);
  	*(unsigned long *) &pending =
  		in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
+	if (!(pending.flags & CBE_IIC_IRQ_VALID))
+		return NO_IRQ;
+	virq = irq_linear_revmap(iic_host, iic_pending_to_hwnum(pending));
+	if (virq == NO_IRQ)
+		return NO_IRQ;
  	iic->eoi_stack[++iic->eoi_ptr] = pending.prio;
  	BUG_ON(iic->eoi_ptr > 15);
-	if (pending.flags & CBE_IIC_IRQ_VALID)
-		return irq_linear_revmap(iic->host,
- 					 iic_pending_to_hwnum(pending));
-	return NO_IRQ;
+	return virq;
 }
 
 #ifdef CONFIG_SMP
@@ -108,12 +164,7 @@ static unsigned int iic_get_irq(struct p
 /* Use the highest interrupt priorities for IPI */
 static inline int iic_ipi_to_irq(int ipi)
 {
-	return IIC_IRQ_IPI0 + IIC_NUM_IPIS - 1 - ipi;
-}
-
-static inline int iic_irq_to_ipi(int irq)
-{
-	return IIC_NUM_IPIS - 1 - (irq - IIC_IRQ_IPI0);
+	return IIC_IRQ_TYPE_IPI + 0xf - ipi;
 }
 
 void iic_setup_cpu(void)
@@ -123,7 +174,7 @@ void iic_setup_cpu(void)
 
 void iic_cause_IPI(int cpu, int mesg)
 {
-	out_be64(&per_cpu(iic, cpu).regs->generate, (IIC_NUM_IPIS - 1 - mesg) << 4);
+	out_be64(&per_cpu(iic, cpu).regs->generate, (0xf - mesg) << 4);
 }
 
 u8 iic_get_target_id(int cpu)
@@ -134,9 +185,7 @@ EXPORT_SYMBOL_GPL(iic_get_target_id);
 
 struct irq_host *iic_get_irq_host(int node)
 {
-	if (node < 0 || node >= IIC_NODE_COUNT)
-		return NULL;
-	return iic_hosts[node];
+	return iic_host;
 }
 EXPORT_SYMBOL_GPL(iic_get_irq_host);
 
@@ -149,34 +198,20 @@ static irqreturn_t iic_ipi_action(int ir
 
 	return IRQ_HANDLED;
 }
-
 static void iic_request_ipi(int ipi, const char *name)
 {
-	int node, virq;
+	int virq;
 
-	for (node = 0; node < IIC_NODE_COUNT; node++) {
-		char *rname;
-		if (iic_hosts[node] == NULL)
-			continue;
-		virq = irq_create_mapping(iic_hosts[node],
-					  iic_ipi_to_irq(ipi));
-		if (virq == NO_IRQ) {
-			printk(KERN_ERR
-			       "iic: failed to map IPI %s on node %d\n",
-			       name, node);
-			continue;
-		}
-		rname = kzalloc(strlen(name) + 16, GFP_KERNEL);
-		if (rname)
-			sprintf(rname, "%s node %d", name, node);
-		else
-			rname = (char *)name;
-		if (request_irq(virq, iic_ipi_action, IRQF_DISABLED,
-				rname, (void *)(long)ipi))
-			printk(KERN_ERR
-			       "iic: failed to request IPI %s on node %d\n",
-			       name, node);
+	virq = irq_create_mapping(iic_host, iic_ipi_to_irq(ipi));
+	if (virq == NO_IRQ) {
+		printk(KERN_ERR
+		       "iic: failed to map IPI %s\n", name);
+		return;
 	}
+	if (request_irq(virq, iic_ipi_action, IRQF_DISABLED, name,
+			(void *)(long)ipi))
+		printk(KERN_ERR
+		       "iic: failed to request IPI %s\n", name);
 }
 
 void iic_request_IPIs(void)
@@ -193,16 +228,24 @@ void iic_request_IPIs(void)
 
 static int iic_host_match(struct irq_host *h, struct device_node *node)
 {
-	return h->host_data != NULL && node == h->host_data;
+	return device_is_compatible(node,
+				    "IBM,CBEA-Internal-Interrupt-Controller");
 }
 
 static int iic_host_map(struct irq_host *h, unsigned int virq,
 			irq_hw_number_t hw)
 {
-	if (hw < IIC_IRQ_IPI0)
-		set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq);
-	else
+	switch (hw & IIC_IRQ_TYPE_MASK) {
+	case IIC_IRQ_TYPE_IPI:
 		set_irq_chip_and_handler(virq, &iic_chip, handle_percpu_irq);
+		break;
+	case IIC_IRQ_TYPE_IOEXC:
+		set_irq_chip_and_handler(virq, &iic_ioexc_chip,
+					 handle_fasteoi_irq);
+		break;
+	default:
+		set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq);
+	}
 	return 0;
 }
 
@@ -211,11 +254,39 @@ static int iic_host_xlate(struct irq_hos
 			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
 
 {
-	/* Currently, we don't translate anything. That needs to be fixed as
-	 * we get better defined device-trees. iic interrupts have to be
-	 * explicitely mapped by whoever needs them
-	 */
-	return -ENODEV;
+	unsigned int node, ext, unit, class;
+	const u32 *val;
+
+	if (!device_is_compatible(ct,
+				     "IBM,CBEA-Internal-Interrupt-Controller"))
+		return -ENODEV;
+	if (intsize != 1)
+		return -ENODEV;
+	val = get_property(ct, "#interrupt-cells", NULL);
+	if (val == NULL || *val != 1)
+		return -ENODEV;
+
+	node = intspec[0] >> 24;
+	ext = (intspec[0] >> 16) & 0xff;
+	class = (intspec[0] >> 8) & 0xff;
+	unit = intspec[0] & 0xff;
+
+	/* Check if node is in supported range */
+	if (node > 1)
+		return -EINVAL;
+
+	/* Build up interrupt number, special case for IO exceptions */
+	*out_hwirq = (node << IIC_IRQ_NODE_SHIFT);
+	if (unit == IIC_UNIT_IIC && class == 1)
+		*out_hwirq |= IIC_IRQ_TYPE_IOEXC | ext;
+	else
+		*out_hwirq |= IIC_IRQ_TYPE_NORMAL |
+			(class << IIC_IRQ_CLASS_SHIFT) | unit;
+
+	/* Dummy flags, ignored by iic code */
+	*out_flags = IRQ_TYPE_EDGE_RISING;
+
+	return 0;
 }
 
 static struct irq_host_ops iic_host_ops = {
@@ -225,7 +296,7 @@ static struct irq_host_ops iic_host_ops 
 };
 
 static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr,
-				struct irq_host *host)
+				struct device_node *node)
 {
 	/* XXX FIXME: should locate the linux CPU number from the HW cpu
 	 * number properly. We are lucky for now
@@ -237,28 +308,27 @@ static void __init init_one_iic(unsigned
 
 	iic->target_id = ((hw_cpu & 2) << 3) | ((hw_cpu & 1) ? 0xf : 0xe);
 	iic->eoi_stack[0] = 0xff;
-	iic->host = host;
+	iic->node = of_node_get(node);
 	out_be64(&iic->regs->prio, 0);
 
-	printk(KERN_INFO "IIC for CPU %d at %lx mapped to %p, target id 0x%x\n",
-	       hw_cpu, addr, iic->regs, iic->target_id);
+	printk(KERN_INFO "IIC for CPU %d target id 0x%x : %s\n",
+	       hw_cpu, iic->target_id, node->full_name);
 }
 
 static int __init setup_iic(void)
 {
 	struct device_node *dn;
 	struct resource r0, r1;
-	struct irq_host *host;
-	int found = 0;
- 	u32 *np;
+	unsigned int node, cascade, found = 0;
+	struct cbe_iic_regs *node_iic;
+ 	const u32 *np;
 
 	for (dn = NULL;
 	     (dn = of_find_node_by_name(dn,"interrupt-controller")) != NULL;) {
 		if (!device_is_compatible(dn,
 				     "IBM,CBEA-Internal-Interrupt-Controller"))
 			continue;
- 		np = (u32 *)get_property(dn, "ibm,interrupt-server-ranges",
-					 NULL);
+ 		np = get_property(dn, "ibm,interrupt-server-ranges", NULL);
  		if (np == NULL) {
 			printk(KERN_WARNING "IIC: CPU association not found\n");
 			of_node_put(dn);
@@ -270,19 +340,33 @@ static int __init setup_iic(void)
 			of_node_put(dn);
 			return -ENODEV;
 		}
-		host = NULL;
-		if (found < IIC_NODE_COUNT) {
-			host = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
-					      IIC_SOURCE_COUNT,
-					      &iic_host_ops,
-					      IIC_IRQ_INVALID);
-			iic_hosts[found] = host;
-			BUG_ON(iic_hosts[found] == NULL);
-			iic_hosts[found]->host_data = of_node_get(dn);
-			found++;
-		}
-		init_one_iic(np[0], r0.start, host);
-		init_one_iic(np[1], r1.start, host);
+		found++;
+		init_one_iic(np[0], r0.start, dn);
+		init_one_iic(np[1], r1.start, dn);
+
+		/* Setup cascade for IO exceptions. XXX cleanup tricks to get
+		 * node vs CPU etc...
+		 * Note that we configure the IIC_IRR here with a hard coded
+		 * priority of 1. We might want to improve that later.
+		 */
+		node = np[0] >> 1;
+		node_iic = cbe_get_cpu_iic_regs(np[0]);
+		cascade = node << IIC_IRQ_NODE_SHIFT;
+		cascade |= 1 << IIC_IRQ_CLASS_SHIFT;
+		cascade |= IIC_UNIT_IIC;
+		cascade = irq_create_mapping(iic_host, cascade);
+		if (cascade == NO_IRQ)
+			continue;
+		set_irq_data(cascade, node_iic);
+		set_irq_chained_handler(cascade , iic_ioexc_cascade);
+		out_be64(&node_iic->iic_ir,
+			 (1 << 12)		/* priority */ |
+			 (node << 4)		/* dest node */ |
+			 IIC_UNIT_THREAD_0	/* route them to thread 0 */);
+		/* Flush pending (make sure it triggers if there is
+		 * anything pending
+		 */
+		out_be64(&node_iic->iic_is, 0xfffffffffffffffful);
 	}
 
 	if (found)
@@ -293,6 +377,12 @@ static int __init setup_iic(void)
 
 void __init iic_init_IRQ(void)
 {
+	/* Setup an irq host data structure */
+	iic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, IIC_SOURCE_COUNT,
+				  &iic_host_ops, IIC_IRQ_INVALID);
+	BUG_ON(iic_host == NULL);
+	irq_set_default_host(iic_host);
+
 	/* Discover and initialize iics */
 	if (setup_iic() < 0)
 		panic("IIC: Failed to initialize !\n");
Index: linux-cell/arch/powerpc/platforms/cell/interrupt.h
===================================================================
--- linux-cell.orig/arch/powerpc/platforms/cell/interrupt.h	2006-09-08 17:17:10.000000000 +1000
+++ linux-cell/arch/powerpc/platforms/cell/interrupt.h	2006-09-22 12:56:14.000000000 +1000
@@ -2,48 +2,76 @@
 #define ASM_CELL_PIC_H
 #ifdef __KERNEL__
 /*
- * Mapping of IIC pending bits into per-node
- * interrupt numbers.
+ * Mapping of IIC pending bits into per-node interrupt numbers.
  *
- * IRQ     FF CC SS PP   FF CC SS PP	Description
+ * Interrupt numbers are in the range 0...0x1ff where the top bit
+ * (0x100) represent the source node. Only 2 nodes are supported with
+ * the current code though it's trivial to extend that if necessary using
+ * higher level bits
  *
- * 00-3f   80 02 +0 00 - 80 02 +0 3f	South Bridge
- * 00-3f   80 02 +b 00 - 80 02 +b 3f	South Bridge
- * 41-4a   80 00 +1 ** - 80 00 +a **	SPU Class 0
- * 51-5a   80 01 +1 ** - 80 01 +a **	SPU Class 1
- * 61-6a   80 02 +1 ** - 80 02 +a **	SPU Class 2
- * 70-7f   C0 ** ** 00 - C0 ** ** 0f	IPI
+ * The bottom 8 bits are split into 2 type bits and 6 data bits that
+ * depend on the type:
  *
- *    F flags
- *    C class
- *    S source
- *    P Priority
- *    + node number
- *    * don't care
+ * 00 (0x00 | data) : normal interrupt. data is (class << 4) | source
+ * 01 (0x40 | data) : IO exception. data is the exception number as
+ *                    defined by bit numbers in IIC_SR
+ * 10 (0x80 | data) : IPI. data is the IPI number (obtained from the priority)
+ *                    and node is always 0 (IPIs are per-cpu, their source is
+ *                    not relevant)
+ * 11 (0xc0 | data) : reserved
  *
- * A node consists of a Cell Broadband Engine and an optional
- * south bridge device providing a maximum of 64 IRQs.
- * The south bridge may be connected to either IOIF0
- * or IOIF1.
- * Each SPE is represented as three IRQ lines, one per
- * interrupt class.
- * 16 IRQ numbers are reserved for inter processor
- * interruptions, although these are only used in the
- * range of the first node.
+ * In addition, interrupt number 0x80000000 is defined as always invalid
+ * (that is the node field is expected to never extend to move than 23 bits)
  *
- * This scheme needs 128 IRQ numbers per BIF node ID,
- * which means that with the total of 512 lines
- * available, we can have a maximum of four nodes.
  */
 
 enum {
-	IIC_IRQ_INVALID		= 0xff,
-	IIC_IRQ_MAX		= 0x3f,
-	IIC_IRQ_EXT_IOIF0	= 0x20,
-	IIC_IRQ_EXT_IOIF1	= 0x2b,
-	IIC_IRQ_IPI0		= 0x40,
-	IIC_NUM_IPIS    	= 0x10, /* IRQs reserved for IPI */
-	IIC_SOURCE_COUNT	= 0x50,
+	IIC_IRQ_INVALID		= 0x80000000u,
+	IIC_IRQ_NODE_MASK	= 0x100,
+	IIC_IRQ_NODE_SHIFT	= 8,
+	IIC_IRQ_MAX		= 0x1ff,
+	IIC_IRQ_TYPE_MASK	= 0xc0,
+	IIC_IRQ_TYPE_NORMAL	= 0x00,
+	IIC_IRQ_TYPE_IOEXC	= 0x40,
+	IIC_IRQ_TYPE_IPI	= 0x80,
+	IIC_IRQ_CLASS_SHIFT	= 4,
+	IIC_IRQ_CLASS_0		= 0x00,
+	IIC_IRQ_CLASS_1		= 0x10,
+	IIC_IRQ_CLASS_2		= 0x20,
+	IIC_SOURCE_COUNT	= 0x200,
+
+	/* Here are defined the various source/dest units. Avoid using those
+	 * definitions if you can, they are mostly here for reference
+	 */
+	IIC_UNIT_SPU_0		= 0x4,
+	IIC_UNIT_SPU_1		= 0x7,
+	IIC_UNIT_SPU_2		= 0x3,
+	IIC_UNIT_SPU_3		= 0x8,
+	IIC_UNIT_SPU_4		= 0x2,
+	IIC_UNIT_SPU_5		= 0x9,
+	IIC_UNIT_SPU_6		= 0x1,
+	IIC_UNIT_SPU_7		= 0xa,
+	IIC_UNIT_IOC_0		= 0x0,
+	IIC_UNIT_IOC_1		= 0xb,
+	IIC_UNIT_THREAD_0	= 0xe, /* target only */
+	IIC_UNIT_THREAD_1	= 0xf, /* target only */
+	IIC_UNIT_IIC		= 0xe, /* source only (IO exceptions) */
+
+	/* Base numbers for the external interrupts */
+	IIC_IRQ_EXT_IOIF0	=
+		IIC_IRQ_TYPE_NORMAL | IIC_IRQ_CLASS_2 | IIC_UNIT_IOC_0,
+	IIC_IRQ_EXT_IOIF1	=
+		IIC_IRQ_TYPE_NORMAL | IIC_IRQ_CLASS_2 | IIC_UNIT_IOC_1,
+
+	/* Base numbers for the IIC_ISR interrupts */
+	IIC_IRQ_IOEX_TMI	= IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 63,
+	IIC_IRQ_IOEX_PMI	= IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 62,
+	IIC_IRQ_IOEX_ATI	= IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 61,
+	IIC_IRQ_IOEX_MATBFI	= IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 60,
+	IIC_IRQ_IOEX_ELDI	= IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 59,
+
+	/* Which bits in IIC_ISR are edge sensitive */
+	IIC_ISR_EDGE_MASK	= 0x4ul,
 };
 
 extern void iic_init_IRQ(void);
@@ -52,7 +80,6 @@ extern void iic_request_IPIs(void);
 extern void iic_setup_cpu(void);
 
 extern u8 iic_get_target_id(int cpu);
-extern struct irq_host *iic_get_irq_host(int node);
 
 extern void spider_init_IRQ(void);
 
Index: linux-cell/arch/powerpc/platforms/cell/spider-pic.c
===================================================================
--- linux-cell.orig/arch/powerpc/platforms/cell/spider-pic.c	2006-09-08 17:17:10.000000000 +1000
+++ linux-cell/arch/powerpc/platforms/cell/spider-pic.c	2006-09-29 14:37:00.000000000 +1000
@@ -240,10 +240,9 @@ static void spider_irq_cascade(unsigned 
 static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
 {
 	unsigned int virq;
-	u32 *imap, *tmp;
+	const u32 *imap, *tmp;
 	int imaplen, intsize, unit;
 	struct device_node *iic;
-	struct irq_host *iic_host;
 
 #if 0 /* Enable that when we have a way to retreive the node as well */
 	/* First, we check wether we have a real "interrupts" in the device
@@ -258,25 +257,25 @@ static unsigned int __init spider_find_c
 #endif
 
 	/* Now do the horrible hacks */
-	tmp = (u32 *)get_property(pic->of_node, "#interrupt-cells", NULL);
+	tmp = get_property(pic->of_node, "#interrupt-cells", NULL);
 	if (tmp == NULL)
 		return NO_IRQ;
 	intsize = *tmp;
-	imap = (u32 *)get_property(pic->of_node, "interrupt-map", &imaplen);
+	imap = get_property(pic->of_node, "interrupt-map", &imaplen);
 	if (imap == NULL || imaplen < (intsize + 1))
 		return NO_IRQ;
 	iic = of_find_node_by_phandle(imap[intsize]);
 	if (iic == NULL)
 		return NO_IRQ;
 	imap += intsize + 1;
-	tmp = (u32 *)get_property(iic, "#interrupt-cells", NULL);
+	tmp = get_property(iic, "#interrupt-cells", NULL);
 	if (tmp == NULL)
 		return NO_IRQ;
 	intsize = *tmp;
 	/* Assume unit is last entry of interrupt specifier */
 	unit = imap[intsize - 1];
 	/* Ok, we have a unit, now let's try to get the node */
-	tmp = (u32 *)get_property(iic, "ibm,interrupt-server-ranges", NULL);
+	tmp = get_property(iic, "ibm,interrupt-server-ranges", NULL);
 	if (tmp == NULL) {
 		of_node_put(iic);
 		return NO_IRQ;
@@ -289,11 +288,11 @@ static unsigned int __init spider_find_c
 	 * the iic host from the iic OF node, but that way I'm still compatible
 	 * with really really old old firmwares for which we don't have a node
 	 */
-	iic_host = iic_get_irq_host(pic->node_id);
-	if (iic_host == NULL)
-		return NO_IRQ;
 	/* Manufacture an IIC interrupt number of class 2 */
-	virq = irq_create_mapping(iic_host, 0x20 | unit);
+	virq = irq_create_mapping(NULL,
+				  (pic->node_id << IIC_IRQ_NODE_SHIFT) |
+				  (2 << IIC_IRQ_CLASS_SHIFT) |
+				  unit);
 	if (virq == NO_IRQ)
 		printk(KERN_ERR "spider_pic: failed to map cascade !");
 	return virq;
Index: linux-cell/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-cell.orig/arch/powerpc/platforms/cell/spu_base.c	2006-09-08 17:17:10.000000000 +1000
+++ linux-cell/arch/powerpc/platforms/cell/spu_base.c	2006-09-22 12:56:14.000000000 +1000
@@ -568,24 +568,23 @@ 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)
 {
-	struct irq_host *host;
 	unsigned int isrc;
 	u32 *tmp;
 
-	host = iic_get_irq_host(spu->node);
-	if (host == NULL)
-		return -ENODEV;
-
-	/* Get the interrupt source from the device-tree */
+	/* Get the interrupt source unit from the device-tree */
 	tmp = (u32 *)get_property(np, "isrc", NULL);
 	if (!tmp)
 		return -ENODEV;
-	spu->isrc = isrc = tmp[0];
+	isrc = tmp[0];
+
+	/* Add the node number */
+	isrc |= spu->node << IIC_IRQ_NODE_SHIFT;
+	spu->isrc = isrc;
 
 	/* Now map interrupts of all 3 classes */
-	spu->irqs[0] = irq_create_mapping(host, 0x00 | isrc);
-	spu->irqs[1] = irq_create_mapping(host, 0x10 | isrc);
-	spu->irqs[2] = irq_create_mapping(host, 0x20 | isrc);
+	spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc);
+	spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc);
+	spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc);
 
 	/* Right now, we only fail if class 2 failed */
 	return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;

^ permalink raw reply

* [PATCH] powerpc: cell spu problem state mapping updates
From: Benjamin Herrenschmidt @ 2006-09-29  5:10 UTC (permalink / raw)
  To: cbe-oss-dev@ozlabs.org; +Cc: linuxppc-dev list, Paul Mackerras, Arnd Bergmann

This patch adds a new "psmap" file to spufs that allows mmap of all of
the problem state mapping of SPEs. It is compatible with 64k pages. In
addition, it removes mmap ability of individual files when using 64k
pages, with the exception of signal1 and signal2 which will both map the
entire 64k page holding both registers. It also removes
CONFIG_SPUFS_MMAP as there is no point in not building mmap support in
spufs.

It goes along a separate patch to libspe implementing usage of that new
file to access problem state registers.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

Arnd: Unless I screwed up, this should be the same as the previous one I
sent you, with the addition of the changelog you requested and the
removal of the typo on WARRANTY.

Paul: If Arnd agrees, add that to your merge queue.

Index: linux-cell/arch/powerpc/platforms/cell/spufs/file.c
===================================================================
--- linux-cell.orig/arch/powerpc/platforms/cell/spufs/file.c	2006-09-29 15:04:30.000000000 +1000
+++ linux-cell/arch/powerpc/platforms/cell/spufs/file.c	2006-09-29 15:04:46.000000000 +1000
@@ -36,6 +36,8 @@
 
 #include "spufs.h"
 
+#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
+
 
 static int
 spufs_mem_open(struct inode *inode, struct file *file)
@@ -88,7 +90,6 @@ spufs_mem_write(struct file *file, const
 	return ret;
 }
 
-#ifdef CONFIG_SPUFS_MMAP
 static struct page *
 spufs_mem_mmap_nopage(struct vm_area_struct *vma,
 		      unsigned long address, int *type)
@@ -133,22 +134,19 @@ spufs_mem_mmap(struct file *file, struct
 	vma->vm_ops = &spufs_mem_mmap_vmops;
 	return 0;
 }
-#endif
 
 static struct file_operations spufs_mem_fops = {
 	.open	 = spufs_mem_open,
 	.read    = spufs_mem_read,
 	.write   = spufs_mem_write,
 	.llseek  = generic_file_llseek,
-#ifdef CONFIG_SPUFS_MMAP
 	.mmap    = spufs_mem_mmap,
-#endif
 };
 
-#ifdef CONFIG_SPUFS_MMAP
 static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
 				    unsigned long address,
-				    int *type, unsigned long ps_offs)
+				    int *type, unsigned long ps_offs,
+				    unsigned long ps_size)
 {
 	struct page *page = NOPAGE_SIGBUS;
 	int fault_type = VM_FAULT_SIGBUS;
@@ -158,7 +156,7 @@ static struct page *spufs_ps_nopage(stru
 	int ret;
 
 	offset += vma->vm_pgoff << PAGE_SHIFT;
-	if (offset >= 0x4000)
+	if (offset >= ps_size)
 		goto out;
 
 	ret = spu_acquire_runnable(ctx);
@@ -179,10 +177,11 @@ static struct page *spufs_ps_nopage(stru
 	return page;
 }
 
+#if SPUFS_MMAP_4K
 static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma,
 					   unsigned long address, int *type)
 {
-	return spufs_ps_nopage(vma, address, type, 0x4000);
+	return spufs_ps_nopage(vma, address, type, 0x4000, 0x1000);
 }
 
 static struct vm_operations_struct spufs_cntl_mmap_vmops = {
@@ -191,17 +190,12 @@ static struct vm_operations_struct spufs
 
 /*
  * mmap support for problem state control area [0x4000 - 0x4fff].
- * Mapping this area requires that the application have CAP_SYS_RAWIO,
- * as these registers require special care when read/writing.
  */
 static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -209,7 +203,9 @@ static int spufs_cntl_mmap(struct file *
 	vma->vm_ops = &spufs_cntl_mmap_vmops;
 	return 0;
 }
-#endif
+#else /* SPUFS_MMAP_4K */
+#define spufs_cntl_mmap NULL
+#endif /* !SPUFS_MMAP_4K */
 
 static int spufs_cntl_open(struct inode *inode, struct file *file)
 {
@@ -242,9 +238,7 @@ static struct file_operations spufs_cntl
 	.open = spufs_cntl_open,
 	.read = spufs_cntl_read,
 	.write = spufs_cntl_write,
-#ifdef CONFIG_SPUFS_MMAP
 	.mmap = spufs_cntl_mmap,
-#endif
 };
 
 static int
@@ -657,11 +651,19 @@ static ssize_t spufs_signal1_write(struc
 	return 4;
 }
 
-#ifdef CONFIG_SPUFS_MMAP
 static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma,
 					      unsigned long address, int *type)
 {
-	return spufs_ps_nopage(vma, address, type, 0x14000);
+#if PAGE_SIZE == 0x1000
+	return spufs_ps_nopage(vma, address, type, 0x14000, 0x1000);
+#elif PAGE_SIZE == 0x10000
+	/* For 64k pages, both signal1 and signal2 can be used to mmap the whole
+	 * signal 1 and 2 area
+	 */
+	return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
+#else
+#error unsupported page size
+#endif
 }
 
 static struct vm_operations_struct spufs_signal1_mmap_vmops = {
@@ -680,15 +682,12 @@ static int spufs_signal1_mmap(struct fil
 	vma->vm_ops = &spufs_signal1_mmap_vmops;
 	return 0;
 }
-#endif
 
 static struct file_operations spufs_signal1_fops = {
 	.open = spufs_signal1_open,
 	.read = spufs_signal1_read,
 	.write = spufs_signal1_write,
-#ifdef CONFIG_SPUFS_MMAP
 	.mmap = spufs_signal1_mmap,
-#endif
 };
 
 static int spufs_signal2_open(struct inode *inode, struct file *file)
@@ -743,11 +742,20 @@ static ssize_t spufs_signal2_write(struc
 	return 4;
 }
 
-#ifdef CONFIG_SPUFS_MMAP
+#if SPUFS_MMAP_4K
 static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma,
 					      unsigned long address, int *type)
 {
-	return spufs_ps_nopage(vma, address, type, 0x1c000);
+#if PAGE_SIZE == 0x1000
+	return spufs_ps_nopage(vma, address, type, 0x1c000, 0x1000);
+#elif PAGE_SIZE == 0x10000
+	/* For 64k pages, both signal1 and signal2 can be used to mmap the whole
+	 * signal 1 and 2 area
+	 */
+	return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
+#else
+#error unsupported page size
+#endif
 }
 
 static struct vm_operations_struct spufs_signal2_mmap_vmops = {
@@ -767,15 +775,15 @@ static int spufs_signal2_mmap(struct fil
 	vma->vm_ops = &spufs_signal2_mmap_vmops;
 	return 0;
 }
-#endif
+#else /* SPUFS_MMAP_4K */
+#define spufs_signal2_mmap NULL
+#endif /* !SPUFS_MMAP_4K */
 
 static struct file_operations spufs_signal2_fops = {
 	.open = spufs_signal2_open,
 	.read = spufs_signal2_read,
 	.write = spufs_signal2_write,
-#ifdef CONFIG_SPUFS_MMAP
 	.mmap = spufs_signal2_mmap,
-#endif
 };
 
 static void spufs_signal1_type_set(void *data, u64 val)
@@ -824,11 +832,11 @@ static u64 spufs_signal2_type_get(void *
 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
 					spufs_signal2_type_set, "%llu");
 
-#ifdef CONFIG_SPUFS_MMAP
+#if SPUFS_MMAP_4K
 static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma,
 					   unsigned long address, int *type)
 {
-	return spufs_ps_nopage(vma, address, type, 0x0000);
+	return spufs_ps_nopage(vma, address, type, 0x0000, 0x1000);
 }
 
 static struct vm_operations_struct spufs_mss_mmap_vmops = {
@@ -837,17 +845,12 @@ static struct vm_operations_struct spufs
 
 /*
  * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
- * Mapping this area requires that the application have CAP_SYS_RAWIO,
- * as these registers require special care when read/writing.
  */
 static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -855,7 +858,9 @@ static int spufs_mss_mmap(struct file *f
 	vma->vm_ops = &spufs_mss_mmap_vmops;
 	return 0;
 }
-#endif
+#else /* SPUFS_MMAP_4K */
+#define spufs_mss_mmap NULL
+#endif /* !SPUFS_MMAP_4K */
 
 static int spufs_mss_open(struct inode *inode, struct file *file)
 {
@@ -867,17 +872,54 @@ static int spufs_mss_open(struct inode *
 
 static struct file_operations spufs_mss_fops = {
 	.open	 = spufs_mss_open,
-#ifdef CONFIG_SPUFS_MMAP
 	.mmap	 = spufs_mss_mmap,
-#endif
+};
+
+static struct page *spufs_psmap_mmap_nopage(struct vm_area_struct *vma,
+					   unsigned long address, int *type)
+{
+	return spufs_ps_nopage(vma, address, type, 0x0000, 0x20000);
+}
+
+static struct vm_operations_struct spufs_psmap_mmap_vmops = {
+	.nopage = spufs_psmap_mmap_nopage,
+};
+
+/*
+ * mmap support for full problem state area [0x00000 - 0x1ffff].
+ */
+static int spufs_psmap_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
+
+	vma->vm_ops = &spufs_psmap_mmap_vmops;
+	return 0;
+}
+
+static int spufs_psmap_open(struct inode *inode, struct file *file)
+{
+	struct spufs_inode_info *i = SPUFS_I(inode);
+
+	file->private_data = i->i_ctx;
+	return nonseekable_open(inode, file);
+}
+
+static struct file_operations spufs_psmap_fops = {
+	.open	 = spufs_psmap_open,
+	.mmap	 = spufs_psmap_mmap,
 };
 
 
-#ifdef CONFIG_SPUFS_MMAP
+#if SPUFS_MMAP_4K
 static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
 					   unsigned long address, int *type)
 {
-	return spufs_ps_nopage(vma, address, type, 0x3000);
+	return spufs_ps_nopage(vma, address, type, 0x3000, 0x1000);
 }
 
 static struct vm_operations_struct spufs_mfc_mmap_vmops = {
@@ -886,17 +928,12 @@ static struct vm_operations_struct spufs
 
 /*
  * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
- * Mapping this area requires that the application have CAP_SYS_RAWIO,
- * as these registers require special care when read/writing.
  */
 static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -904,7 +941,9 @@ static int spufs_mfc_mmap(struct file *f
 	vma->vm_ops = &spufs_mfc_mmap_vmops;
 	return 0;
 }
-#endif
+#else /* SPUFS_MMAP_4K */
+#define spufs_mfc_mmap NULL
+#endif /* !SPUFS_MMAP_4K */
 
 static int spufs_mfc_open(struct inode *inode, struct file *file)
 {
@@ -1194,9 +1233,7 @@ static struct file_operations spufs_mfc_
 	.flush	 = spufs_mfc_flush,
 	.fsync	 = spufs_mfc_fsync,
 	.fasync	 = spufs_mfc_fasync,
-#ifdef CONFIG_SPUFS_MMAP
 	.mmap	 = spufs_mfc_mmap,
-#endif
 };
 
 static void spufs_npc_set(void *data, u64 val)
@@ -1368,5 +1405,6 @@ struct tree_descr spufs_dir_contents[] =
 	{ "event_mask", &spufs_event_mask_ops, 0666, },
 	{ "srr0", &spufs_srr0_ops, 0666, },
 	{ "phys-id", &spufs_id_ops, 0666, },
+	{ "psmap", &spufs_psmap_fops, 0666, },
 	{},
 };
Index: linux-cell/arch/powerpc/platforms/cell/Kconfig
===================================================================
--- linux-cell.orig/arch/powerpc/platforms/cell/Kconfig	2006-09-29 15:04:30.000000000 +1000
+++ linux-cell/arch/powerpc/platforms/cell/Kconfig	2006-09-29 15:04:46.000000000 +1000
@@ -16,11 +16,6 @@ config SPU_BASE
 	bool
 	default n
 
-config SPUFS_MMAP
-	bool
-	depends on SPU_FS && SPARSEMEM
-	default y
-
 config CBE_RAS
 	bool "RAS features for bare metal Cell BE"
 	default y

^ permalink raw reply

* RE: [PATCH 11/12] Add MPC8360EMDS default dts file
From: Li Yang-r58472 @ 2006-09-29  7:46 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, paulus
In-Reply-To: <20060928173816.168d4cc2@vitb.ru.mvista.com>

> -----Original Message-----
> From: Vitaly Bordug [mailto:vbordug@ru.mvista.com]
> Sent: Thursday, September 28, 2006 9:38 PM
> To: Li Yang-r58472
> Cc: paulus@samba.org; galak@kernel.crashing.org;
linuxppc-dev@ozlabs.org
> Subject: Re: [PATCH 11/12] Add MPC8360EMDS default dts file
>=20
> On Thu, 28 Sep 2006 16:19:30 +0800
> Li Yang <leoli@freescale.com> wrote:
>=20
> > +		muram@10000 {
> > +			device_type =3D "muram";
> > +			ranges =3D <0 00010000 0000c000>;
> > +
> > +			data-only@0{
> > +				reg =3D <0 c000>;
> > +			};
> > +		};
> > +
>=20
> Why not to have reg property, showing the allocation ranges? data-only
seems
> redundant as a node...

The reason why I added this node is to put the address under "muram"
bus.  If I put the reg in muram node, the address will be offset to QE
base.  But what the driver needs is the offset to MURAM base.  IMHO,
this approach is clearer logically.

- Leo

^ permalink raw reply

* Re: [PATCH] Cell interrupt rework (final)
From: Arnd Bergmann @ 2006-09-29  7:51 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev list, Paul Mackerras, cbe-oss-dev@ozlabs.org
In-Reply-To: <1159506029.15792.18.camel@localhost.localdomain>

On Friday 29 September 2006 07:00, Benjamin Herrenschmidt wrote:
> This patch reworks the cell iic interrupt handling so that:
>=20
> =A0- Node ID is back in the interrupt number (only one IRQ host is created
> for all nodes). This allows interrupts from sources on another node to
> be routed non-locally. This will allow possibly one day to fix maxcpus=3D1
> or 2 and still get interrupts from devices on BE 1. (A bit more fixing
> is needed for that) and it will allow us to implement actual affinity
> control of external interrupts.
>=20
> =A0- Added handling of the IO exceptions interrupts (badly named, but I
> re-used the name initially used by STI). Those are the interrupts
> exposed by IIC_ISR and IIC_IRR, such as the IOC translation exception,
> performance monitor, etc... Those get their special numbers in the IRQ
> number space and are internally implemented as a cascade on unit 0xe,
> class 1 of each node.
>=20
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

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

^ permalink raw reply

* Re: [PATCH] powerpc: cell spu problem state mapping updates
From: Arnd Bergmann @ 2006-09-29  7:52 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev list, Paul Mackerras, cbe-oss-dev@ozlabs.org
In-Reply-To: <1159506605.15792.24.camel@localhost.localdomain>

On Friday 29 September 2006 07:10, Benjamin Herrenschmidt wrote:
> This patch adds a new "psmap" file to spufs that allows mmap of all of
> the problem state mapping of SPEs. It is compatible with 64k pages. In
> addition, it removes mmap ability of individual files when using 64k
> pages, with the exception of signal1 and signal2 which will both map the
> entire 64k page holding both registers. It also removes
> CONFIG_SPUFS_MMAP as there is no point in not building mmap support in
> spufs.
> 
> It goes along a separate patch to libspe implementing usage of that new
> file to access problem state registers.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

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

^ permalink raw reply

* [PATCH] IBM GPIO driver for PowerPC 4xx is back from the dead
From: Jean-Baptiste Maneyrol @ 2006-09-29  7:46 UTC (permalink / raw)
  To: linuxppc-embedded

Here is a patch for linux 2.6.18 that makes come back the old ibm gpio
driver from 2.6.10.

It is mainly useful for compatibility with old linux 2.4 from Montavista
I think, because direct memory access seems the new way to go.

Signed-off-by: Jean-Baptiste Maneyrol
<jean-baptiste.maneyrol@teamlog.com>


Jean-Baptiste Maneyrol
Teamlog - France

^ permalink raw reply

* [PATCH] IBM GPIO driver for PowerPC 4xx is back from the dead
From: Jean-Baptiste Maneyrol @ 2006-09-29  8:29 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 346 bytes --]

Here is a patch for linux 2.6.18 that makes come back the old ibm gpio
driver from 2.6.10.

It is mainly useful for compatibility with old linux 2.4 from Montavista
I think, because direct memory access seems the new way to go.

Signed-off-by: Jean-Baptiste Maneyrol
<jean-baptiste.maneyrol@teamlog.com>


Jean-Baptiste Maneyrol
Teamlog - France

[-- Attachment #2: ibm_gpio.patch --]
[-- Type: text/x-patch, Size: 12617 bytes --]

diff -Naur linux-2.6.18_gpio/drivers/char/ibm_gpio.c tlgate_gpio/drivers/char/ibm_gpio.c
--- linux-2.6.18_gpio/drivers/char/ibm_gpio.c	1970-01-01 01:00:00.000000000 +0100
+++ tlgate_gpio/drivers/char/ibm_gpio.c	2006-09-28 16:46:42.000000000 +0200
@@ -0,0 +1,349 @@
+/*
+ * FILE NAME ibm_gpio.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ *  API for IBM PowerPC 4xx GPIO device.
+ *  Driver for IBM PowerPC 4xx GPIO device.
+ *
+ *  Armin Kuster akuster@pacbell.net
+ *  Sept, 2001
+ *
+ *  Orignial driver
+ *  Author: MontaVista Software, Inc.  <source@mvista.com>
+ *          Frank Rowand <frank_rowand@mvista.com>
+ *          Debbie Chu   <debbie_chu@mvista.com>
+ *
+ * Copyright 2000,2001,2002 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE	LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *	TODO: devfs
+ *
+ *	Version: 02/01/12 - Armin
+ *			 converted to ocp and using ioremap
+ *
+ *	1.2 02/21/01 - Armin
+ *		minor compiler warning fixes
+ *
+ *	1.3 02/22/01 - Armin
+ *		added apm
+ *
+ *	1.4 05/07/02 - Armin/David Mueller
+ *		coverted to core_ocp[];
+ *
+ *	1.5 05/25/02 - Armin
+ *	 name change from *_driver to *_dev
+ *
+ *	1.6 06/04/02 - Matt Porter
+ *	ioremap paddr. Comment as 4xx generic driver.
+ *	Fix header to be userland safe and locate in
+ *	an accessible area.  Add ioctl to configure
+ *	multiplexed GPIO pins.
+ *
+ *	1.7 07/25/02 - Armin
+ *	added CPM to enable/disable in init/exit
+ *
+ */
+
+#define VUFX "07.25.02"
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <asm/ibm_gpio.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/ibm4xx.h>
+
+struct miscdevice ibm_gpio_miscdev;
+static struct gpio_regs *gpiop;
+
+int
+ibm_gpio_config(__u32 device, __u32 mask, __u32 data)
+{
+	u32 cfg_reg;
+
+	if (device != 0)
+		return -ENXIO;
+
+#ifdef CONFIG_40x
+#ifdef DCRN_CHCR0
+	/*
+	 * PPC405 uses CPC0_CR0 to select multiplexed GPIO pins.
+	 */
+	cfg_reg = mfdcr(DCRN_CHCR0);
+	cfg_reg = (cfg_reg & ~mask) | (data & mask);
+	mtdcr(DCRN_CHCR0, cfg_reg);
+#endif
+#elif CONFIG_440GP
+	/*
+	 * PPC440GP uses CPC0_GPIO to select multiplexed GPIO pins.
+	 */
+	cfg_reg = mfdcr(DCRN_CPC0_GPIO);
+	cfg_reg = (cfg_reg & ~mask) | (data & mask);
+	mtdcr(DCRN_CPC0_GPIO, cfg_reg);
+#elif CONFIG_440GX
+	/*
+	 * PPC440GX uses SDR0_PFC0 to select multiplexed GPIO pins
+	 */
+	cfg_reg = SDR_READ(DCRN_SDR_PFC0);
+	cfg_reg = (cfg_reg & ~mask) | (data & mask);
+	SDR_WRITE(DCRN_SDR_PFC0, cfg_reg);
+#else
+#error This driver is only supported on PPC40x and PPC440 CPUs
+#endif
+
+	return 0;
+}
+
+int
+ibm_gpio_tristate(__u32 device, __u32 mask, __u32 data)
+{
+	if (device != 0)
+		return -ENXIO;
+	gpiop->tcr = (gpiop->tcr & ~mask) | (data & mask);
+	return 0;
+}
+
+int
+ibm_gpio_open_drain(__u32 device, __u32 mask, __u32 data)
+{
+	if (device != 0)
+		return -ENXIO;
+	gpiop->odr = (gpiop->odr & ~mask) | (data & mask);
+
+	return 0;
+}
+
+int
+ibm_gpio_in(__u32 device, __u32 mask, volatile __u32 * data)
+{
+	if (device != 0)
+		return -ENXIO;
+	gpiop->tcr = gpiop->tcr & ~mask;
+	eieio();
+
+	/*
+	   ** If the previous state was OUT, and gpiop->ir is read once, then the
+	   ** data that was being OUTput will be read.  One way to get the right
+	   ** data is to read gpiop->ir twice.
+	 */
+
+	*data = gpiop->ir;
+	*data = gpiop->ir & mask;
+	eieio();
+	return 0;
+}
+
+int
+ibm_gpio_out(__u32 device, __u32 mask, __u32 data)
+{
+	if (device != 0)
+		return -ENXIO;
+	gpiop->or = (gpiop->or & ~mask) | (data & mask);
+	eieio();
+	gpiop->tcr = gpiop->tcr | mask;
+	eieio();
+	return 0;
+}
+
+static int
+ibm_gpio_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int
+ibm_gpio_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int
+ibm_gpio_ioctl(struct inode *inode, struct file *file,
+	       unsigned int cmd, unsigned long arg)
+{
+	static struct ibm_gpio_ioctl_data ioctl_data;
+	int status;
+
+	switch (cmd) {
+	case IBMGPIO_IN:
+		if (copy_from_user(&ioctl_data,
+				   (struct ibm_gpio_ioctl_data *) arg,
+				   sizeof (ioctl_data))) {
+			return -EFAULT;
+		}
+
+		status = ibm_gpio_in(ioctl_data.device,
+				     ioctl_data.mask, &ioctl_data.data);
+		if (status != 0)
+			return status;
+
+		if (copy_to_user((struct ibm_gpio_ioctl_data *) arg,
+				 &ioctl_data, sizeof (ioctl_data))) {
+			return -EFAULT;
+		}
+
+		break;
+
+	case IBMGPIO_OUT:
+		if (copy_from_user(&ioctl_data,
+				   (struct ibm_gpio_ioctl_data *) arg,
+				   sizeof (ioctl_data))) {
+			return -EFAULT;
+		}
+
+		return ibm_gpio_out(ioctl_data.device,
+				    ioctl_data.mask, ioctl_data.data);
+
+		break;
+
+	case IBMGPIO_OPEN_DRAIN:
+		if (copy_from_user(&ioctl_data,
+				   (struct ibm_gpio_ioctl_data *) arg,
+				   sizeof (ioctl_data))) {
+			return -EFAULT;
+		}
+
+		return ibm_gpio_open_drain(ioctl_data.device,
+					   ioctl_data.mask, ioctl_data.data);
+
+		break;
+
+	case IBMGPIO_TRISTATE:
+		if (copy_from_user(&ioctl_data,
+				   (struct ibm_gpio_ioctl_data *) arg,
+				   sizeof (ioctl_data)))
+			return -EFAULT;
+
+		return ibm_gpio_tristate(ioctl_data.device,
+					 ioctl_data.mask, ioctl_data.data);
+
+		break;
+
+	case IBMGPIO_CFG:
+		if (copy_from_user(&ioctl_data,
+				   (struct ibm_gpio_ioctl_data *) arg,
+				   sizeof (ioctl_data)))
+			return -EFAULT;
+
+		return ibm_gpio_config(ioctl_data.device,
+				ioctl_data.mask, ioctl_data.data);
+
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+
+	}
+	return 0;
+}
+
+static struct file_operations ibm_gpio_fops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= ibm_gpio_ioctl,
+	.open		= ibm_gpio_open,
+	.release	= ibm_gpio_release,
+};
+
+static int __init
+ibm_gpio_probe(struct ocp_device *ocp)
+{
+	ibm_gpio_miscdev.minor = GPIO_MINOR;
+	ibm_gpio_miscdev.name = ocp->name;
+	ibm_gpio_miscdev.fops = &ibm_gpio_fops;
+	misc_register(&ibm_gpio_miscdev);
+
+	if (!request_mem_region(ocp->def->paddr, sizeof(struct gpio_regs), "ibm_gpio"))
+		return -EBUSY;
+	
+	gpiop = (struct gpio_regs *) ioremap(ocp->def->paddr,
+			sizeof(struct gpio_regs));
+	if (!gpiop) {
+		release_mem_region(ocp->def->paddr, sizeof(struct gpio_regs));
+		return -ENOMEM;
+	}
+	
+	printk("GPIO #%d at 0x%lx\n", ocp->def->index,
+			(unsigned long) gpiop);
+
+	return 0;
+}
+
+static void __exit
+ibm_gpio_remove(struct ocp_device *ocp)
+{
+	misc_deregister(&ibm_gpio_miscdev);
+
+	iounmap(gpiop);
+	gpiop = NULL;
+	
+	release_mem_region(ocp->def->paddr, sizeof(struct gpio_regs));
+}
+
+static struct ocp_device_id ibm_gpio_ids[] __devinitdata =
+{
+	{ .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_GPIO },
+	{ .vendor = OCP_VENDOR_INVALID }
+};
+
+MODULE_DEVICE_TABLE(ocp, ibm_gpio_ids);
+
+static struct ocp_driver ibm_gpio_driver =
+{
+	.name           = "ibm_gpio",
+	.id_table       = ibm_gpio_ids,
+	.probe          = ibm_gpio_probe,
+	.remove         = __devexit_p(ibm_gpio_remove),
+#if defined(CONFIG_PM)
+	.suspend        = NULL,
+	.resume         = NULL,
+#endif
+};
+
+static int __init
+ibm_gpio_init(void)
+{
+	printk("IBM GPIO driver version %s\n", VUFX);
+	return ocp_register_driver(&ibm_gpio_driver);
+}
+
+static void __exit
+ibm_gpio_exit(void)
+{
+	ocp_unregister_driver(&ibm_gpio_driver);
+}
+
+module_init(ibm_gpio_init);
+module_exit(ibm_gpio_exit);
+
+EXPORT_SYMBOL(ibm_gpio_tristate);
+EXPORT_SYMBOL(ibm_gpio_open_drain);
+EXPORT_SYMBOL(ibm_gpio_in);
+EXPORT_SYMBOL(ibm_gpio_out);
+
+MODULE_LICENSE("GPL");
diff -Naur linux-2.6.18_gpio/drivers/char/Kconfig tlgate_gpio/drivers/char/Kconfig
--- linux-2.6.18_gpio/drivers/char/Kconfig	2006-09-28 16:47:53.000000000 +0200
+++ tlgate_gpio/drivers/char/Kconfig	2006-09-28 16:50:15.000000000 +0200
@@ -936,6 +936,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called mwave.
 
+config IBM_GPIO
+	tristate "IBM PowerPC 4xx GPIO Support"
+	depends on IBM_OCP
+	help
+	  Give userspace access to the GPIO pins on the PowerPC
+	  4xx processors.
+	
+	  If compiled as a module, it will be called ibm_gpio.
+
 config SCx200_GPIO
 	tristate "NatSemi SCx200 GPIO Support"
 	depends on SCx200
diff -Naur linux-2.6.18_gpio/drivers/char/Makefile tlgate_gpio/drivers/char/Makefile
--- linux-2.6.18_gpio/drivers/char/Makefile	2006-09-28 16:47:57.000000000 +0200
+++ tlgate_gpio/drivers/char/Makefile	2006-09-28 16:46:42.000000000 +0200
@@ -81,6 +81,7 @@
 obj-$(CONFIG_PPDEV)		+= ppdev.o
 obj-$(CONFIG_NWBUTTON)		+= nwbutton.o
 obj-$(CONFIG_NWFLASH)		+= nwflash.o
+obj-$(CONFIG_IBM_GPIO)		+= ibm_gpio.o
 obj-$(CONFIG_SCx200_GPIO)	+= scx200_gpio.o
 obj-$(CONFIG_PC8736x_GPIO)	+= pc8736x_gpio.o
 obj-$(CONFIG_NSC_GPIO)		+= nsc_gpio.o
diff -Naur linux-2.6.18_gpio/include/asm-ppc/ibm_gpio.h tlgate_gpio/include/asm-ppc/ibm_gpio.h
--- linux-2.6.18_gpio/include/asm-ppc/ibm_gpio.h	1970-01-01 01:00:00.000000000 +0100
+++ tlgate_gpio/include/asm-ppc/ibm_gpio.h	2006-09-28 16:47:09.000000000 +0200
@@ -0,0 +1,71 @@
+/*
+ * FILE NAME ibm_ocp_gpio.h
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Generic gpio.
+ *
+ *  Armin Kuster akuster@pacbell.net
+ *  Sept, 2001
+ *
+ *  Orignial driver
+ *  Author: MontaVista Software, Inc.  <source@mvista.com>
+ *          Frank Rowand <frank_rowand@mvista.com>
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __IBM_OCP_GPIO_H
+#define __IBM_OCP_GPIO_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+
+typedef struct gpio_regs {
+	u32 or;
+	u32 tcr;
+	u32 pad[4];
+	u32 odr;
+	u32 ir;
+} gpio_t;
+
+#define GPIO_MINOR		185
+
+#endif		/* __KERNEL__ */
+
+struct ibm_gpio_ioctl_data {
+        __u32 device;
+        __u32 mask;
+        __u32 data;
+};
+
+#define IBMGPIO_IOCTL_BASE	'Z'
+
+#define IBMGPIO_IN		_IOWR(IBMGPIO_IOCTL_BASE, 0, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_OUT		_IOW (IBMGPIO_IOCTL_BASE, 1, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_OPEN_DRAIN	_IOW (IBMGPIO_IOCTL_BASE, 2, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_TRISTATE	_IOW (IBMGPIO_IOCTL_BASE, 3, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_CFG		_IOW (IBMGPIO_IOCTL_BASE, 4, struct ibm_gpio_ioctl_data)
+
+#endif

^ permalink raw reply

* RE: Running Linux on Avnet's FX12 Evaluation Board
From: Jaap de Jong @ 2006-09-29  8:17 UTC (permalink / raw)
  To: linuxppc-embedded

Hi,

I had to declare the ddr_sdram as plb_ddr instead of opb_ddr...

Jaap


-----Original Message-----
Hello,

I am trying to run a Linuxppc 2.4 kernel (20051021) on an IBM Powerpc
405, I have compiled it according to the instructions on
http://www.itee.uq.edu.au/~jwilliams/mblaze-uclinux/uclinux_powerpc/#lin
uxppc-2,
I load it into the ram using the Xilinx Microprocessor Debug (XMD)
Engine and try to run it, but it seems to have some trouble with the
memory:

^ permalink raw reply

* Re: [PATCH] IBM GPIO driver for PowerPC 4xx is back from the dead
From: Arnd Bergmann @ 2006-09-29  9:06 UTC (permalink / raw)
  To: linuxppc-embedded; +Cc: Jean-Baptiste Maneyrol
In-Reply-To: <1159518565.9269.1.camel@jb-portable>

On Friday 29 September 2006 10:29, Jean-Baptiste Maneyrol wrote:
> diff -Naur linux-2.6.18_gpio/drivers/char/ibm_gpio.c tlgate_gpio/drivers/=
char/ibm_gpio.c
> --- linux-2.6.18_gpio/drivers/char/ibm_gpio.c=A0=A0=A01970-01-01 01:00:00=
=2E000000000 +0100
> +++ tlgate_gpio/drivers/char/ibm_gpio.c=A02006-09-28 16:46:42.000000000 +=
0200
> @@ -0,0 +1,349 @@
> +/*
> + * FILE NAME ibm_gpio.c

<insert usual comment about removing the file name from the file>

> + * BRIEF MODULE DESCRIPTION
> + * =A0API for IBM PowerPC 4xx GPIO device.
> + * =A0Driver for IBM PowerPC 4xx GPIO device.
> + *
> + * =A0Armin Kuster akuster@pacbell.net
> + * =A0Sept, 2001
> + *
> + * =A0Orignial driver
> + * =A0Author: MontaVista Software, Inc. =A0<source@mvista.com>
> + * =A0 =A0 =A0 =A0 =A0Frank Rowand <frank_rowand@mvista.com>
> + * =A0 =A0 =A0 =A0 =A0Debbie Chu =A0 <debbie_chu@mvista.com>
> + *
> + * Copyright 2000,2001,2002 MontaVista Software Inc.

Any new copyright year?


> + *=A0=A0=A0=A0=A0TODO: devfs

surely not.

> + *=A0=A0=A0=A0=A0Version: 02/01/12 - Armin
> + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 conver=
ted to ocp and using ioremap
> + *
> + *=A0=A0=A0=A0=A01.2 02/21/01 - Armin
> + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0minor compiler warning fixes
> + *
> + *=A0=A0=A0=A0=A01.3 02/22/01 - Armin
> + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0added apm
> + *
> + *=A0=A0=A0=A0=A01.4 05/07/02 - Armin/David Mueller
> + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0coverted to core_ocp[];
> + *
> + *=A0=A0=A0=A0=A01.5 05/25/02 - Armin
> + *=A0=A0=A0=A0=A0 name change from *_driver to *_dev
> + *
> + *=A0=A0=A0=A0=A01.6 06/04/02 - Matt Porter
> + *=A0=A0=A0=A0=A0ioremap paddr. Comment as 4xx generic driver.
> + *=A0=A0=A0=A0=A0Fix header to be userland safe and locate in
> + *=A0=A0=A0=A0=A0an accessible area. =A0Add ioctl to configure
> + *=A0=A0=A0=A0=A0multiplexed GPIO pins.
> + *
> + *=A0=A0=A0=A0=A01.7 07/25/02 - Armin
> + *=A0=A0=A0=A0=A0added CPM to enable/disable in init/exit

kill that changelog

> + */
> +
> +#define VUFX "07.25.02"

should be MODULE_VERSION()

> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/miscdevice.h>
> +#include <linux/init.h>
> +#include <linux/ioctl.h>
> +#include <linux/fs.h>
> +#include <asm/ibm_gpio.h>
> +#include <asm/uaccess.h>
> +#include <asm/io.h>
> +#include <asm/machdep.h>
> +#include <asm/ocp.h>
> +#include <asm/ibm4xx.h>
> +
> +struct miscdevice ibm_gpio_miscdev;
> +static struct gpio_regs *gpiop;
> +
> +int
> +ibm_gpio_config(__u32 device, __u32 mask, __u32 data)

any symbols should be static. Function arguments are not
visible to users, so they should be 'u32' instead of '__u32'.

> +{
> +=A0=A0=A0=A0=A0=A0=A0u32 cfg_reg;
> +
> +=A0=A0=A0=A0=A0=A0=A0if (device !=3D 0)
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return -ENXIO;
> +
> +#ifdef CONFIG_40x
> +#ifdef DCRN_CHCR0
> +=A0=A0=A0=A0=A0=A0=A0/*
> +=A0=A0=A0=A0=A0=A0=A0 * PPC405 uses CPC0_CR0 to select multiplexed GPIO =
pins.
> +=A0=A0=A0=A0=A0=A0=A0 */
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D mfdcr(DCRN_CHCR0);
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D (cfg_reg & ~mask) | (data & mask);
> +=A0=A0=A0=A0=A0=A0=A0mtdcr(DCRN_CHCR0, cfg_reg);
> +#endif
> +#elif CONFIG_440GP
> +=A0=A0=A0=A0=A0=A0=A0/*
> +=A0=A0=A0=A0=A0=A0=A0 * PPC440GP uses CPC0_GPIO to select multiplexed GP=
IO pins.
> +=A0=A0=A0=A0=A0=A0=A0 */
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D mfdcr(DCRN_CPC0_GPIO);
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D (cfg_reg & ~mask) | (data & mask);
> +=A0=A0=A0=A0=A0=A0=A0mtdcr(DCRN_CPC0_GPIO, cfg_reg);
> +#elif CONFIG_440GX
> +=A0=A0=A0=A0=A0=A0=A0/*
> +=A0=A0=A0=A0=A0=A0=A0 * PPC440GX uses SDR0_PFC0 to select multiplexed GP=
IO pins
> +=A0=A0=A0=A0=A0=A0=A0 */
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D SDR_READ(DCRN_SDR_PFC0);
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D (cfg_reg & ~mask) | (data & mask);
> +=A0=A0=A0=A0=A0=A0=A0SDR_WRITE(DCRN_SDR_PFC0, cfg_reg);
> +#else
> +#error This driver is only supported on PPC40x and PPC440 CPUs
> +#endif

This prevents building a single kernel for multiple 440 version.
Please use a run-time check, or better get the necessary information
from the device tree.

> +int
> +ibm_gpio_in(__u32 device, __u32 mask, volatile __u32 * data)
> +{
> +=A0=A0=A0=A0=A0=A0=A0if (device !=3D 0)
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return -ENXIO;
> +=A0=A0=A0=A0=A0=A0=A0gpiop->tcr =3D gpiop->tcr & ~mask;
> +=A0=A0=A0=A0=A0=A0=A0eieio();
> +
> +=A0=A0=A0=A0=A0=A0=A0/*
> +=A0=A0=A0=A0=A0=A0=A0 =A0 ** If the previous state was OUT, and gpiop->i=
r is read once, then the
> +=A0=A0=A0=A0=A0=A0=A0 =A0 ** data that was being OUTput will be read. =
=A0One way to get the right
> +=A0=A0=A0=A0=A0=A0=A0 =A0 ** data is to read gpiop->ir twice.
> +=A0=A0=A0=A0=A0=A0=A0 */
> +
> +=A0=A0=A0=A0=A0=A0=A0*data =3D gpiop->ir;
> +=A0=A0=A0=A0=A0=A0=A0*data =3D gpiop->ir & mask;
> +=A0=A0=A0=A0=A0=A0=A0eieio();
> +=A0=A0=A0=A0=A0=A0=A0return 0;
> +}

Don't just assign *data, make that an __iomem pointer and use
an appropriate accessor function (out_be32 or such).


> +
> +static int
> +ibm_gpio_open(struct inode *inode, struct file *file)
> +{
> +=A0=A0=A0=A0=A0=A0=A0return 0;
> +}
> +
> +static int
> +ibm_gpio_release(struct inode *inode, struct file *file)
> +{
> +=A0=A0=A0=A0=A0=A0=A0return 0;
> +}

You don't need these.


> +static int
> +ibm_gpio_ioctl(struct inode *inode, struct file *file,
> +=A0=A0=A0=A0=A0=A0=A0 =A0 =A0 =A0 unsigned int cmd, unsigned long arg)
> +{
> +=A0=A0=A0=A0=A0=A0=A0static struct ibm_gpio_ioctl_data ioctl_data;
> +=A0=A0=A0=A0=A0=A0=A0int status;
> +
> +=A0=A0=A0=A0=A0=A0=A0switch (cmd) {
> +=A0=A0=A0=A0=A0=A0=A0case IBMGPIO_IN:
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0if (copy_from_user(&ioctl_d=
ata,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0 =A0 (struct ibm_gpio_ioctl_data *) arg,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0 =A0 sizeof (ioctl_data))) {
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0ret=
urn -EFAULT;
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0}

Just do the copy_from_user() once, in the beginning here, instead
of each case.
> +
> +static int __init
> +ibm_gpio_probe(struct ocp_device *ocp)
> +{
> +=A0=A0=A0=A0=A0=A0=A0ibm_gpio_miscdev.minor =3D GPIO_MINOR;
> +=A0=A0=A0=A0=A0=A0=A0ibm_gpio_miscdev.name =3D ocp->name;
> +=A0=A0=A0=A0=A0=A0=A0ibm_gpio_miscdev.fops =3D &ibm_gpio_fops;
> +=A0=A0=A0=A0=A0=A0=A0misc_register(&ibm_gpio_miscdev);
> +
> +=A0=A0=A0=A0=A0=A0=A0if (!request_mem_region(ocp->def->paddr, sizeof(str=
uct gpio_regs), "ibm_gpio"))
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return -EBUSY;
> +=A0=A0=A0=A0=A0=A0=A0
> +=A0=A0=A0=A0=A0=A0=A0gpiop =3D (struct gpio_regs *) ioremap(ocp->def->pa=
ddr,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0siz=
eof(struct gpio_regs));
> +=A0=A0=A0=A0=A0=A0=A0if (!gpiop) {
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0release_mem_region(ocp->def=
=2D>paddr, sizeof(struct gpio_regs));
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return -ENOMEM;
> +=A0=A0=A0=A0=A0=A0=A0}
> +=A0=A0=A0=A0=A0=A0=A0
> +=A0=A0=A0=A0=A0=A0=A0printk("GPIO #%d at 0x%lx\n", ocp->def->index,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0(un=
signed long) gpiop);
> +
> +=A0=A0=A0=A0=A0=A0=A0return 0;
> +}
> +
> +static void __exit
> +ibm_gpio_remove(struct ocp_device *ocp)
> +{
> +=A0=A0=A0=A0=A0=A0=A0misc_deregister(&ibm_gpio_miscdev);
> +
> +=A0=A0=A0=A0=A0=A0=A0iounmap(gpiop);
> +=A0=A0=A0=A0=A0=A0=A0gpiop =3D NULL;
> +=A0=A0=A0=A0=A0=A0=A0
> +=A0=A0=A0=A0=A0=A0=A0release_mem_region(ocp->def->paddr, sizeof(struct g=
pio_regs));
> +}
> +
> +static struct ocp_device_id ibm_gpio_ids[] __devinitdata =3D
> +{
> +=A0=A0=A0=A0=A0=A0=A0{ .vendor =3D OCP_VENDOR_IBM, .function =3D OCP_FUN=
C_GPIO },
> +=A0=A0=A0=A0=A0=A0=A0{ .vendor =3D OCP_VENDOR_INVALID }
> +};
> +
> +MODULE_DEVICE_TABLE(ocp, ibm_gpio_ids);
> +
> +static struct ocp_driver ibm_gpio_driver =3D
> +{
> +=A0=A0=A0=A0=A0=A0=A0.name =A0 =A0 =A0 =A0 =A0 =3D "ibm_gpio",
> +=A0=A0=A0=A0=A0=A0=A0.id_table =A0 =A0 =A0 =3D ibm_gpio_ids,
> +=A0=A0=A0=A0=A0=A0=A0.probe =A0 =A0 =A0 =A0 =A0=3D ibm_gpio_probe,
> +=A0=A0=A0=A0=A0=A0=A0.remove =A0 =A0 =A0 =A0 =3D __devexit_p(ibm_gpio_re=
move),
> +#if defined(CONFIG_PM)
> +=A0=A0=A0=A0=A0=A0=A0.suspend =A0 =A0 =A0 =A0=3D NULL,
> +=A0=A0=A0=A0=A0=A0=A0.resume =A0 =A0 =A0 =A0 =3D NULL,
> +#endif
> +};
> +
> +static int __init
> +ibm_gpio_init(void)
> +{
> +=A0=A0=A0=A0=A0=A0=A0printk("IBM GPIO driver version %s\n", VUFX);
> +=A0=A0=A0=A0=A0=A0=A0return ocp_register_driver(&ibm_gpio_driver);
> +}
> +
> +static void __exit
> +ibm_gpio_exit(void)
> +{
> +=A0=A0=A0=A0=A0=A0=A0ocp_unregister_driver(&ibm_gpio_driver);
> +}

ocp will die a painful death soon, when 440 has been converted over
to use the device tree and of_device.

> +EXPORT_SYMBOL(ibm_gpio_tristate);
> +EXPORT_SYMBOL(ibm_gpio_open_drain);
> +EXPORT_SYMBOL(ibm_gpio_in);
> +EXPORT_SYMBOL(ibm_gpio_out);

Why export these at all? They don't seem to be used elsewhere?

If you need to export them, make it EXPORT_SYMBOL_GPL and put that
line directly under the functions.

> +
> +struct ibm_gpio_ioctl_data {
> + =A0 =A0 =A0 =A0__u32 device;
> + =A0 =A0 =A0 =A0__u32 mask;
> + =A0 =A0 =A0 =A0__u32 data;
> +};
> +
> +#define IBMGPIO_IOCTL_BASE=A0=A0=A0=A0=A0'Z'
> +
> +#define IBMGPIO_IN=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0_IOWR(IBMGPIO_I=
OCTL_BASE, 0, struct ibm_gpio_ioctl_data)
> +#define IBMGPIO_OUT=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0_IOW (IBMGPIO_IOC=
TL_BASE, 1, struct ibm_gpio_ioctl_data)
> +#define IBMGPIO_OPEN_DRAIN=A0=A0=A0=A0=A0_IOW (IBMGPIO_IOCTL_BASE, 2, st=
ruct ibm_gpio_ioctl_data)
> +#define IBMGPIO_TRISTATE=A0=A0=A0=A0=A0=A0=A0_IOW (IBMGPIO_IOCTL_BASE, 3=
, struct ibm_gpio_ioctl_data)
> +#define IBMGPIO_CFG=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0_IOW (IBMGPIO_IOC=
TL_BASE, 4, struct ibm_gpio_ioctl_data)

Is that the same ioctl interface as for the other gpio drivers?

> +#endif

^ permalink raw reply

* [PATCH] Fix rheap alignment problem
From: Li Yang @ 2006-09-29 10:15 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

Honor alignment parameter in the rheap allocator.  This is
needed by qe_lib.
Remove compile warning.

Signed-off-by: Pantelis Antoniou <pantelis@embeddedalley.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Acked-by: Kumar Galak <galak@kernel.crashing.org>

---
 arch/powerpc/lib/Makefile |    1 +
 arch/powerpc/lib/rheap.c  |   24 ++++++++++++++++++++----
 include/asm-ppc/rheap.h   |    4 ++++
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index ff70964..fe61c92 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -14,6 +14,7 @@ endif
 obj-$(CONFIG_PPC64)	+= checksum_64.o copypage_64.o copyuser_64.o \
 			   memcpy_64.o usercopy_64.o mem_64.o string.o \
 			   strcase.o
+obj-$(CONFIG_QUICC_ENGINE) += rheap.o
 obj-$(CONFIG_PPC_ISERIES) += e2a.o
 obj-$(CONFIG_XMON)	+= sstep.o
 
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
index 31e5118..57bf991 100644
--- a/arch/powerpc/lib/rheap.c
+++ b/arch/powerpc/lib/rheap.c
@@ -423,17 +423,21 @@ void *rh_detach_region(rh_info_t * info,
 	return (void *)s;
 }
 
-void *rh_alloc(rh_info_t * info, int size, const char *owner)
+void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner)
 {
 	struct list_head *l;
 	rh_block_t *blk;
 	rh_block_t *newblk;
 	void *start;
 
-	/* Validate size */
-	if (size <= 0)
+	/* Validate size, (must be power of two) */
+	if (size <= 0 || (alignment & (alignment - 1)) != 0)
 		return ERR_PTR(-EINVAL);
 
+	/* given alignment larger that default rheap alignment */
+	if (alignment > info->alignment)
+		size += alignment - 1;
+
 	/* Align to configured alignment */
 	size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
 
@@ -476,15 +480,27 @@ void *rh_alloc(rh_info_t * info, int siz
 
 	attach_taken_block(info, newblk);
 
+	/* for larger alignment return fixed up pointer  */
+	/* this is no problem with the deallocator since */
+	/* we scan for pointers that lie in the blocks   */
+	if (alignment > info->alignment)
+		start = (void *)(((unsigned long)start + alignment - 1) &
+				~(alignment - 1));
+
 	return start;
 }
 
+void *rh_alloc(rh_info_t * info, int size, const char *owner)
+{
+	return rh_alloc_align(info, size, info->alignment, owner);
+}
+
 /* allocate at precisely the given address */
 void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
 {
 	struct list_head *l;
 	rh_block_t *blk, *newblk1, *newblk2;
-	unsigned long s, e, m, bs, be;
+	unsigned long s, e, m, bs = 0, be = 0;
 
 	/* Validate size */
 	if (size <= 0)
diff --git a/include/asm-ppc/rheap.h b/include/asm-ppc/rheap.h
index e6ca1f6..65b9322 100644
--- a/include/asm-ppc/rheap.h
+++ b/include/asm-ppc/rheap.h
@@ -62,6 +62,10 @@ extern int rh_attach_region(rh_info_t * 
 /* Detach a free region */
 extern void *rh_detach_region(rh_info_t * info, void *start, int size);
 
+/* Allocate the given size from the remote heap (with alignment) */
+extern void *rh_alloc_align(rh_info_t * info, int size, int alignment,
+		const char *owner);
+
 /* Allocate the given size from the remote heap */
 extern void *rh_alloc(rh_info_t * info, int size, const char *owner);

^ permalink raw reply related

* [PATCH 0/9] Add support for QE and 8360EMDS board -v3
From: Li Yang @ 2006-09-29 10:34 UTC (permalink / raw)
  To: paulus, Kumar; +Cc: linuxppc-dev

Paul,

The series of patches add generic QE infrastructure called
qe_lib, and MPC8360EMDS board support.  Qe_lib is used by
QE device drivers such as ucc_geth driver.

This version updates QE interrupt controller to use new irq
mapping mechanism, addresses all the comments received with
last submission and includes some style fixes.

v2: Change to use device tree for BCSR and MURAM;
Remove I/O port interrupt handling code as it is not generic
enough.

v3: Address comments from Kumar;  Update definition of several
device tree nodes;  Copyright style change.

- Leo

^ permalink raw reply

* [PATCH 1/9] qe_lib: Add common files
From: Li Yang @ 2006-09-29 10:35 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

Signed-off-by: Shlomi Gridish <gridish@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Kim Phillips <kim.phillips@freescale.com> 

---
 arch/powerpc/Kconfig                   |   12 +
 arch/powerpc/sysdev/Makefile           |    1 
 arch/powerpc/sysdev/qe_lib/Kconfig     |   29 ++
 arch/powerpc/sysdev/qe_lib/Makefile    |    8 +
 arch/powerpc/sysdev/qe_lib/qe_common.c |  362 ++++++++++++++++++++++++
 include/asm-powerpc/qe.h               |  492 ++++++++++++++++++++++++++++++++
 6 files changed, 904 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 694b0c6..16bc605 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -355,6 +355,16 @@ config APUS
 	  <http://linux-apus.sourceforge.net/>.
 endchoice
 
+config QUICC_ENGINE
+	bool
+	depends on PPC_MPC836x
+	default y
+	help
+	  The QE(QUICC Engine) is a new generation of coprocessor on 
+	  Freescale embedded CPUs(like CPM  in older chips).  Selecting
+	  this option means that you wish to build a kernel for a machine
+	  with QE coprocessor on it.
+
 config PPC_PSERIES
 	depends on PPC_MULTIPLATFORM && PPC64
 	bool "IBM pSeries & new (POWER5-based) iSeries"
@@ -1047,6 +1057,8 @@ # XXX source "arch/ppc/8xx_io/Kconfig"
 
 # XXX source "arch/ppc/8260_io/Kconfig"
 
+source "arch/powerpc/sysdev/qe_lib/Kconfig"
+
 source "arch/powerpc/platforms/iseries/Kconfig"
 
 source "lib/Kconfig"
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index e5e999e..c6e5b31 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_PPC_TODC)		+= todc.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
+obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
new file mode 100644
index 0000000..28487e4
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -0,0 +1,29 @@
+#
+# QE Communication options
+#
+
+menu "QE Options"
+	depends on QUICC_ENGINE
+
+config UCC_SLOW
+	bool "UCC Slow Protocols Support"
+	default n
+	select UCC
+	help
+	  This option provides qe_lib support to UCC slow
+	  protocols: UART, BISYNC, QMC
+
+config UCC_FAST
+	bool "UCC Fast Protocols Support"
+	default n
+	select UCC
+	help
+	  This option provides qe_lib support to UCC fast
+	  protocols: HDLC, Ethernet, ATM, transparent
+
+config UCC
+	bool
+	default y if UCC_FAST || UCC_SLOW
+
+endmenu
+
diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/sysdev/qe_lib/Makefile
new file mode 100644
index 0000000..9a54a81
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the linux ppc-specific parts of QE
+#
+obj-$(CONFIG_QUICC_ENGINE)+= qe_common.o qe.o qe_ic.o qe_io.o
+
+obj-$(CONFIG_UCC)	+= ucc.o
+obj-$(CONFIG_UCC_SLOW)	+= ucc_slow.o
+obj-$(CONFIG_UCC_FAST)	+= ucc_fast.o ucc_slow.o
diff --git a/arch/powerpc/sysdev/qe_lib/qe_common.c b/arch/powerpc/sysdev/qe_lib/qe_common.c
new file mode 100644
index 0000000..516c186
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/qe_common.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ *
+ * Authors: 	Shlomi Gridish <gridish@freescale.com>
+ * 		Li Yang <leoli@freescale.com>
+ * Based on cpm2_common.c from Dan Malek (dmalek@jlc.net)
+ *
+ * Description:
+ * General Purpose functions for the global management of the
+ * QUICC Engine (QE).
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+#include <asm/prom.h>
+#include <asm/rheap.h>
+
+/* QE snum state
+*/
+typedef enum qe_snum_state {
+	QE_SNUM_STATE_USED,	/* used */
+	QE_SNUM_STATE_FREE	/* free */
+} qe_snum_state_e;
+
+/* QE snum
+*/
+typedef struct qe_snum {
+	u8 num;			/* snum  */
+	qe_snum_state_e state;	/* state */
+} qe_snum_t;
+
+/* We allocate this here because it is used almost exclusively for
+ * the communication processor devices.
+ */
+EXPORT_SYMBOL(qe_immr);
+qe_map_t *qe_immr = NULL;
+static qe_snum_t snums[QE_NUM_OF_SNUM];	/* Dynamically allocated SNUMs  */
+
+static void qe_snums_init(void);
+static void qe_muram_init(void);
+static int qe_sdma_init(void);
+
+static DEFINE_SPINLOCK(qe_lock);
+
+void qe_reset(void)
+{
+	if (qe_immr == NULL)
+		qe_immr = (qe_map_t *) ioremap(get_qe_base(), QE_IMMAP_SIZE);
+
+	qe_snums_init();
+
+	qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
+		     (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+	/* Reclaim the MURAM memory for our use. */
+	qe_muram_init();
+
+	if (qe_sdma_init())
+		panic("sdma init failed!");
+}
+
+EXPORT_SYMBOL(qe_issue_cmd);
+int qe_issue_cmd(uint cmd, uint device, u8 mcn_protocol, u32 cmd_input)
+{
+	unsigned long flags;
+	u32 cecr;
+	u8 mcn_shift = 0, dev_shift = 0;
+
+	spin_lock_irqsave(&qe_lock, flags);
+	if (cmd == QE_RESET) {
+		out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
+	} else {
+		if (cmd == QE_ASSIGN_PAGE) {
+			/* Here device is the SNUM, not sub-block */
+			dev_shift = QE_CR_SNUM_SHIFT;
+		} else if (cmd == QE_ASSIGN_RISC) {
+			/* Here device is the SNUM, and mcnProtocol is
+			 * e_QeCmdRiscAssignment value */
+			dev_shift = QE_CR_SNUM_SHIFT;
+			mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT;
+		} else {
+			if (device == QE_CR_SUBBLOCK_USB)
+				mcn_shift = QE_CR_MCN_USB_SHIFT;
+			else
+				mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
+		}
+
+		out_be32(&qe_immr->cp.cecdr,
+			 immrbar_virt_to_phys((void *)cmd_input));
+		out_be32(&qe_immr->cp.cecr,
+			 (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
+			  mcn_protocol << mcn_shift));
+	}
+
+	/* wait for the QE_CR_FLG to clear */
+	do {
+		cecr = in_be32(&qe_immr->cp.cecr);
+	} while (cecr & QE_CR_FLG);
+	spin_unlock_irqrestore(&qe_lock, flags);
+
+	return 0;
+}
+
+/* Set a baud rate generator. This needs lots of work. There are
+ * 16 BRGs, which can be connected to the QE channels or output
+ * as clocks. The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers). Documentation uses 1-based numbering.
+ */
+static unsigned int brg_clk = 0;
+
+unsigned int get_brg_clk(void)
+{
+	struct device_node *qe;
+	if (brg_clk)
+		return brg_clk;
+
+	qe = of_find_node_by_type(NULL, "qe");
+	if (qe) {
+		unsigned int size;
+		u32 *prop = (u32 *) get_property(qe, "brg-frequency", &size);
+		brg_clk = *prop;
+		of_node_put(qe);
+	};
+	return brg_clk;
+}
+
+/* This function is used by UARTS, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void qe_setbrg(uint brg, uint rate)
+{
+	volatile uint *bp;
+	u32 divisor;
+	int div16 = 0;
+
+	bp = (uint *) & qe_immr->brg.brgc1;
+	bp += brg;
+
+	divisor = (get_brg_clk() / rate);
+	if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
+		div16 = 1;
+		divisor /= 16;
+	}
+
+	*bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
+	if (div16)
+		*bp |= QE_BRGC_DIV16;
+}
+
+static void qe_snums_init(void)
+{
+	int i;
+
+	/* Initialize the SNUMs array. */
+	for (i = 0; i < QE_NUM_OF_SNUM; i++)
+		snums[i].state = QE_SNUM_STATE_FREE;
+
+	/* Initialize SNUMs (thread serial numbers) according to QE
+	 * spec chapter 4, SNUM table */
+	i = 0;
+	snums[i++].num = 0x04;
+	snums[i++].num = 0x05;
+	snums[i++].num = 0x0C;
+	snums[i++].num = 0x0D;
+	snums[i++].num = 0x14;
+	snums[i++].num = 0x15;
+	snums[i++].num = 0x1C;
+	snums[i++].num = 0x1D;
+	snums[i++].num = 0x24;
+	snums[i++].num = 0x25;
+	snums[i++].num = 0x2C;
+	snums[i++].num = 0x2D;
+	snums[i++].num = 0x34;
+	snums[i++].num = 0x35;
+	snums[i++].num = 0x88;
+	snums[i++].num = 0x89;
+	snums[i++].num = 0x98;
+	snums[i++].num = 0x99;
+	snums[i++].num = 0xA8;
+	snums[i++].num = 0xA9;
+	snums[i++].num = 0xB8;
+	snums[i++].num = 0xB9;
+	snums[i++].num = 0xC8;
+	snums[i++].num = 0xC9;
+	snums[i++].num = 0xD8;
+	snums[i++].num = 0xD9;
+	snums[i++].num = 0xE8;
+	snums[i++].num = 0xE9;
+}
+
+int qe_get_snum(void)
+{
+	unsigned long flags;
+	int snum = -EBUSY;
+	int i;
+
+	spin_lock_irqsave(&qe_lock, flags);
+	for (i = 0; i < QE_NUM_OF_SNUM; i++) {
+		if (snums[i].state == QE_SNUM_STATE_FREE) {
+			snums[i].state = QE_SNUM_STATE_USED;
+			snum = snums[i].num;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&qe_lock, flags);
+
+	return snum;
+}
+
+EXPORT_SYMBOL(qe_get_snum);
+
+void qe_put_snum(u8 snum)
+{
+	int i;
+
+	for (i = 0; i < QE_NUM_OF_SNUM; i++) {
+		if (snums[i].num == snum) {
+			snums[i].state = QE_SNUM_STATE_FREE;
+			break;
+		}
+	}
+}
+
+EXPORT_SYMBOL(qe_put_snum);
+
+static int qe_sdma_init(void)
+{
+	sdma_t *sdma = &qe_immr->sdma;
+	uint sdma_buf_offset;
+
+	if (!sdma)
+		return -ENODEV;
+
+	/* allocate 2 internal temporary buffers (512 bytes size each) for
+	 * the SDMA */
+	sdma_buf_offset = qe_muram_alloc(512 * 2, 64);
+	if (IS_MURAM_ERR(sdma_buf_offset))
+		return -ENOMEM;
+
+	out_be32(&sdma->sdebcr, sdma_buf_offset & QE_SDEBCR_BA_MASK);
+	out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK | (0x1 >>
+					QE_SDMR_CEN_SHIFT)));
+
+	return 0;
+}
+
+/*
+ * muram_alloc / muram_free bits.
+ */
+static DEFINE_SPINLOCK(qe_muram_lock);
+
+/* 16 blocks should be enough to satisfy all requests
+ * until the memory subsystem goes up... */
+static rh_block_t qe_boot_muram_rh_block[16];
+static rh_info_t qe_muram_info;
+
+static void qe_muram_init(void)
+{
+	struct device_node *np;
+	u32 address;
+	u64 size;
+	unsigned int flags;
+
+	/* initialize the info header */
+	rh_init(&qe_muram_info, 1,
+		sizeof(qe_boot_muram_rh_block) /
+		sizeof(qe_boot_muram_rh_block[0]), qe_boot_muram_rh_block);
+	
+	/* Attach the usable muram area */
+	/* XXX: This is a subset of the available muram. It
+	 * varies with the processor and the microcode patches activated.
+	 */
+	if ((np = of_find_node_by_name(NULL, "data-only")) != NULL) {
+		address = *of_get_address(np, 0, &size, &flags);
+		of_node_put(np);
+		rh_attach_region(&qe_muram_info,
+			(void *)address, (int)size);
+	}
+}
+
+/* This function returns an index into the MURAM area.
+ */
+uint qe_muram_alloc(uint size, uint align)
+{
+	void *start;
+	unsigned long flags;
+
+	spin_lock_irqsave(&qe_muram_lock, flags);
+	start = rh_alloc_align(&qe_muram_info, size, align, "QE");
+	spin_unlock_irqrestore(&qe_muram_lock, flags);
+
+	return (uint) start;
+}
+
+EXPORT_SYMBOL(qe_muram_alloc);
+
+int qe_muram_free(uint offset)
+{
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&qe_muram_lock, flags);
+	ret = rh_free(&qe_muram_info, (void *)offset);
+	spin_unlock_irqrestore(&qe_muram_lock, flags);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(qe_muram_free);
+
+/* not sure if this is ever needed */
+uint qe_muram_alloc_fixed(uint offset, uint size)
+{
+	void *start;
+	unsigned long flags;
+
+	spin_lock_irqsave(&qe_muram_lock, flags);
+	start =
+	    rh_alloc_fixed(&qe_muram_info, (void *)offset, size, "commproc");
+	spin_unlock_irqrestore(&qe_muram_lock, flags);
+
+	return (uint) start;
+}
+
+EXPORT_SYMBOL(qe_muram_alloc_fixed);
+
+void qe_muram_dump(void)
+{
+	rh_dump(&qe_muram_info);
+}
+
+EXPORT_SYMBOL(qe_muram_dump);
+
+void *qe_muram_addr(uint offset)
+{
+	return (void *)&qe_immr->muram[offset];
+}
+
+EXPORT_SYMBOL(qe_muram_addr);
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
new file mode 100644
index 0000000..8578a9b
--- /dev/null
+++ b/include/asm-powerpc/qe.h
@@ -0,0 +1,492 @@
+/*
+ * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ *
+ * Authors: 	Shlomi Gridish <gridish@freescale.com>
+ * 		Li Yang <leoli@freescale.com>
+ *
+ * Description:
+ * QUICC Engine (QE) external definitions and structure.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifdef CONFIG_QUICC_ENGINE
+#ifdef __KERNEL__
+#ifndef __QE_H__
+#define __QE_H__
+
+#include <asm/immap_qe.h>
+
+static inline long IS_MURAM_ERR(const uint offset)
+{
+	return (uint) offset > (uint) - 1000L;
+}
+
+#define QE_NUM_OF_SNUM  28
+#define QE_NUM_OF_BRGS  16
+#define QE_NUM_OF_PORTS 1024
+
+/* Memory partitions
+*/
+#define MEM_PART_SYSTEM     0
+#define MEM_PART_SECONDARY  1
+#define MEM_PART_MURAM      2
+
+/* Export QE common operations */
+extern void qe_reset(void);
+extern int par_io_init(struct device_node *np);
+extern int par_io_of_config(struct device_node *np);
+
+/* QE internal APIs */
+int qe_issue_cmd(uint cmd, uint device, u8 mcn_protocol, u32 cmd_input);
+void qe_setbrg(uint brg, uint rate);
+int qe_get_snum(void);
+void qe_put_snum(u8 snum);
+uint qe_muram_alloc(uint size, uint align);
+int qe_muram_free(uint offset);
+uint qe_muram_alloc_fixed(uint offset, uint size);
+void qe_muram_dump(void);
+void *qe_muram_addr(uint offset);
+/* Buffer descriptors.
+*/
+typedef struct qe_bd {
+	u16 status;
+	u16 length;
+	u32 buf;
+} __attribute__ ((packed)) qe_bd_t;
+
+#define QE_SIZEOF_BD       sizeof(qe_bd_t)
+
+#define BD_STATUS_MASK                      0xffff0000
+#define BD_LENGTH_MASK                      0x0000ffff
+
+#define BD_BUFFER_ARG(bd)                   ((qe_bd_t *)bd)->buf
+#define BD_BUFFER_CLEAR(bd)                 out_be32(&(BD_BUFFER_ARG(bd)), 0);
+#define BD_BUFFER(bd)                       in_be32(&(BD_BUFFER_ARG(bd)))
+#define BD_STATUS_AND_LENGTH_SET(bd, val)   out_be32((u32*)bd, val)
+#define BD_STATUS_AND_LENGTH(bd)            in_be32((u32*)bd)
+#define BD_BUFFER_SET(bd, buffer)           out_be32(&(BD_BUFFER_ARG(bd)), \
+	(u32)(buffer))
+/* Macro for retrieving the following BD.
+   example:
+   next = BD_GET_NEXT( currBd, bdStatus, bdBase, SIZEOF_MY_BD, T_W ) */
+#define BD_GET_NEXT( curr_bd, bd_status, bd_base, bd_len, last_bd ) \
+        ( (!((bd_status) & (last_bd))) ? ((curr_bd)+(bd_len)) : (bd_base) )
+
+/* Alignments
+*/
+#define QE_INTR_TABLE_ALIGN                16	/* ??? */
+#define QE_ALIGNMENT_OF_BD                 8
+#define QE_ALIGNMENT_OF_PRAM               64
+
+/* RISC allocation
+*/
+typedef enum qe_risc_allocation {
+	QE_RISC_ALLOCATION_RISC1 = 1,	/* RISC 1 */
+	QE_RISC_ALLOCATION_RISC2 = 2,	/* RISC 2 */
+	QE_RISC_ALLOCATION_RISC1_AND_RISC2 = 3	/* Dynamically choose RISC 1 or
+						   RISC 2 */
+} qe_risc_allocation_e;
+
+/* QE extended filtering Table Lookup Key Size
+*/
+typedef enum qe_fltr_tbl_lookup_key_size {
+	QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES
+		= 0x3f,		/* LookupKey parsed by the Generate LookupKey 
+				   CMD is truncated to 8  bytes */
+	QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES
+		= 0x5f,		/* LookupKey parsed by the Generate LookupKey 
+				   CMD is truncated to 16 bytes */
+} qe_fltr_tbl_lookup_key_size_e;
+
+/* QE FLTR extended filtering Largest External Table Lookup Key Size
+*/
+typedef enum qe_fltr_largest_external_tbl_lookup_key_size_ {
+	QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE
+		= 0x0,/* not used */
+	QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES
+		= QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES,	/* 8  bytes */
+	QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES
+		= QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES	/* 16 bytes */
+} qe_fltr_largest_external_tbl_lookup_key_size_e;
+
+/* structure representing QE parameter RAM
+*/
+typedef struct qe_timer_tables {
+	u16 tm_base;		/* QE timer table base adr */
+	u16 tm_ptr;		/* QE timer table pointer  */
+	u16 r_tmr;		/* QE timer mode register  */
+	u16 r_tmv;		/* QE timer valid register */
+	u32 tm_cmd;		/* QE timer cmd register   */
+	u32 tm_cnt;		/* QE timer internal cnt   */
+} __attribute__ ((packed)) qe_timer_tables_t;
+
+#define QE_FLTR_TAD_SIZE                8
+
+/* QE extended filtering Termination Action Descriptor (TAD)
+*/
+typedef struct qe_fltr_tad {
+	u8 serialized[QE_FLTR_TAD_SIZE];
+} __attribute__ ((packed)) qe_fltr_tad_t;
+
+/* Communication Direction.
+*/
+typedef enum comm_dir {
+	COMM_DIR_NONE = 0,
+	COMM_DIR_RX = 1,
+	COMM_DIR_TX = 2,
+	COMM_DIR_RX_AND_TX = 3
+} comm_dir_e;
+
+/* Clocks and GRG's
+*/
+typedef enum qe_clock {
+	QE_CLK_NONE = 0
+	    , QE_BRG1		/* Baud Rate Generator  1 */
+	    , QE_BRG2		/* Baud Rate Generator  2 */
+	    , QE_BRG3		/* Baud Rate Generator  3 */
+	    , QE_BRG4		/* Baud Rate Generator  4 */
+	    , QE_BRG5		/* Baud Rate Generator  5 */
+	    , QE_BRG6		/* Baud Rate Generator  6 */
+	    , QE_BRG7		/* Baud Rate Generator  7 */
+	    , QE_BRG8		/* Baud Rate Generator  8 */
+	    , QE_BRG9		/* Baud Rate Generator  9 */
+	    , QE_BRG10		/* Baud Rate Generator 10 */
+	    , QE_BRG11		/* Baud Rate Generator 11 */
+	    , QE_BRG12		/* Baud Rate Generator 12 */
+	    , QE_BRG13		/* Baud Rate Generator 13 */
+	    , QE_BRG14		/* Baud Rate Generator 14 */
+	    , QE_BRG15		/* Baud Rate Generator 15 */
+	    , QE_BRG16		/* Baud Rate Generator 16 */
+	    , QE_CLK1		/* Clock  1               */
+	    , QE_CLK2		/* Clock  2               */
+	    , QE_CLK3		/* Clock  3               */
+	    , QE_CLK4		/* Clock  4               */
+	    , QE_CLK5		/* Clock  5               */
+	    , QE_CLK6		/* Clock  6               */
+	    , QE_CLK7		/* Clock  7               */
+	    , QE_CLK8		/* Clock  8               */
+	    , QE_CLK9		/* Clock  9               */
+	    , QE_CLK10		/* Clock 10               */
+	    , QE_CLK11		/* Clock 11               */
+	    , QE_CLK12		/* Clock 12               */
+	    , QE_CLK13		/* Clock 13               */
+	    , QE_CLK14		/* Clock 14               */
+	    , QE_CLK15		/* Clock 15               */
+	    , QE_CLK16		/* Clock 16               */
+	    , QE_CLK17		/* Clock 17               */
+	    , QE_CLK18		/* Clock 18               */
+	    , QE_CLK19		/* Clock 19               */
+	    , QE_CLK20		/* Clock 20               */
+	    , QE_CLK21		/* Clock 21               */
+	    , QE_CLK22		/* Clock 22               */
+	    , QE_CLK23		/* Clock 23               */
+	    , QE_CLK24		/* Clock 24               */
+	    , QE_CLK_DUMMY
+} qe_clock_e;
+
+/* QE CMXUCR Registers.
+ * There are two UCCs represented in each of the four CMXUCR registers.
+ * These values are for the UCC in the LSBs
+ */
+#define QE_CMXUCR_MII_ENET_MNG              0x00007000
+#define QE_CMXUCR_MII_ENET_MNG_SHIFT        12
+#define QE_CMXUCR_GRANT                     0x00008000
+#define QE_CMXUCR_TSA                       0x00004000
+#define QE_CMXUCR_BKPT                      0x00000100
+#define QE_CMXUCR_TX_CLK_SRC_MASK           0x0000000F
+
+/* QE CMXGCR Registers.
+*/
+#define QE_CMXGCR_MII_ENET_MNG              0x00007000
+#define QE_CMXGCR_MII_ENET_MNG_SHIFT        12
+#define QE_CMXGCR_USBCS                     0x0000000f
+
+/* QE CECR Commands.
+*/
+#define QE_CR_FLG                   0x00010000
+#define QE_RESET                    0x80000000
+#define QE_INIT_TX_RX               0x00000000
+#define QE_INIT_RX                  0x00000001
+#define QE_INIT_TX                  0x00000002
+#define QE_ENTER_HUNT_MODE          0x00000003
+#define QE_STOP_TX                  0x00000004
+#define QE_GRACEFUL_STOP_TX         0x00000005
+#define QE_RESTART_TX               0x00000006
+#define QE_CLOSE_RX_BD              0x00000007
+#define QE_SWITCH_COMMAND           0x00000007
+#define QE_SET_GROUP_ADDRESS        0x00000008
+#define QE_START_IDMA               0x00000009
+#define QE_MCC_STOP_RX              0x00000009
+#define QE_ATM_TRANSMIT             0x0000000a
+#define QE_HPAC_CLEAR_ALL           0x0000000b
+#define QE_GRACEFUL_STOP_RX         0x0000001a
+#define QE_RESTART_RX               0x0000001b
+#define QE_HPAC_SET_PRIORITY        0x0000010b
+#define QE_HPAC_STOP_TX             0x0000020b
+#define QE_HPAC_STOP_RX             0x0000030b
+#define QE_HPAC_GRACEFUL_STOP_TX    0x0000040b
+#define QE_HPAC_GRACEFUL_STOP_RX    0x0000050b
+#define QE_HPAC_START_TX            0x0000060b
+#define QE_HPAC_START_RX            0x0000070b
+#define QE_USB_STOP_TX              0x0000000a
+#define QE_USB_RESTART_TX           0x0000000b
+#define QE_QMC_STOP_TX              0x0000000c
+#define QE_QMC_STOP_RX              0x0000000d
+#define QE_SS7_SU_FIL_RESET         0x0000000e
+/* jonathbr added from here down for 83xx */
+#define QE_RESET_BCS                0x0000000a
+#define QE_MCC_INIT_TX_RX_16        0x00000003
+#define QE_MCC_STOP_TX              0x00000004
+#define QE_MCC_INIT_TX_1            0x00000005
+#define QE_MCC_INIT_RX_1            0x00000006
+#define QE_MCC_RESET                0x00000007
+#define QE_SET_TIMER                0x00000008
+#define QE_RANDOM_NUMBER            0x0000000c
+#define QE_ATM_MULTI_THREAD_INIT    0x00000011
+#define QE_ASSIGN_PAGE              0x00000012
+#define QE_ADD_REMOVE_HASH_ENTRY    0x00000013
+#define QE_START_FLOW_CONTROL       0x00000014
+#define QE_STOP_FLOW_CONTROL        0x00000015
+#define QE_ASSIGN_PAGE_TO_DEVICE    0x00000016
+
+#define QE_ASSIGN_RISC		    0x00000010
+#define QE_CR_MCN_NORMAL_SHIFT      6
+#define QE_CR_MCN_USB_SHIFT         4
+#define QE_CR_MCN_RISC_ASSIGN_SHIFT 8
+#define QE_CR_SNUM_SHIFT            17
+
+/* QE CECR Sub Block - sub block of QE command.
+*/
+#define QE_CR_SUBBLOCK_INVALID      0x00000000
+#define QE_CR_SUBBLOCK_USB          0x03200000
+#define QE_CR_SUBBLOCK_UCCFAST1     0x02000000
+#define QE_CR_SUBBLOCK_UCCFAST2     0x02200000
+#define QE_CR_SUBBLOCK_UCCFAST3     0x02400000
+#define QE_CR_SUBBLOCK_UCCFAST4     0x02600000
+#define QE_CR_SUBBLOCK_UCCFAST5     0x02800000
+#define QE_CR_SUBBLOCK_UCCFAST6     0x02a00000
+#define QE_CR_SUBBLOCK_UCCFAST7     0x02c00000
+#define QE_CR_SUBBLOCK_UCCFAST8     0x02e00000
+#define QE_CR_SUBBLOCK_UCCSLOW1     0x00000000
+#define QE_CR_SUBBLOCK_UCCSLOW2     0x00200000
+#define QE_CR_SUBBLOCK_UCCSLOW3     0x00400000
+#define QE_CR_SUBBLOCK_UCCSLOW4     0x00600000
+#define QE_CR_SUBBLOCK_UCCSLOW5     0x00800000
+#define QE_CR_SUBBLOCK_UCCSLOW6     0x00a00000
+#define QE_CR_SUBBLOCK_UCCSLOW7     0x00c00000
+#define QE_CR_SUBBLOCK_UCCSLOW8     0x00e00000
+#define QE_CR_SUBBLOCK_MCC1         0x03800000
+#define QE_CR_SUBBLOCK_MCC2         0x03a00000
+#define QE_CR_SUBBLOCK_MCC3         0x03000000
+#define QE_CR_SUBBLOCK_IDMA1        0x02800000
+#define QE_CR_SUBBLOCK_IDMA2        0x02a00000
+#define QE_CR_SUBBLOCK_IDMA3        0x02c00000
+#define QE_CR_SUBBLOCK_IDMA4        0x02e00000
+#define QE_CR_SUBBLOCK_HPAC         0x01e00000
+#define QE_CR_SUBBLOCK_SPI1         0x01400000
+#define QE_CR_SUBBLOCK_SPI2         0x01600000
+#define QE_CR_SUBBLOCK_RAND         0x01c00000
+#define QE_CR_SUBBLOCK_TIMER        0x01e00000
+#define QE_CR_SUBBLOCK_GENERAL      0x03c00000
+
+/* QE CECR Protocol - For non-MCC, specifies mode for QE CECR command.
+*/
+#define QE_CR_PROTOCOL_UNSPECIFIED       0x00	/* For all other protocols */
+#define QE_CR_PROTOCOL_HDLC_TRANSPARENT  0x00
+#define QE_CR_PROTOCOL_ATM_POS           0x0A
+#define QE_CR_PROTOCOL_ETHERNET          0x0C
+#define QE_CR_PROTOCOL_L2_SWITCH         0x0D
+
+/* BMR byte order
+*/
+#define QE_BMR_BYTE_ORDER_BO_PPC  0x08	/* powerpc little endian */
+#define QE_BMR_BYTE_ORDER_BO_MOT  0x10	/* motorola big endian   */
+#define QE_BMR_BYTE_ORDER_BO_MAX  0x18
+
+/* BRG configuration register
+*/
+#define QE_BRGC_ENABLE          0x00010000
+#define QE_BRGC_DIVISOR_SHIFT   1
+#define QE_BRGC_DIVISOR_MAX     0xFFF
+#define QE_BRGC_DIV16           1
+/* QE Timers registers */
+#define QE_GTCFR1_PCAS      0x80
+#define QE_GTCFR1_STP2      0x20
+#define QE_GTCFR1_RST2      0x10
+#define QE_GTCFR1_GM2       0x08
+#define QE_GTCFR1_GM1       0x04
+#define QE_GTCFR1_STP1      0x02
+#define QE_GTCFR1_RST1      0x01
+
+/* SDMA registers */
+#define QE_SDSR_BER1            0x02000000
+#define QE_SDSR_BER2            0x01000000
+
+#define QE_SDMR_GLB_1_MSK       0x80000000
+#define QE_SDMR_ADR_SEL         0x20000000
+#define QE_SDMR_BER1_MSK        0x02000000
+#define QE_SDMR_BER2_MSK        0x01000000
+#define QE_SDMR_EB1_MSK         0x00800000
+#define QE_SDMR_ER1_MSK         0x00080000
+#define QE_SDMR_ER2_MSK         0x00040000
+#define QE_SDMR_CEN_MASK        0x0000E000
+#define QE_SDMR_SBER_1          0x00000200
+#define QE_SDMR_SBER_2          0x00000200
+#define QE_SDMR_EB1_PR_MASK     0x000000C0
+#define QE_SDMR_ER1_PR          0x00000008
+
+#define QE_SDMR_CEN_SHIFT       13
+#define QE_SDMR_EB1_PR_SHIFT    6
+
+#define QE_SDTM_MSNUM_SHIFT     24
+
+#define QE_SDEBCR_BA_MASK       0x01FFFFFF
+
+/* UPC
+*/
+#define UPGCR_PROTOCOL      0x80000000	/* protocol ul2 or pl2 */
+#define UPGCR_TMS           0x40000000	/* Transmit master/slave mode */
+#define UPGCR_RMS           0x20000000	/* Receive master/slave mode */
+#define UPGCR_ADDR          0x10000000	/* Master MPHY Addr multiplexing */
+#define UPGCR_DIAG          0x01000000	/* Diagnostic mode */
+
+/* UCC
+*/
+#define UCC_GUEMR_MODE_MASK_RX  0x02
+#define UCC_GUEMR_MODE_MASK_TX  0x01
+#define UCC_GUEMR_MODE_FAST_RX  0x02
+#define UCC_GUEMR_MODE_FAST_TX  0x01
+#define UCC_GUEMR_MODE_SLOW_RX  0x00
+#define UCC_GUEMR_MODE_SLOW_TX  0x00
+#define UCC_GUEMR_SET_RESERVED3 0x10	/* Bit 3 in the guemr is reserved but 
+					   must be set 1 */
+
+/* structure representing UCC SLOW parameter RAM
+*/
+typedef struct ucc_slow_pram {
+	u16 rbase;		/* RX BD base address       */
+	u16 tbase;		/* TX BD base address       */
+	u8 rfcr;		/* Rx function code         */
+	u8 tfcr;		/* Tx function code         */
+	u16 mrblr;		/* Rx buffer length         */
+	u32 rstate;		/* Rx internal state        */
+	u32 rptr;		/* Rx internal data pointer */
+	u16 rbptr;		/* rb BD Pointer            */
+	u16 rcount;		/* Rx internal byte count   */
+	u32 rtemp;		/* Rx temp                  */
+	u32 tstate;		/* Tx internal state        */
+	u32 tptr;		/* Tx internal data pointer */
+	u16 tbptr;		/* Tx BD pointer            */
+	u16 tcount;		/* Tx byte count            */
+	u32 ttemp;		/* Tx temp                  */
+	u32 rcrc;		/* temp receive CRC         */
+	u32 tcrc;		/* temp transmit CRC        */
+} __attribute__ ((packed)) ucc_slow_pram_t;
+
+/* General UCC SLOW Mode Register (GUMRH & GUMRL)
+*/
+#define UCC_SLOW_GUMR_H_CRC16         0x00004000
+#define UCC_SLOW_GUMR_H_CRC16CCITT    0x00000000
+#define UCC_SLOW_GUMR_H_CRC32CCITT    0x00008000
+#define UCC_SLOW_GUMR_H_REVD          0x00002000
+#define UCC_SLOW_GUMR_H_TRX           0x00001000
+#define UCC_SLOW_GUMR_H_TTX           0x00000800
+#define UCC_SLOW_GUMR_H_CDP           0x00000400
+#define UCC_SLOW_GUMR_H_CTSP          0x00000200
+#define UCC_SLOW_GUMR_H_CDS           0x00000100
+#define UCC_SLOW_GUMR_H_CTSS          0x00000080
+#define UCC_SLOW_GUMR_H_TFL           0x00000040
+#define UCC_SLOW_GUMR_H_RFW           0x00000020
+#define UCC_SLOW_GUMR_H_TXSY          0x00000010
+#define UCC_SLOW_GUMR_H_4SYNC         0x00000004
+#define UCC_SLOW_GUMR_H_8SYNC         0x00000008
+#define UCC_SLOW_GUMR_H_16SYNC        0x0000000c
+#define UCC_SLOW_GUMR_H_RTSM          0x00000002
+#define UCC_SLOW_GUMR_H_RSYN          0x00000001
+
+#define UCC_SLOW_GUMR_L_TCI           0x10000000
+#define UCC_SLOW_GUMR_L_RINV          0x02000000
+#define UCC_SLOW_GUMR_L_TINV          0x01000000
+#define UCC_SLOW_GUMR_L_TEND          0x00020000
+#define UCC_SLOW_GUMR_L_ENR           0x00000020
+#define UCC_SLOW_GUMR_L_ENT           0x00000010
+
+/* General UCC FAST Mode Register
+*/
+#define UCC_FAST_GUMR_TCI             0x20000000
+#define UCC_FAST_GUMR_TRX             0x10000000
+#define UCC_FAST_GUMR_TTX             0x08000000
+#define UCC_FAST_GUMR_CDP             0x04000000
+#define UCC_FAST_GUMR_CTSP            0x02000000
+#define UCC_FAST_GUMR_CDS             0x01000000
+#define UCC_FAST_GUMR_CTSS            0x00800000
+#define UCC_FAST_GUMR_TXSY            0x00020000
+#define UCC_FAST_GUMR_RSYN            0x00010000
+#define UCC_FAST_GUMR_RTSM            0x00002000
+#define UCC_FAST_GUMR_REVD            0x00000400
+#define UCC_FAST_GUMR_ENR             0x00000020
+#define UCC_FAST_GUMR_ENT             0x00000010
+
+/* Slow UCC Event Register (UCCE)
+*/
+#define UCC_SLOW_UCCE_GLR       0x1000
+#define UCC_SLOW_UCCE_GLT       0x0800
+#define UCC_SLOW_UCCE_DCC       0x0400
+#define UCC_SLOW_UCCE_FLG       0x0200
+#define UCC_SLOW_UCCE_AB        0x0200
+#define UCC_SLOW_UCCE_IDLE      0x0100
+#define UCC_SLOW_UCCE_GRA       0x0080
+#define UCC_SLOW_UCCE_TXE       0x0010
+#define UCC_SLOW_UCCE_RXF       0x0008
+#define UCC_SLOW_UCCE_CCR       0x0008
+#define UCC_SLOW_UCCE_RCH       0x0008
+#define UCC_SLOW_UCCE_BSY       0x0004
+#define UCC_SLOW_UCCE_TXB       0x0002
+#define UCC_SLOW_UCCE_TX        0x0002
+#define UCC_SLOW_UCCE_RX        0x0001
+#define UCC_SLOW_UCCE_GOV       0x0001
+#define UCC_SLOW_UCCE_GUN       0x0002
+#define UCC_SLOW_UCCE_GINT      0x0004
+#define UCC_SLOW_UCCE_IQOV      0x0008
+
+#define UCC_SLOW_UCCE_HDLC_SET  (UCC_SLOW_UCCE_TXE|UCC_SLOW_UCCE_BSY| \
+		UCC_SLOW_UCCE_GRA|UCC_SLOW_UCCE_TXB|UCC_SLOW_UCCE_RXF| \
+		UCC_SLOW_UCCE_DCC|UCC_SLOW_UCCE_GLT|UCC_SLOW_UCCE_GLR)
+#define UCC_SLOW_UCCE_ENET_SET  (UCC_SLOW_UCCE_TXE|UCC_SLOW_UCCE_BSY| \
+		UCC_SLOW_UCCE_GRA|UCC_SLOW_UCCE_TXB|UCC_SLOW_UCCE_RXF)
+#define UCC_SLOW_UCCE_TRANS_SET (UCC_SLOW_UCCE_TXE|UCC_SLOW_UCCE_BSY| \
+		UCC_SLOW_UCCE_GRA|UCC_SLOW_UCCE_TX |UCC_SLOW_UCCE_RX | \
+		UCC_SLOW_UCCE_DCC|UCC_SLOW_UCCE_GLT|UCC_SLOW_UCCE_GLR)
+#define UCC_SLOW_UCCE_UART_SET  (UCC_SLOW_UCCE_BSY|UCC_SLOW_UCCE_GRA| \
+		UCC_SLOW_UCCE_TXB|UCC_SLOW_UCCE_TX |UCC_SLOW_UCCE_RX | \
+		UCC_SLOW_UCCE_GLT|UCC_SLOW_UCCE_GLR)
+#define UCC_SLOW_UCCE_QMC_SET   (UCC_SLOW_UCCE_IQOV|UCC_SLOW_UCCE_GINT| \
+		UCC_SLOW_UCCE_GUN|UCC_SLOW_UCCE_GOV)
+
+#define UCC_SLOW_UCCE_OTHER     (UCC_SLOW_UCCE_TXE|UCC_SLOW_UCCE_BSY| \
+		UCC_SLOW_UCCE_GRA|UCC_SLOW_UCCE_DCC|UCC_SLOW_UCCE_GLT| \
+		UCC_SLOW_UCCE_GLR)
+
+#define UCC_SLOW_INTR_TX        UCC_SLOW_UCCE_TXB
+#define UCC_SLOW_INTR_RX        (UCC_SLOW_UCCE_RXF | UCC_SLOW_UCCE_RX)
+#define UCC_SLOW_INTR           (UCC_SLOW_INTR_TX  | UCC_SLOW_INTR_RX)
+
+/* Transmit On Demand (UTORD)
+*/
+#define UCC_SLOW_TOD            0x8000
+#define UCC_FAST_TOD            0x8000
+
+/* Function code masks.
+*/
+#define FC_GBL                             0x20
+#define FC_DTB_LCL                         0x02
+#define UCC_FAST_FUNCTION_CODE_GBL         0x20
+#define UCC_FAST_FUNCTION_CODE_DTB_LCL     0x02
+#define UCC_FAST_FUNCTION_CODE_BDB_LCL     0x01
+
+#endif				/* __QE_H__ */
+#endif				/* __KERNEL__ */
+#endif				/* CONFIG_QUICC_ENGINE */

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox