LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 2/2] powerpc: Add IPIC MSI support
From: Michael Ellerman @ 2007-12-14  9:40 UTC (permalink / raw)
  To: Kumar Gala
  Cc: Olof Johansson, linuxppc-dev list, Phillips Kim, Jin Zhengxiong,
	Li Tony
In-Reply-To: <90B908AC-E879-4046-AAFC-FE79EB78A932@kernel.crashing.org>

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

On Fri, 2007-12-14 at 02:52 -0600, Kumar Gala wrote:
> On Dec 14, 2007, at 2:47 AM, Li Tony wrote:
> 
> >
> > Hi,
> >
> > I think it is possible to make common code to support both IPIC and  
> > MPIC.
> > Currently, the MPIC has already implemented MSI which is different  
> > from IPIC and embedded into the mpic code body.
> > If want to unifiy MSI code, we need to remove the current MPIC MSI  
> > implementation.
> 
> The MPIC is going to have to support several MSI styles (IBM/U3,  
> PaSemi, and FSL) since we all seem to handle it differently.

I haven't really looked at the similarities or differences, but I think
Kumar is right, MPIC is going to have to (and already does) support
different styles.

If there's some commonality that can be shared I'm all ears, patches
welcome ;)

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: 189 bytes --]

^ permalink raw reply

* Re: any more patches for 2.6.24?
From: Étienne Bersac @ 2007-12-14 11:04 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18274.3076.467791.719752@cargo.ozlabs.ibm.com>

Hi,

I posted a patch adding windfarm-pm121 driver, i wish it were included
in 2.6.24 . Can you review it ?

http://ozlabs.org/pipermail/linuxppc-dev/2007-December/047641.html

Regards,
Étienne.

^ permalink raw reply

* Re: apm_emulation regression
From: Johannes Berg @ 2007-12-14 12:18 UTC (permalink / raw)
  To: benh; +Cc: Rafael J. Wysocki, linuxppc-dev list, linux-pm, ralf
In-Reply-To: <1197590712.15741.197.camel@pasglop>

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


> > It can use the new notifier that happens before freezing yes. Johannes,
> > I think that's pretty much what my old powermac implementation did
> > (using my private notifier scheme I had there), might be worth reviving
> > that bit and sticking it into the generic apm_emu ...
> 
> Note that you may want to improve on it with a timeout in case userspace
> doesn't ack...

Yeah heh. I'll take a look, shouldn't be too hard. Except I'm not
exactly sure how to test it.

johannes

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

^ permalink raw reply

* [PATCH] OProfile: remove dependency on spufs module
From: Arnd Bergmann @ 2007-12-14 14:27 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: David Woodhouse, Paul Mackerras, jk, Bob Nelson
In-Reply-To: <18274.3076.467791.719752@cargo.ozlabs.ibm.com>

From: Bob Nelson <rrnelson@linux.vnet.ibm.com>

This is a patch removes an OProfile dependency on the spufs module.
This was causing a problem for multiplatform systems that are
built with support for Oprofile on Cell but try to load the
oprofile module on another system.

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

---
On Friday 14 December 2007, Paul Mackerras wrote:
> Currently I have just this one bugfix queued up to go to Linus for
> 2.6.24:
> 
> Stephen Rothwell (1):
>       [POWERPC] iSeries: don't printk with HV spinlock held
> 
> Does anyone else have bugfixes that need to go in 2.6.24?

A few  people have asked me for including this one, I'd like
it to get that in still. It was broken ever since you could
enable support for spu oprofile.

Jeremy, please ack the spufs changes if you are ok with the patch.

Sorry for delaying this patch so long on my side everyone.

	Arnd <><

 arch/powerpc/platforms/cell/Kconfig          |    2 +-
 arch/powerpc/platforms/cell/Makefile         |    1 +
 arch/powerpc/platforms/cell/spu_notify.c     |   67 ++++++++++++++++++++++++++
 arch/powerpc/platforms/cell/spu_syscalls.c   |   14 +++++
 arch/powerpc/platforms/cell/spufs/context.c  |   16 ------
 arch/powerpc/platforms/cell/spufs/sched.c    |   29 +++--------
 arch/powerpc/platforms/cell/spufs/syscalls.c |    1 +
 include/asm-powerpc/spu.h                    |    4 ++
 8 files changed, 95 insertions(+), 39 deletions(-)
 create mode 100644 arch/powerpc/platforms/cell/spu_notify.c


Index: linux-2.6-new/arch/powerpc/platforms/cell/Kconfig
===================================================================
--- linux-2.6-new.orig/arch/powerpc/platforms/cell/Kconfig
+++ linux-2.6-new/arch/powerpc/platforms/cell/Kconfig
@@ -88,3 +88,8 @@ config CBE_CPUFREQ_PMI
 	  but also at lower core voltage.
 
 endmenu
+
+config OPROFILE_CELL
+	def_bool y
+	depends on PPC_CELL_NATIVE && (OPROFILE = m || OPROFILE = y)
+
Index: linux-2.6-new/arch/powerpc/platforms/cell/Makefile
===================================================================
--- linux-2.6-new.orig/arch/powerpc/platforms/cell/Makefile
+++ linux-2.6-new/arch/powerpc/platforms/cell/Makefile
@@ -19,6 +19,7 @@ spu-manage-$(CONFIG_PPC_CELLEB)		+= spu_
 spu-manage-$(CONFIG_PPC_CELL_NATIVE)	+= spu_manage.o
 
 obj-$(CONFIG_SPU_BASE)			+= spu_callbacks.o spu_base.o \
+					   spu_notify.o \
 					   spu_syscalls.o \
 					   $(spu-priv1-y) \
 					   $(spu-manage-y) \
Index: linux-2.6-new/arch/powerpc/platforms/cell/spu_notify.c
===================================================================
--- /dev/null
+++ linux-2.6-new/arch/powerpc/platforms/cell/spu_notify.c
@@ -0,0 +1,67 @@
+/*
+ * Move OProfile dependencies from spufs module to the kernel so it
+ * can run on non-cell PPC.
+ *
+ * Copyright (C) IBM 2005
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ */
+
+#undef DEBUG
+
+#include <linux/module.h>
+#include <asm/spu.h>
+#include "spufs/spufs.h"
+
+static BLOCKING_NOTIFIER_HEAD(spu_switch_notifier);
+
+void spu_switch_notify(struct spu *spu, struct spu_context *ctx)
+{
+	blocking_notifier_call_chain(&spu_switch_notifier,
+				     ctx ? ctx->object_id : 0, spu);
+}
+EXPORT_SYMBOL_GPL(spu_switch_notify);
+
+int spu_switch_event_register(struct notifier_block *n)
+{
+	int ret;
+	ret = blocking_notifier_chain_register(&spu_switch_notifier, n);
+	if (!ret)
+		notify_spus_active();
+	return ret;
+}
+EXPORT_SYMBOL_GPL(spu_switch_event_register);
+
+int spu_switch_event_unregister(struct notifier_block *n)
+{
+	return blocking_notifier_chain_unregister(&spu_switch_notifier, n);
+}
+EXPORT_SYMBOL_GPL(spu_switch_event_unregister);
+
+void spu_set_profile_private_kref(struct spu_context *ctx,
+				  struct kref *prof_info_kref,
+				  void (* prof_info_release) (struct kref *kref))
+{
+	ctx->prof_priv_kref = prof_info_kref;
+	ctx->prof_priv_release = prof_info_release;
+}
+EXPORT_SYMBOL_GPL(spu_set_profile_private_kref);
+
+void *spu_get_profile_private_kref(struct spu_context *ctx)
+{
+	return ctx->prof_priv_kref;
+}
+EXPORT_SYMBOL_GPL(spu_get_profile_private_kref);
+
Index: linux-2.6-new/arch/powerpc/platforms/cell/spu_syscalls.c
===================================================================
--- linux-2.6-new.orig/arch/powerpc/platforms/cell/spu_syscalls.c
+++ linux-2.6-new/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -145,6 +145,20 @@ int elf_coredump_extra_notes_write(struc
 	return ret;
 }
 
+void notify_spus_active(void)
+{
+	struct spufs_calls *calls;
+
+	calls = spufs_calls_get();
+	if (!calls)
+		return;
+
+	calls->notify_spus_active();
+	spufs_calls_put(calls);
+
+	return;
+}
+
 int register_spu_syscalls(struct spufs_calls *calls)
 {
 	if (spufs_calls)
Index: linux-2.6-new/arch/powerpc/platforms/cell/spufs/context.c
===================================================================
--- linux-2.6-new.orig/arch/powerpc/platforms/cell/spufs/context.c
+++ linux-2.6-new/arch/powerpc/platforms/cell/spufs/context.c
@@ -190,19 +190,3 @@ void spu_release_saved(struct spu_contex
 	spu_release(ctx);
 }
 
-void spu_set_profile_private_kref(struct spu_context *ctx,
-				  struct kref *prof_info_kref,
-				  void ( * prof_info_release) (struct kref *kref))
-{
-	ctx->prof_priv_kref = prof_info_kref;
-	ctx->prof_priv_release = prof_info_release;
-}
-EXPORT_SYMBOL_GPL(spu_set_profile_private_kref);
-
-void *spu_get_profile_private_kref(struct spu_context *ctx)
-{
-	return ctx->prof_priv_kref;
-}
-EXPORT_SYMBOL_GPL(spu_get_profile_private_kref);
-
-
Index: linux-2.6-new/arch/powerpc/platforms/cell/spufs/sched.c
===================================================================
--- linux-2.6-new.orig/arch/powerpc/platforms/cell/spufs/sched.c
+++ linux-2.6-new/arch/powerpc/platforms/cell/spufs/sched.c
@@ -166,15 +166,7 @@ static int node_allowed(struct spu_conte
 	return rval;
 }
 
-static BLOCKING_NOTIFIER_HEAD(spu_switch_notifier);
-
-void spu_switch_notify(struct spu *spu, struct spu_context *ctx)
-{
-	blocking_notifier_call_chain(&spu_switch_notifier,
-			    ctx ? ctx->object_id : 0, spu);
-}
-
-static void notify_spus_active(void)
+void do_notify_spus_active(void)
 {
 	int node;
 
@@ -200,22 +192,15 @@ static void notify_spus_active(void)
 		mutex_unlock(&cbe_spu_info[node].list_mutex);
 	}
 }
+EXPORT_SYMBOL_GPL(do_notify_spus_active);
 
-int spu_switch_event_register(struct notifier_block * n)
-{
-	int ret;
-	ret = blocking_notifier_chain_register(&spu_switch_notifier, n);
-	if (!ret)
-		notify_spus_active();
-	return ret;
-}
-EXPORT_SYMBOL_GPL(spu_switch_event_register);
-
-int spu_switch_event_unregister(struct notifier_block * n)
+#ifndef MODULE
+void notify_spus_active(void)
 {
-	return blocking_notifier_chain_unregister(&spu_switch_notifier, n);
+	do_notify_spus_active();
 }
-EXPORT_SYMBOL_GPL(spu_switch_event_unregister);
+EXPORT_SYMBOL_GPL(notify_spus_active);
+#endif
 
 /**
  * spu_bind_context - bind spu context to physical spu
Index: linux-2.6-new/arch/powerpc/platforms/cell/spufs/syscalls.c
===================================================================
--- linux-2.6-new.orig/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ linux-2.6-new/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -86,5 +86,6 @@ struct spufs_calls spufs_calls = {
 	.spu_run = do_spu_run,
 	.coredump_extra_notes_size = spufs_coredump_extra_notes_size,
 	.coredump_extra_notes_write = spufs_coredump_extra_notes_write,
+	.notify_spus_active = do_notify_spus_active,
 	.owner = THIS_MODULE,
 };
Index: linux-2.6-new/include/asm-powerpc/spu.h
===================================================================
--- linux-2.6-new.orig/include/asm-powerpc/spu.h
+++ linux-2.6-new/include/asm-powerpc/spu.h
@@ -246,6 +246,7 @@ struct spufs_calls {
 						__u32 __user *ustatus);
 	int (*coredump_extra_notes_size)(void);
 	int (*coredump_extra_notes_write)(struct file *file, loff_t *foffset);
+	void (*notify_spus_active)(void);
 	struct module *owner;
 };
 
@@ -298,6 +299,9 @@ struct notifier_block;
 int spu_switch_event_register(struct notifier_block * n);
 int spu_switch_event_unregister(struct notifier_block * n);
 
+extern void notify_spus_active(void);
+extern void do_notify_spus_active(void);
+
 /*
  * This defines the Local Store, Problem Area and Privlege Area of an SPU.
  */

^ permalink raw reply

* Re: [PATCH 1/7] bootwrapper: Add a firmware-independent "raw" target.
From: Grant Likely @ 2007-12-14 15:23 UTC (permalink / raw)
  To: Milton Miller; +Cc: ppcdev
In-Reply-To: <f7eb0ae3da29213720e6b0049deca335@bga.com>

On 12/14/07, Milton Miller <miltonm@bga.com> wrote:
> On Fri Dec 14 10:43:27 EST 2007,  Stephen Neuendorffer wrote:
>
> > From: Grant Likely <grant.likely at secretlab.ca>
> >
> > This target produces a flat binary rather than an ELF file,
> > fixes the entry point at the beginning of the image, and takes
> > a complete device tree with no fixups needed.
> >
> > The device tree must have labels on /#address-cells, the timebase
> > frequency, and the memory size.
> >
> > Signed-off-by: Grant Likely <grant.likely at secretlab.ca>

For the record; this patch was lifted from my dev tree and in turn I
stole it from Scott Wood.

>
> > +$(obj)/zImage.raw: vmlinux $(dts) $(wrapperbits)
> > +       $(call if_changed,wrap,raw,$(dts))
> >
>
> This should be handled by the standard zImage% rule.

It's weird.  On my system the standard zImage rule wouldn't do this
target.  I had to add this rule just to get it to compile.  I've not
yet been motivated to revisit and fix it.

> I'm not sure exactly what platform you are using this on.  Apparently
> it is a legacy firmware that loads the image and jumps to it leaving
> interrupts on and not invalidating the cache.

Heh; actually it's a platform with *no* firmware.  :-)

It's on a Xilinx FPGA.  SDRAM is initialized by the FPGA design and
the kernel image is loaded either with a debugger, or via the
SystemACE device.  In either case, the kernel is the first thing to
run after reset.... oh, and reset is not as complete as one would
normally expect.

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: [PATCH 2/3] mpc82xx: Embedded Planet EP8248E support
From: Scott Wood @ 2007-12-14 15:53 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <EB293853-B27A-4B0E-AEEB-8D3F09E8F12D@kernel.crashing.org>

On Thu, Dec 13, 2007 at 11:19:33PM -0600, Kumar Gala wrote:
> Can we make this a /dts-v1/; since its new.

It's not really new; it's just been collecting dust for a while. :-P

Are there any tools to autoconvert (preferably without losing comments)?

> >+/ {
> >+	model = "EP8248E";
> >+	compatible = "fsl,ep8248e";
> >+	#address-cells = <1>;
> >+	#size-cells = <1>;
> 
> Add a aliases { } and can we use that instead of linux,network-index  
> and linux,planetcore-label.

I don't see any support in the current bootwrapper for aliases.

-Scott

^ permalink raw reply

* Re: [PATCH v2 2/4] [libata] pata_of_platform: OF-Platform PATA device driver
From: Scott Wood @ 2007-12-14 16:09 UTC (permalink / raw)
  To: Olof Johansson
  Cc: linux-ide, Paul Mundt, Arnd Bergmann, Jeff Garzik, linuxppc-dev
In-Reply-To: <20071214082313.GA28118@lixom.net>

On Fri, Dec 14, 2007 at 02:23:13AM -0600, Olof Johansson wrote:
> On Wed, Dec 05, 2007 at 12:39:12PM -0600, Scott Wood wrote:
> > Why is it dependent on anything other than platform bus support and ATA?
> 
> There's no way to specify dependency on platform bus as a config option,
> that's likely what EMBEDDED was meant to do. Some platforms have platform
> bus in spite of being !EMBEDDED, arch/arm/configs/rpc_defconfig seems
> to be among those. PPC too.

If platform bus can't be configged out, then the only dependency should
be the implicit one on ATA (is there anything else whose absence will
stop the code from building, or working if the appropriate platform
device is passed in?).

-Scott

^ permalink raw reply

* Re: [PATCH v2 2/4] [libata] pata_of_platform: OF-Platform PATA device driver
From: Olof Johansson @ 2007-12-14 16:33 UTC (permalink / raw)
  To: Scott Wood
  Cc: linux-ide, Paul Mundt, Jeff Garzik, Arnd Bergmann, linuxppc-dev
In-Reply-To: <20071214160928.GA16607@ld0162-tx32.am.freescale.net>

On Fri, Dec 14, 2007 at 10:09:28AM -0600, Scott Wood wrote:
> On Fri, Dec 14, 2007 at 02:23:13AM -0600, Olof Johansson wrote:
> > On Wed, Dec 05, 2007 at 12:39:12PM -0600, Scott Wood wrote:
> > > Why is it dependent on anything other than platform bus support and ATA?
> > 
> > There's no way to specify dependency on platform bus as a config option,
> > that's likely what EMBEDDED was meant to do. Some platforms have platform
> > bus in spite of being !EMBEDDED, arch/arm/configs/rpc_defconfig seems
> > to be among those. PPC too.
> 
> If platform bus can't be configged out, then the only dependency should
> be the implicit one on ATA (is there anything else whose absence will
> stop the code from building, or working if the appropriate platform
> device is passed in?).

Sure, sounds good to me.


-Olof

^ permalink raw reply

* Re: [PATCH 2/3] mpc82xx: Embedded Planet EP8248E support
From: Kumar Gala @ 2007-12-14 16:28 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20071214155341.GB16269@ld0162-tx32.am.freescale.net>


On Dec 14, 2007, at 9:53 AM, Scott Wood wrote:

> On Thu, Dec 13, 2007 at 11:19:33PM -0600, Kumar Gala wrote:
>> Can we make this a /dts-v1/; since its new.
>
> It's not really new; it's just been collecting dust for a while. :-P

Its new to us on the list :P

> Are there any tools to autoconvert (preferably without losing  
> comments)?

Not sure of jon had a perl script or something.

>>> +/ {
>>> +	model = "EP8248E";
>>> +	compatible = "fsl,ep8248e";
>>> +	#address-cells = <1>;
>>> +	#size-cells = <1>;
>>
>> Add a aliases { } and can we use that instead of linux,network-index
>> and linux,planetcore-label.
>
> I don't see any support in the current bootwrapper for aliases.

Yeah, I was hoping you'd code something up :)

- k

^ permalink raw reply

* Re: [PATCH 05/10] powerpc: Add crash kernel support for 85xx
From: Kumar Gala @ 2007-12-14 16:48 UTC (permalink / raw)
  To: Dale Farnsworth; +Cc: linuxppc-dev
In-Reply-To: <20071122154619.GA26471@xyzzy.farnsworth.org>


On Nov 22, 2007, at 9:46 AM, Dale Farnsworth wrote:

> Add the ability to build a ppc_85xx kernel to run at a physical
> address of 32MB.
>
> Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
> ---
> arch/powerpc/Kconfig                 |    2 +-
> arch/powerpc/kernel/head_fsl_booke.S |   23 ++++++++++++++++++-----
> arch/powerpc/mm/fsl_booke_mmu.c      |    6 +++---
> 3 files changed, 22 insertions(+), 9 deletions(-)
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 805b4d1..d405298 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -253,7 +253,7 @@ config KEXEC
>
> config CRASH_DUMP
> 	bool "Build a kdump crash kernel (EXPERIMENTAL)"
> -	depends on PPC_MULTIPLATFORM && EXPERIMENTAL
> +	depends on (PPC_MULTIPLATFORM || PPC_85xx) && EXPERIMENTAL
> 	help
> 	  Build a kernel suitable for use as a kdump capture kernel.
> 	  The kernel will be linked at a different address than normal, and
> diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/ 
> kernel/head_fsl_booke.S
> index 4b98227..1c9685f 100644
> --- a/arch/powerpc/kernel/head_fsl_booke.S
> +++ b/arch/powerpc/kernel/head_fsl_booke.S
> @@ -41,6 +41,12 @@
> #include <asm/asm-offsets.h>
> #include "head_booke.h"
>
> +#ifdef CONFIG_CRASH_DUMP
> +#define INITIAL_BOOKE_PAGESZ (BOOKE_PAGESZ_64M)
> +#else
> +#define INITIAL_BOOKE_PAGESZ (BOOKE_PAGESZ_16M)
> +#endif

I'm ok with bumping the first page to 64M in all cases.

>
> +
> /* As with the other PowerPC ports, it is expected that when code
>  * execution begins here, the following registers contain valid, yet
>  * optional, information:
> @@ -75,6 +81,7 @@ _ENTRY(_start);
>  * boot loader and load a single entry in TLB1[0] to map the
>  * first 16M of kernel memory.  Any boot info passed from the
>  * bootloader needs to live in this first 16M.
> + * Note that for crash (kdump) kernels, the first 64M is mapped.
>  *
>  * Requirement on bootloader:
>  *  - The page we're executing in needs to reside in TLB1 and
> @@ -167,7 +174,7 @@ skpinv:	addi	r6,r6,1				/* Increment */
> 	mtspr	SPRN_MAS0,r7
> 	tlbre
>
> -	/* Just modify the entry ID and EPN for the temp mapping */
> +	/* Just modify the entry ID, EPN and RPN for the temp mapping */
> 	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
> 	rlwimi	r7,r5,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r5) */
> 	mtspr	SPRN_MAS0,r7
> @@ -177,9 +184,12 @@ skpinv:	addi	r6,r6,1				/* Increment */
> 	ori	r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
> 	mtspr	SPRN_MAS1,r6
> 	mfspr	r6,SPRN_MAS2
> -	li	r7,0		/* temp EPN = 0 */
> +	lis	r7,PHYSICAL_START@h
> 	rlwimi	r7,r6,0,20,31
> 	mtspr	SPRN_MAS2,r7
> +	mfspr	r6,SPRN_MAS3
> +	rlwimi	r7,r6,0,20,31
> +	mtspr	SPRN_MAS3,r7
> 	tlbwe
>
> 	xori	r6,r4,1
> @@ -222,11 +232,11 @@ skpinv:	addi	r6,r6,1				/* Increment */
> 	lis	r6,0x1000		/* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
> 	mtspr	SPRN_MAS0,r6
> 	lis	r6,(MAS1_VALID|MAS1_IPROT)@h
> -	ori	r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_16M))@l
> +	ori	r6,r6,(MAS1_TSIZE(INITIAL_BOOKE_PAGESZ))@l
> 	mtspr	SPRN_MAS1,r6
> 	li	r7,0
> -	lis	r6,KERNELBASE@h
> -	ori	r6,r6,KERNELBASE@l
> +	lis	r6,PAGE_OFFSET@h
> +	ori	r6,r6,PAGE_OFFSET@l
> 	rlwimi	r6,r7,0,20,31
> 	mtspr	SPRN_MAS2,r6
> 	li	r7,(MAS3_SX|MAS3_SW|MAS3_SR)
> @@ -234,6 +244,9 @@ skpinv:	addi	r6,r6,1				/* Increment */
> 	tlbwe
>
> /* 7. Jump to KERNELBASE mapping */
> +	lis	r6,KERNELBASE@h
> +	ori	r6,r6,KERNELBASE@l
> +	rlwimi	r6,r7,0,20,31
> 	lis	r7,MSR_KERNEL@h
> 	ori	r7,r7,MSR_KERNEL@l
> 	bl	1f			/* Find our address */
> diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/ 
> fsl_booke_mmu.c
> index 17139da..c93a966 100644
> --- a/arch/powerpc/mm/fsl_booke_mmu.c
> +++ b/arch/powerpc/mm/fsl_booke_mmu.c
> @@ -165,15 +165,15 @@ void invalidate_tlbcam_entry(int index)
> void __init cam_mapin_ram(unsigned long cam0, unsigned long cam1,
> 		unsigned long cam2)
> {
> -	settlbcam(0, KERNELBASE, PPC_MEMSTART, cam0, _PAGE_KERNEL, 0);
> +	settlbcam(0, PAGE_OFFSET, PPC_MEMSTART, cam0, _PAGE_KERNEL, 0);
> 	tlbcam_index++;
> 	if (cam1) {
> 		tlbcam_index++;
> -		settlbcam(1, KERNELBASE+cam0, PPC_MEMSTART+cam0, cam1,  
> _PAGE_KERNEL, 0);
> +		settlbcam(1, PAGE_OFFSET+cam0, PPC_MEMSTART+cam0, cam1,  
> _PAGE_KERNEL, 0);
> 	}
> 	if (cam2) {
> 		tlbcam_index++;
> -		settlbcam(2, KERNELBASE+cam0+cam1, PPC_MEMSTART+cam0+cam1, cam2,  
> _PAGE_KERNEL, 0);
> +		settlbcam(2, PAGE_OFFSET+cam0+cam1, PPC_MEMSTART+cam0+cam1, cam2,  
> _PAGE_KERNEL, 0);
> 	}
> }

The rest looks good.  Does this mean we can boot a e500 kernel at a  
non-zero physical address?  (can we run or is the non-zero phy just  
for a short period of init time).

- k

^ permalink raw reply

* Re: [PATCH 05/10] powerpc: Add crash kernel support for 85xx
From: Dale Farnsworth @ 2007-12-14 17:23 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <7AF0D992-6B4E-475C-949B-FAE4DDE03D3A@kernel.crashing.org>

On Fri, Dec 14, 2007 at 10:48:58AM -0600, Kumar Gala wrote:
> On Nov 22, 2007, at 9:46 AM, Dale Farnsworth wrote:
> 
> > Add the ability to build a ppc_85xx kernel to run at a physical
> > address of 32MB.
> >
> > Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
> > ---
> > arch/powerpc/Kconfig                 |    2 +-
> > arch/powerpc/kernel/head_fsl_booke.S |   23 ++++++++++++++++++-----
> > arch/powerpc/mm/fsl_booke_mmu.c      |    6 +++---
> > 3 files changed, 22 insertions(+), 9 deletions(-)
> >
> > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> > index 805b4d1..d405298 100644
> > --- a/arch/powerpc/Kconfig
> > +++ b/arch/powerpc/Kconfig
> > @@ -253,7 +253,7 @@ config KEXEC
> >
> > config CRASH_DUMP
> > 	bool "Build a kdump crash kernel (EXPERIMENTAL)"
> > -	depends on PPC_MULTIPLATFORM && EXPERIMENTAL
> > +	depends on (PPC_MULTIPLATFORM || PPC_85xx) && EXPERIMENTAL
> > 	help
> > 	  Build a kernel suitable for use as a kdump capture kernel.
> > 	  The kernel will be linked at a different address than normal, and
> > diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/ 
> > kernel/head_fsl_booke.S
> > index 4b98227..1c9685f 100644
> > --- a/arch/powerpc/kernel/head_fsl_booke.S
> > +++ b/arch/powerpc/kernel/head_fsl_booke.S
> > @@ -41,6 +41,12 @@
> > #include <asm/asm-offsets.h>
> > #include "head_booke.h"
> >
> > +#ifdef CONFIG_CRASH_DUMP
> > +#define INITIAL_BOOKE_PAGESZ (BOOKE_PAGESZ_64M)
> > +#else
> > +#define INITIAL_BOOKE_PAGESZ (BOOKE_PAGESZ_16M)
> > +#endif
> 
> I'm ok with bumping the first page to 64M in all cases.

OK, I'll make that change in the next rev.  Thanks.

<snip>

> The rest looks good.  Does this mean we can boot a e500 kernel at a
> non-zero physical address?  (can we run or is the non-zero phy just
> for a short period of init time).

Yes, with this series of patches, we can boot and run with a classic ppc
or e500 kernel at 32MB physical (0xc2000000 virtual).  Note that on
classic, we still need memory at phys 0 for the exception vectors.
On e500 IIRC, we don't use the vectors at phys 0, but we still write
the trampoline vectors there.  I just didn't bother making that conditional.

I'll post an updated series soon, with hopes of getting it into 2.6.25

-Dale

^ permalink raw reply

* RE: [PATCH 1/7] bootwrapper: Add a firmware-independent "raw" target.
From: Stephen Neuendorffer @ 2007-12-14 17:31 UTC (permalink / raw)
  To: Milton Miller; +Cc: ppcdev
In-Reply-To: <f7eb0ae3da29213720e6b0049deca335@bga.com>

=20

> -----Original Message-----
> From: Milton Miller [mailto:miltonm@bga.com]=20
> Sent: Friday, December 14, 2007 12:06 AM
> To: Stephen Neuendorffer
> Cc: ppcdev; Grant Likely
> Subject: Re: [PATCH 1/7] bootwrapper: Add a=20
> firmware-independent "raw" target.
>=20
> On Fri Dec 14 10:43:27 EST 2007,  Stephen Neuendorffer wrote:
>=20
> > From: Grant Likely <grant.likely at secretlab.ca>
> >
> > This target produces a flat binary rather than an ELF file,
> > fixes the entry point at the beginning of the image, and takes
> > a complete device tree with no fixups needed.
> >
> > The device tree must have labels on /#address-cells, the timebase
> > frequency, and the memory size.
> >
> > Signed-off-by: Grant Likely <grant.likely at secretlab.ca>
> > ---
>=20
>=20
> You indicated in the intro in 0/ that this was not ready, and you=20
> didn't include your own s-o-b, but you did not put any statements to=20
> that effect in the header.  The intro is not copied into patchwork,=20
> which maintainers often use when deciding what to push.

Sorry... Still trying to figure out the process.

> Now on to why this should not be merged:
>=20
> In addition to the above, it changes the build rules.  It tries to=20
> change wrapper to assemble the .dtb into a .o from a .S file, but=20
> doesn't set any flags to force the assembler into the right mode.  In=20
> contrast the linker is controlled by the .lds linker script.
>=20
> In addition, the requirement for assembly labels can easily be=20
> eliminated.  As mentioned above, they are used for 3=20
> properties.  With=20
> the existing library (in 2.6.24 and earlier), call simple_malloc_init=20
> with a small bss array (like BSS_STACK does to allocate stack), and=20
> then read the properties out of the device tree.  At that point, call=20
> simple_malloc_init a second time using the found memory size.   As I=20
> said the last time this was posted, my patches to boot from kexec=20
> implemented this strategy.
>=20
> However, with the new libfdt, which is already in for-2.6.25,=20
> we should=20
> no longer need malloc() to simple read the tree.   At least that is=20
> what was advertised.

Yes, I agree, I just haven't had a chance to go back and write that code
yet...

Thanks for the comments,
Steve

^ permalink raw reply

* [PATCH v3 0/3] OF-platform PATA driver
From: Anton Vorontsov @ 2007-12-14 18:21 UTC (permalink / raw)
  To: linuxppc-dev, linux-ide
  Cc: Jeff Garzik, Arnd Bergmann, Paul Mundt, Olof Johansson

Hi all,

Here is the third version of the OF-platform PATA driver and
related patches.


Changes since v2:
- "PPC" added to PATA_PLATFORM "depends on" Kconfig entry;
  I didn't remove EMBEDDED "depends on" -- this wasn't discussed
  much and these patches should not depend on the decision.
- cosmetic fixes;
- "s/ioport_shift/reg_shift/g" patch dropped.

Changes since v1:
- __pata_platform_probe now accepts pio_mask argument;
- pata-platform compatible property renamed to ata-generic;
- pata_of_platform understands pio-mode property. It's used to pass
  pio_mask to the __pata_platform_probe. That is, in ata-generic
  context pio-mode means "pio mode the bus already configured for";
- New optional patch that renames pata_platform_info's
  ioport_shift to reg_shift.

Changes since RFC:
- nuked drivers/ata/pata_platform.h;
- powerpc bits: proper localbus node added.

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.net/bd2

^ permalink raw reply

* [PATCH 1/3] [libata] pata_platform: make probe and remove functions device type neutral
From: Anton Vorontsov @ 2007-12-14 18:24 UTC (permalink / raw)
  To: linuxppc-dev, linux-ide
  Cc: Jeff Garzik, Arnd Bergmann, Paul Mundt, Olof Johansson
In-Reply-To: <20071214182109.GA858@localhost.localdomain>

Split pata_platform_{probe,remove} into two pieces:
1. pata_platform_{probe,remove} -- platform_device-dependant bits;
2. __ptata_platform_{probe,remove} -- device type neutral bits.

This is done to not duplicate code for the OF-platform driver.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-by: Olof Johansson <olof@lixom.net>
---
 drivers/ata/pata_platform.c   |  144 ++++++++++++++++++++++++----------------
 include/linux/pata_platform.h |    9 +++
 2 files changed, 95 insertions(+), 58 deletions(-)

diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index ac03a90..224bb6c 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -93,14 +93,9 @@ static struct ata_port_operations pata_platform_port_ops = {
 };
 
 static void pata_platform_setup_port(struct ata_ioports *ioaddr,
-				     struct pata_platform_info *info)
+				     unsigned int shift)
 {
-	unsigned int shift = 0;
-
 	/* Fixup the port shift for platforms that need it */
-	if (info && info->ioport_shift)
-		shift = info->ioport_shift;
-
 	ioaddr->data_addr	= ioaddr->cmd_addr + (ATA_REG_DATA    << shift);
 	ioaddr->error_addr	= ioaddr->cmd_addr + (ATA_REG_ERR     << shift);
 	ioaddr->feature_addr	= ioaddr->cmd_addr + (ATA_REG_FEATURE << shift);
@@ -114,8 +109,13 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
 }
 
 /**
- *	pata_platform_probe		-	attach a platform interface
- *	@pdev: platform device
+ *	__pata_platform_probe		-	attach a platform interface
+ *	@dev: device
+ *	@io_res: Resource representing I/O base
+ *	@ctl_res: Resource representing CTL base
+ *	@irq_res: Resource representing IRQ and its flags
+ *	@ioport_shift: I/O port shift
+ *	@__pio_mask: PIO mask
  *
  *	Register a platform bus IDE interface. Such interfaces are PIO and we
  *	assume do not support IRQ sharing.
@@ -135,42 +135,18 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
  *
  *	If no IRQ resource is present, PIO polling mode is used instead.
  */
-static int __devinit pata_platform_probe(struct platform_device *pdev)
+int __devinit __pata_platform_probe(struct device *dev,
+				    struct resource *io_res,
+				    struct resource *ctl_res,
+				    struct resource *irq_res,
+				    unsigned int ioport_shift,
+				    int __pio_mask)
 {
-	struct resource *io_res, *ctl_res;
 	struct ata_host *host;
 	struct ata_port *ap;
-	struct pata_platform_info *pp_info;
 	unsigned int mmio;
-	int irq;
-
-	/*
-	 * Simple resource validation ..
-	 */
-	if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
-		dev_err(&pdev->dev, "invalid number of resources\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Get the I/O base first
-	 */
-	io_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (io_res == NULL) {
-		io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		if (unlikely(io_res == NULL))
-			return -EINVAL;
-	}
-
-	/*
-	 * Then the CTL base
-	 */
-	ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
-	if (ctl_res == NULL) {
-		ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		if (unlikely(ctl_res == NULL))
-			return -EINVAL;
-	}
+	int irq = 0;
+	int irq_flags = 0;
 
 	/*
 	 * Check for MMIO
@@ -181,20 +157,21 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
 	/*
 	 * And the IRQ
 	 */
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		irq = 0;	/* no irq */
+	if (irq_res && irq_res->start > 0) {
+		irq = irq_res->start;
+		irq_flags = irq_res->flags;
+	}
 
 	/*
 	 * Now that that's out of the way, wire up the port..
 	 */
-	host = ata_host_alloc(&pdev->dev, 1);
+	host = ata_host_alloc(dev, 1);
 	if (!host)
 		return -ENOMEM;
 	ap = host->ports[0];
 
 	ap->ops = &pata_platform_port_ops;
-	ap->pio_mask = pio_mask;
+	ap->pio_mask = __pio_mask;
 	ap->flags |= ATA_FLAG_SLAVE_POSS;
 
 	/*
@@ -209,25 +186,24 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
 	 * Handle the MMIO case
 	 */
 	if (mmio) {
-		ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, io_res->start,
+		ap->ioaddr.cmd_addr = devm_ioremap(dev, io_res->start,
 				io_res->end - io_res->start + 1);
-		ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start,
+		ap->ioaddr.ctl_addr = devm_ioremap(dev, ctl_res->start,
 				ctl_res->end - ctl_res->start + 1);
 	} else {
-		ap->ioaddr.cmd_addr = devm_ioport_map(&pdev->dev, io_res->start,
+		ap->ioaddr.cmd_addr = devm_ioport_map(dev, io_res->start,
 				io_res->end - io_res->start + 1);
-		ap->ioaddr.ctl_addr = devm_ioport_map(&pdev->dev, ctl_res->start,
+		ap->ioaddr.ctl_addr = devm_ioport_map(dev, ctl_res->start,
 				ctl_res->end - ctl_res->start + 1);
 	}
 	if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) {
-		dev_err(&pdev->dev, "failed to map IO/CTL base\n");
+		dev_err(dev, "failed to map IO/CTL base\n");
 		return -ENOMEM;
 	}
 
 	ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
 
-	pp_info = pdev->dev.platform_data;
-	pata_platform_setup_port(&ap->ioaddr, pp_info);
+	pata_platform_setup_port(&ap->ioaddr, ioport_shift);
 
 	ata_port_desc(ap, "%s cmd 0x%llx ctl 0x%llx", mmio ? "mmio" : "ioport",
 		      (unsigned long long)io_res->start,
@@ -235,26 +211,78 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
 
 	/* activate */
 	return ata_host_activate(host, irq, irq ? ata_interrupt : NULL,
-				 pp_info ? pp_info->irq_flags : 0,
-				 &pata_platform_sht);
+				 irq_flags, &pata_platform_sht);
 }
+EXPORT_SYMBOL_GPL(__pata_platform_probe);
 
 /**
- *	pata_platform_remove	-	unplug a platform interface
- *	@pdev: platform device
+ *	__pata_platform_remove		-	unplug a platform interface
+ *	@dev: device
  *
  *	A platform bus ATA device has been unplugged. Perform the needed
  *	cleanup. Also called on module unload for any active devices.
  */
-static int __devexit pata_platform_remove(struct platform_device *pdev)
+int __devexit __pata_platform_remove(struct device *dev)
 {
-	struct device *dev = &pdev->dev;
 	struct ata_host *host = dev_get_drvdata(dev);
 
 	ata_host_detach(host);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(__pata_platform_remove);
+
+static int __devinit pata_platform_probe(struct platform_device *pdev)
+{
+	struct resource *io_res;
+	struct resource *ctl_res;
+	struct resource *irq_res;
+	struct pata_platform_info *pp_info = pdev->dev.platform_data;
+
+	/*
+	 * Simple resource validation ..
+	 */
+	if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
+		dev_err(&pdev->dev, "invalid number of resources\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Get the I/O base first
+	 */
+	io_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (io_res == NULL) {
+		io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (unlikely(io_res == NULL))
+			return -EINVAL;
+	}
+
+	/*
+	 * Then the CTL base
+	 */
+	ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
+	if (ctl_res == NULL) {
+		ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		if (unlikely(ctl_res == NULL))
+			return -EINVAL;
+	}
+
+	/*
+	 * And the IRQ
+	 */
+	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (irq_res)
+		irq_res->flags = pp_info ? pp_info->irq_flags : 0;
+
+	return __pata_platform_probe(&pdev->dev, io_res, ctl_res, irq_res,
+				     pp_info ? pp_info->ioport_shift : 0,
+				     pio_mask);
+}
+
+static int __devexit pata_platform_remove(struct platform_device *pdev)
+{
+	return __pata_platform_remove(&pdev->dev);
+}
 
 static struct platform_driver pata_platform_driver = {
 	.probe		= pata_platform_probe,
diff --git a/include/linux/pata_platform.h b/include/linux/pata_platform.h
index 5799e8d..6a7a92d 100644
--- a/include/linux/pata_platform.h
+++ b/include/linux/pata_platform.h
@@ -15,4 +15,13 @@ struct pata_platform_info {
 	unsigned int irq_flags;
 };
 
+extern int __devinit __pata_platform_probe(struct device *dev,
+					   struct resource *io_res,
+					   struct resource *ctl_res,
+					   struct resource *irq_res,
+					   unsigned int ioport_shift,
+					   int __pio_mask);
+
+extern int __devexit __pata_platform_remove(struct device *dev);
+
 #endif /* __LINUX_PATA_PLATFORM_H */
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH 2/3] [libata] pata_of_platform: OF-Platform PATA device driver
From: Anton Vorontsov @ 2007-12-14 18:24 UTC (permalink / raw)
  To: linuxppc-dev, linux-ide
  Cc: Jeff Garzik, Arnd Bergmann, Paul Mundt, Olof Johansson
In-Reply-To: <20071214182109.GA858@localhost.localdomain>

This driver nicely wraps around pata_platform library functions,
and provides OF platform bus bindings to the PATA devices.

Also add || PPC to the PATA_PLATFORM's "depends on" Kconfig entry,
needed for PA Semi Electra.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Reviewed-by: Olof Johansson <olof@lixom.net>
---
 drivers/ata/Kconfig            |   12 ++++-
 drivers/ata/Makefile           |    1 +
 drivers/ata/pata_of_platform.c |  104 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 116 insertions(+), 1 deletions(-)
 create mode 100644 drivers/ata/pata_of_platform.c

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index ba63619..64b4964 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -607,13 +607,23 @@ config PATA_WINBOND_VLB
 
 config PATA_PLATFORM
 	tristate "Generic platform device PATA support"
-	depends on EMBEDDED || ARCH_RPC
+	depends on EMBEDDED || ARCH_RPC || PPC
 	help
 	  This option enables support for generic directly connected ATA
 	  devices commonly found on embedded systems.
 
 	  If unsure, say N.
 
+config PATA_OF_PLATFORM
+	tristate "OpenFirmware platform device PATA support"
+	depends on PATA_PLATFORM && PPC_OF
+	help
+	  This option enables support for generic directly connected ATA
+	  devices commonly found on embedded systems with OpenFirmware
+	  bindings.
+
+	  If unsure, say N.
+
 config PATA_ICSIDE
 	tristate "Acorn ICS PATA support"
 	depends on ARM && ARCH_ACORN
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index b13feb2..ebcee64 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_PATA_IXP4XX_CF)	+= pata_ixp4xx_cf.o
 obj-$(CONFIG_PATA_SCC)		+= pata_scc.o
 obj-$(CONFIG_PATA_BF54X)	+= pata_bf54x.o
 obj-$(CONFIG_PATA_PLATFORM)	+= pata_platform.o
+obj-$(CONFIG_PATA_OF_PLATFORM)	+= pata_of_platform.o
 obj-$(CONFIG_PATA_ICSIDE)	+= pata_icside.o
 # Should be last but two libata driver
 obj-$(CONFIG_PATA_ACPI)		+= pata_acpi.o
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
new file mode 100644
index 0000000..4daf118
--- /dev/null
+++ b/drivers/ata/pata_of_platform.c
@@ -0,0 +1,104 @@
+/*
+ * OF-platform PATA driver
+ *
+ * Copyright (c) 2007  MontaVista Software, Inc.
+ *                     Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pata_platform.h>
+
+static int __devinit pata_of_platform_probe(struct of_device *ofdev,
+					    const struct of_device_id *match)
+{
+	int ret;
+	struct device_node *dn = ofdev->node;
+	struct resource io_res;
+	struct resource ctl_res;
+	struct resource irq_res;
+	unsigned int reg_shift = 0;
+	int pio_mode = 0;
+	int pio_mask;
+	const u32 *prop;
+
+	ret = of_address_to_resource(dn, 0, &io_res);
+	if (ret) {
+		dev_err(&ofdev->dev, "can't get IO address from "
+			"device tree\n");
+		return -EINVAL;
+	}
+
+	ret = of_address_to_resource(dn, 1, &ctl_res);
+	if (ret) {
+		dev_err(&ofdev->dev, "can't get CTL address from "
+			"device tree\n");
+		return -EINVAL;
+	}
+
+	ret = of_irq_to_resource(dn, 0, &irq_res);
+	if (ret == NO_IRQ)
+		irq_res.start = irq_res.end = -1;
+	else
+		irq_res.flags = 0;
+
+	prop = (u32 *)of_get_property(dn, "reg-shift", NULL);
+	if (prop)
+		reg_shift = *prop;
+
+	prop = (u32 *)of_get_property(dn, "pio-mode", NULL);
+	if (prop) {
+		pio_mode = *prop;
+		if (pio_mode > 6) {
+			dev_err(&ofdev->dev, "invalid pio-mode\n");
+			return -EINVAL;
+		}
+	} else {
+		dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n");
+	}
+
+	pio_mask = 1 << pio_mode;
+	pio_mask |= (1 << pio_mode) - 1;
+
+	return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res,
+				     reg_shift, pio_mask);
+}
+
+static int __devexit pata_of_platform_remove(struct of_device *ofdev)
+{
+	return __pata_platform_remove(&ofdev->dev);
+}
+
+static struct of_device_id pata_of_platform_match[] = {
+	{ .compatible = "ata-generic", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pata_of_platform_match);
+
+static struct of_platform_driver pata_of_platform_driver = {
+	.name		= "pata_of_platform",
+	.match_table	= pata_of_platform_match,
+	.probe		= pata_of_platform_probe,
+	.remove		= __devexit_p(pata_of_platform_remove),
+};
+
+static int __init pata_of_platform_init(void)
+{
+	return of_register_platform_driver(&pata_of_platform_driver);
+}
+module_init(pata_of_platform_init);
+
+static void __exit pata_of_platform_exit(void)
+{
+	of_unregister_platform_driver(&pata_of_platform_driver);
+}
+module_exit(pata_of_platform_exit);
+
+MODULE_DESCRIPTION("OF-platform PATA driver");
+MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL");
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH 3/3] [POWERPC] MPC8349E-mITX: introduce localbus and pata nodes
From: Anton Vorontsov @ 2007-12-14 18:25 UTC (permalink / raw)
  To: linuxppc-dev, linux-ide
  Cc: Jeff Garzik, Arnd Bergmann, Paul Mundt, Olof Johansson
In-Reply-To: <20071214182109.GA858@localhost.localdomain>

This patch adds localbus and pata nodes to use CF IDE interface
on MPC8349E-mITX boards.

Patch also adds code to probe localbus.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-by: Olof Johansson <olof@lixom.net>
---
 arch/powerpc/boot/dts/mpc8349emitx.dts    |   17 ++++++++++++++++-
 arch/powerpc/platforms/83xx/mpc834x_itx.c |   17 +++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 5072f6d..8440943 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -249,6 +249,21 @@
 		device_type = "pci";
 	};
 
+	localbus@e0005000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8349e-localbus",
+			     "fsl,pq2pro-localbus";
+		reg = <e0005000 d8>;
+		ranges = <3 0 f0000000 210>;
 
-
+		pata@3,0 {
+			compatible = "fsl,mpc8349emitx-pata", "ata-generic";
+			reg = <3 0 10 3 20c 4>;
+			reg-shift = <1>;
+			pio-mode = <6>;
+			interrupts = <17 8>;
+			interrupt-parent = <&ipic>;
+		};
+	};
 };
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index aa76819..4797850 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
+#include <linux/of_platform.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -37,6 +38,22 @@
 
 #include "mpc83xx.h"
 
+static struct of_device_id mpc834x_itx_ids[] = {
+	{ .compatible = "fsl,pq2pro-localbus", },
+	{},
+};
+
+static int __init mpc834x_itx_declare_of_platform_devices(void)
+{
+	if (!machine_is(mpc834x_itx))
+		return 0;
+
+	of_platform_bus_probe(NULL, mpc834x_itx_ids, NULL);
+
+	return 0;
+}
+device_initcall(mpc834x_itx_declare_of_platform_devices);
+
 /* ************************************************************************
  *
  * Setup the architecture
-- 
1.5.2.2

^ permalink raw reply related

* Re: [PATCH 2/3] mpc82xx: Embedded Planet EP8248E support
From: Scott Wood @ 2007-12-14 18:23 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <5898D87A-231D-4CCB-9538-808562F08D57@kernel.crashing.org>

Kumar Gala wrote:
> 
> On Dec 14, 2007, at 9:53 AM, Scott Wood wrote:
> 
>> On Thu, Dec 13, 2007 at 11:19:33PM -0600, Kumar Gala wrote:
>>> Can we make this a /dts-v1/; since its new.
>>
>> It's not really new; it's just been collecting dust for a while. :-P
> 
> Its new to us on the list :P

I thought it got sent out at least once a long time ago...

In any case, I thought that one of the main reasons for the version tag 
is so that the whole world doesn't have to switch at once?

>> Are there any tools to autoconvert (preferably without losing comments)?
> 
> Not sure of jon had a perl script or something.

Jon, anything?

>>>> +/ {
>>>> +    model = "EP8248E";
>>>> +    compatible = "fsl,ep8248e";
>>>> +    #address-cells = <1>;
>>>> +    #size-cells = <1>;
>>>
>>> Add a aliases { } and can we use that instead of linux,network-index
>>> and linux,planetcore-label.
>>
>> I don't see any support in the current bootwrapper for aliases.
> 
> Yeah, I was hoping you'd code something up :)

I'll leave that to those who actually care about using aliases. :-)

-Scott

^ permalink raw reply

* [PATCH] [POWERPC] booting-without-of: localbus should not include board name
From: Anton Vorontsov @ 2007-12-14 18:48 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev

Fix documentation once and for ever, because I'm pretty tired of
repeating that I am merely following it. ;-)

http://ozlabs.org/pipermail/linuxppc-dev/2007-December/048096.html

http://ozlabs.org/pipermail/linuxppc-dev/2007-November/046977.html
http://ozlabs.org/pipermail/linuxppc-dev/2007-November/046979.html

http://ozlabs.org/pipermail/linuxppc-dev/2007-October/044411.html
http://ozlabs.org/pipermail/linuxppc-dev/2007-October/044413.html

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 Documentation/powerpc/booting-without-of.txt |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index ee0209a..b3948fa 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -2091,8 +2091,7 @@ platforms are moved over to use the flattened-device-tree model.
 
    Example:
 	localbus@f0010100 {
-		compatible = "fsl,mpc8272ads-localbus",
-		             "fsl,mpc8272-localbus",
+		compatible = "fsl,mpc8272-localbus",
 		             "fsl,pq2-localbus";
 		#address-cells = <2>;
 		#size-cells = <1>;
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH v2 4/4] Freescale enhanced Local Bus Controller FCM NAND support.
From: Scott Wood @ 2007-12-14 18:56 UTC (permalink / raw)
  To: dwmw2; +Cc: linuxppc-dev, linux-mtd

Signed-off-by: Nick Spence <nick.spence@freescale.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
Respun according to feedback; also, fixed a couple direct accesses
of iomem.

 drivers/mtd/nand/Kconfig         |    9 +
 drivers/mtd/nand/Makefile        |    1 +
 drivers/mtd/nand/fsl_elbc_nand.c | 1217 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 1227 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/fsl_elbc_nand.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 246d451..05d976c 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -306,4 +306,13 @@ config MTD_ALAUDA
 	  These two (and possibly other) Alauda-based cardreaders for
 	  SmartMedia and xD allow raw flash access.
 
+config MTD_NAND_FSL_ELBC
+	tristate "NAND support for Freescale eLBC controllers"
+	depends on MTD_NAND && PPC_OF
+	help
+	  Various Freescale chips, including the 8313, include a NAND Flash
+	  Controller Module with built-in hardware ECC capabilities.
+	  Enabling this option will enable you to use this to control
+	  external NAND devices.
+
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 3ad6c01..d0d4de2 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -29,5 +29,6 @@ obj-$(CONFIG_MTD_NAND_CM_X270)		+= cmx270_nand.o
 obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)	+= excite_nandflash.o
 obj-$(CONFIG_MTD_NAND_PLATFORM)		+= plat_nand.o
 obj-$(CONFIG_MTD_ALAUDA)		+= alauda.o
+obj-$(CONFIG_MTD_NAND_FSL_ELBC)		+= fsl_elbc_nand.o
 
 nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
new file mode 100644
index 0000000..e17085f
--- /dev/null
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -0,0 +1,1217 @@
+/* Freescale Enhanced Local Bus Controller NAND driver
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor
+ *
+ * Authors: Nick Spence <nick.spence@freescale.com>,
+ *          Scott Wood <scottwood@freescale.com>
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/io.h>
+
+#if 0
+#define ELBC_NAND_DEBUG_LVL 6
+#endif
+
+#ifdef ELBC_NAND_DEBUG_LVL
+static int fcm_debug_level = ELBC_NAND_DEBUG_LVL;
+#define FCM_DEBUG(n, args...)		\
+	do {					\
+		if (n <= fcm_debug_level)	\
+			pr_dbg(args);	\
+	} while(0)
+#else
+#define FCM_DEBUG(n, dev, args...) do { } while(0)
+#endif
+
+#define MAX_BANKS 8
+#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
+#define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
+
+struct elbc_bank {
+	__be32 br;             /**< Base Register  */
+#define BR_BA           0xFFFF8000
+#define BR_BA_SHIFT             15
+#define BR_PS           0x00001800
+#define BR_PS_SHIFT             11
+#define BR_PS_8         0x00000800  /* Port Size 8 bit */
+#define BR_PS_16        0x00001000  /* Port Size 16 bit */
+#define BR_PS_32        0x00001800  /* Port Size 32 bit */
+#define BR_DECC         0x00000600
+#define BR_DECC_SHIFT            9
+#define BR_DECC_OFF     0x00000000  /* HW ECC checking and generation off */
+#define BR_DECC_CHK     0x00000200  /* HW ECC checking on, generation off */
+#define BR_DECC_CHK_GEN 0x00000400  /* HW ECC checking and generation on */
+#define BR_WP           0x00000100
+#define BR_WP_SHIFT              8
+#define BR_MSEL         0x000000E0
+#define BR_MSEL_SHIFT            5
+#define BR_MS_GPCM      0x00000000  /* GPCM */
+#define BR_MS_FCM       0x00000020  /* FCM */
+#define BR_MS_SDRAM     0x00000060  /* SDRAM */
+#define BR_MS_UPMA      0x00000080  /* UPMA */
+#define BR_MS_UPMB      0x000000A0  /* UPMB */
+#define BR_MS_UPMC      0x000000C0  /* UPMC */
+#define BR_V            0x00000001
+#define BR_V_SHIFT               0
+#define BR_RES          ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
+
+	__be32 or;             /**< Base Register  */
+#define OR0 0x5004
+#define OR1 0x500C
+#define OR2 0x5014
+#define OR3 0x501C
+#define OR4 0x5024
+#define OR5 0x502C
+#define OR6 0x5034
+#define OR7 0x503C
+
+#define OR_FCM_AM               0xFFFF8000
+#define OR_FCM_AM_SHIFT                 15
+#define OR_FCM_BCTLD            0x00001000
+#define OR_FCM_BCTLD_SHIFT              12
+#define OR_FCM_PGS              0x00000400
+#define OR_FCM_PGS_SHIFT                10
+#define OR_FCM_CSCT             0x00000200
+#define OR_FCM_CSCT_SHIFT                9
+#define OR_FCM_CST              0x00000100
+#define OR_FCM_CST_SHIFT                 8
+#define OR_FCM_CHT              0x00000080
+#define OR_FCM_CHT_SHIFT                 7
+#define OR_FCM_SCY              0x00000070
+#define OR_FCM_SCY_SHIFT                 4
+#define OR_FCM_SCY_1            0x00000010
+#define OR_FCM_SCY_2            0x00000020
+#define OR_FCM_SCY_3            0x00000030
+#define OR_FCM_SCY_4            0x00000040
+#define OR_FCM_SCY_5            0x00000050
+#define OR_FCM_SCY_6            0x00000060
+#define OR_FCM_SCY_7            0x00000070
+#define OR_FCM_RST              0x00000008
+#define OR_FCM_RST_SHIFT                 3
+#define OR_FCM_TRLX             0x00000004
+#define OR_FCM_TRLX_SHIFT                2
+#define OR_FCM_EHTR             0x00000002
+#define OR_FCM_EHTR_SHIFT                1
+};
+
+struct elbc_regs {
+	struct elbc_bank bank[8];
+	u8 res0[0x28];
+	__be32 mar;             /**< UPM Address Register */
+	u8 res1[0x4];
+	__be32 mamr;            /**< UPMA Mode Register */
+	__be32 mbmr;            /**< UPMB Mode Register */
+	__be32 mcmr;            /**< UPMC Mode Register */
+	u8 res2[0x8];
+	__be32 mrtpr;           /**< Memory Refresh Timer Prescaler Register */
+	__be32 mdr;             /**< UPM Data Register */
+	u8 res3[0x4];
+	__be32 lsor;            /**< Special Operation Initiation Register */
+	__be32 lsdmr;           /**< SDRAM Mode Register */
+	u8 res4[0x8];
+	__be32 lurt;            /**< UPM Refresh Timer */
+	__be32 lsrt;            /**< SDRAM Refresh Timer */
+	u8 res5[0x8];
+	__be32 ltesr;           /**< Transfer Error Status Register */
+#define LTESR_BM   0x80000000
+#define LTESR_FCT  0x40000000
+#define LTESR_PAR  0x20000000
+#define LTESR_WP   0x04000000
+#define LTESR_ATMW 0x00800000
+#define LTESR_ATMR 0x00400000
+#define LTESR_CS   0x00080000
+#define LTESR_CC   0x00000001
+#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+	__be32 ltedr;           /**< Transfer Error Disable Register */
+	__be32 lteir;           /**< Transfer Error Interrupt Register */
+	__be32 lteatr;          /**< Transfer Error Attributes Register */
+	__be32 ltear;           /**< Transfer Error Address Register */
+	u8 res6[0xC];
+	__be32 lbcr;            /**< Configuration Register */
+#define LBCR_LDIS  0x80000000
+#define LBCR_LDIS_SHIFT    31
+#define LBCR_BCTLC 0x00C00000
+#define LBCR_BCTLC_SHIFT   22
+#define LBCR_AHD   0x00200000
+#define LBCR_LPBSE 0x00020000
+#define LBCR_LPBSE_SHIFT   17
+#define LBCR_EPAR  0x00010000
+#define LBCR_EPAR_SHIFT    16
+#define LBCR_BMT   0x0000FF00
+#define LBCR_BMT_SHIFT      8
+#define LBCR_INIT  0x00040000
+	__be32 lcrr;            /**< Clock Ratio Register */
+#define LCRR_DBYP    0x80000000
+#define LCRR_DBYP_SHIFT      31
+#define LCRR_BUFCMDC 0x30000000
+#define LCRR_BUFCMDC_SHIFT   28
+#define LCRR_ECL     0x03000000
+#define LCRR_ECL_SHIFT       24
+#define LCRR_EADC    0x00030000
+#define LCRR_EADC_SHIFT      16
+#define LCRR_CLKDIV  0x0000000F
+#define LCRR_CLKDIV_SHIFT     0
+	u8 res7[0x8];
+	__be32 fmr;             /**< Flash Mode Register */
+#define FMR_CWTO     0x0000F000
+#define FMR_CWTO_SHIFT       12
+#define FMR_BOOT     0x00000800
+#define FMR_ECCM     0x00000100
+#define FMR_AL       0x00000030
+#define FMR_AL_SHIFT          4
+#define FMR_OP       0x00000003
+#define FMR_OP_SHIFT          0
+	__be32 fir;             /**< Flash Instruction Register */
+#define FIR_OP0      0xF0000000
+#define FIR_OP0_SHIFT        28
+#define FIR_OP1      0x0F000000
+#define FIR_OP1_SHIFT        24
+#define FIR_OP2      0x00F00000
+#define FIR_OP2_SHIFT        20
+#define FIR_OP3      0x000F0000
+#define FIR_OP3_SHIFT        16
+#define FIR_OP4      0x0000F000
+#define FIR_OP4_SHIFT        12
+#define FIR_OP5      0x00000F00
+#define FIR_OP5_SHIFT         8
+#define FIR_OP6      0x000000F0
+#define FIR_OP6_SHIFT         4
+#define FIR_OP7      0x0000000F
+#define FIR_OP7_SHIFT         0
+#define FIR_OP_NOP   0x0	/* No operation and end of sequence */
+#define FIR_OP_CA    0x1        /* Issue current column address */
+#define FIR_OP_PA    0x2        /* Issue current block+page address */
+#define FIR_OP_UA    0x3        /* Issue user defined address */
+#define FIR_OP_CM0   0x4        /* Issue command from FCR[CMD0] */
+#define FIR_OP_CM1   0x5        /* Issue command from FCR[CMD1] */
+#define FIR_OP_CM2   0x6        /* Issue command from FCR[CMD2] */
+#define FIR_OP_CM3   0x7        /* Issue command from FCR[CMD3] */
+#define FIR_OP_WB    0x8        /* Write FBCR bytes from FCM buffer */
+#define FIR_OP_WS    0x9        /* Write 1 or 2 bytes from MDR[AS] */
+#define FIR_OP_RB    0xA        /* Read FBCR bytes to FCM buffer */
+#define FIR_OP_RS    0xB        /* Read 1 or 2 bytes to MDR[AS] */
+#define FIR_OP_CW0   0xC        /* Wait then issue FCR[CMD0] */
+#define FIR_OP_CW1   0xD        /* Wait then issue FCR[CMD1] */
+#define FIR_OP_RBW   0xE        /* Wait then read FBCR bytes */
+#define FIR_OP_RSW   0xE        /* Wait then read 1 or 2 bytes */
+	__be32 fcr;             /**< Flash Command Register */
+#define FCR_CMD0     0xFF000000
+#define FCR_CMD0_SHIFT       24
+#define FCR_CMD1     0x00FF0000
+#define FCR_CMD1_SHIFT       16
+#define FCR_CMD2     0x0000FF00
+#define FCR_CMD2_SHIFT        8
+#define FCR_CMD3     0x000000FF
+#define FCR_CMD3_SHIFT        0
+	__be32 fbar;            /**< Flash Block Address Register */
+#define FBAR_BLK     0x00FFFFFF
+	__be32 fpar;            /**< Flash Page Address Register */
+#define FPAR_SP_PI   0x00007C00
+#define FPAR_SP_PI_SHIFT     10
+#define FPAR_SP_MS   0x00000200
+#define FPAR_SP_CI   0x000001FF
+#define FPAR_SP_CI_SHIFT      0
+#define FPAR_LP_PI   0x0003F000
+#define FPAR_LP_PI_SHIFT     12
+#define FPAR_LP_MS   0x00000800
+#define FPAR_LP_CI   0x000007FF
+#define FPAR_LP_CI_SHIFT      0
+	__be32 fbcr;            /**< Flash Byte Count Register */
+#define FBCR_BC      0x00000FFF
+	u8 res11[0x8];
+	u8 res8[0xF00];
+};
+
+struct fsl_elbc_ctrl;
+
+/* mtd information per set */
+
+struct fsl_elbc_mtd {
+	struct mtd_info mtd;
+	struct nand_chip chip;
+	struct fsl_elbc_ctrl *ctrl;
+
+	struct device *dev;
+	int bank;               /* Chip select bank number           */
+	u8 __iomem *vbase;      /* Chip select base virtual address  */
+	int page_size;          /* NAND page size (0=512, 1=2048)    */
+	unsigned int fmr;       /* FCM Flash Mode Register value     */
+};
+
+/* overview of the fsl elbc controller */
+
+struct fsl_elbc_ctrl {
+	struct nand_hw_control controller;
+	struct fsl_elbc_mtd *chips[MAX_BANKS];
+
+	/* device info */
+	struct device *dev;
+	struct elbc_regs __iomem *regs;
+	int irq;
+	wait_queue_head_t irq_wait;
+	unsigned int irq_status; /* status read from LTESR by irq handler */
+	u8 __iomem *addr;        /* Address of assigned FCM buffer        */
+	unsigned int page;       /* Last page written to / read from      */
+	unsigned int read_bytes; /* Number of bytes read during command   */
+	unsigned int column;     /* Saved column from SEQIN               */
+	unsigned int index;      /* Pointer to next byte to 'read'        */
+	unsigned int status;     /* status read from LTESR after last op  */
+	unsigned int mdr;        /* UPM/FCM Data Register value           */
+	unsigned int use_mdr;    /* Non zero if the MDR is to be set      */
+	unsigned int oob;        /* Non zero if operating on OOB data     */
+	char *oob_poi;           /* Place to write ECC after read back    */
+};
+
+/* These map to the positions used by the FCM hardware ECC generator */
+
+/* Small Page FLASH with FMR[ECCM] = 0 */
+static struct nand_ecclayout fsl_elbc_oob_sp_eccm0 = {
+	.eccbytes = 3,
+	.eccpos = {6, 7, 8},
+	.oobfree = { {0, 5}, {9, 7} },
+	.oobavail = 12,
+};
+
+/* Small Page FLASH with FMR[ECCM] = 1 */
+static struct nand_ecclayout fsl_elbc_oob_sp_eccm1 = {
+	.eccbytes = 3,
+	.eccpos = {8, 9, 10},
+	.oobfree = { {0, 5}, {6, 2}, {11, 5} },
+	.oobavail = 12,
+};
+
+/* Large Page FLASH with FMR[ECCM] = 0 */
+static struct nand_ecclayout fsl_elbc_oob_lp_eccm0 = {
+	.eccbytes = 12,
+	.eccpos = {6, 7, 8, 22, 23, 24, 38, 39, 40, 54, 55, 56},
+	.oobfree = { {1, 5}, {9, 13}, {25, 13}, {41, 13}, {57, 7} },
+	.oobavail = 48,
+};
+
+/* Large Page FLASH with FMR[ECCM] = 1 */
+static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = {
+	.eccbytes = 12,
+	.eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
+	.oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} },
+	.oobavail = 48,
+};
+
+/*=================================*/
+
+/*
+ * Set up the FCM hardware block and page address fields, and the fcm
+ * structure addr field to point to the correct FCM buffer in memory
+ */
+static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct elbc_regs __iomem *lbc = ctrl->regs;
+	int buf_num;
+
+	ctrl->page = page_addr;
+
+	out_be32(&lbc->fbar,
+	         page_addr >> (chip->phys_erase_shift - chip->page_shift));
+
+	if (priv->page_size) {
+		out_be32(&lbc->fpar,
+		         ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
+		         (oob ? FPAR_LP_MS : 0) | column);
+		buf_num = (page_addr & 1) << 2;
+	} else {
+		out_be32(&lbc->fpar,
+		         ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
+		         (oob ? FPAR_SP_MS : 0) | column);
+		buf_num = page_addr & 7;
+	}
+
+	ctrl->addr = priv->vbase + buf_num * 1024;
+	ctrl->index = column;
+
+	/* for OOB data point to the second half of the buffer */
+	if (oob)
+		ctrl->index += priv->page_size ? 2048 : 512;
+
+	FCM_DEBUG(2, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), index %x, pes %d ps %d\n", buf_num, ctrl->addr, priv->vbase, ctrl->index,
+	          chip->phys_erase_shift, chip->page_shift);
+}
+
+/*
+ * execute FCM command and wait for it to complete
+ */
+static int fsl_elbc_run_command(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct elbc_regs __iomem *lbc = ctrl->regs;
+
+	/* Setup the FMR[OP] to execute without write protection */
+	out_be32(&lbc->fmr, priv->fmr | 3);
+	if (ctrl->use_mdr)
+		out_be32(&lbc->mdr, ctrl->mdr);
+
+	FCM_DEBUG(5, "fsl_elbc_run_command: fmr= %08X fir= %08X fcr= %08X\n",
+		lbc->fmr, lbc->fir, lbc->fcr);
+	FCM_DEBUG(5, "fsl_elbc_run_command: fbar=%08X fpar=%08X fbcr=%08X bank=%d\n",
+		lbc->fbar, lbc->fpar, lbc->fbcr, priv->bank);
+
+	/* execute special operation */
+	out_be32(&lbc->lsor, priv->bank);
+
+	/* wait for FCM complete flag or timeout */
+	ctrl->irq_status = 0;
+	wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
+	                   FCM_TIMEOUT_MSECS * HZ/1000);
+	ctrl->status = ctrl->irq_status;
+
+	/* store mdr value in case it was needed */
+	if (ctrl->use_mdr)
+		ctrl->mdr = in_be32(&lbc->mdr);
+
+	ctrl->use_mdr = 0;
+
+	FCM_DEBUG(5, "fsl_elbc_run_command: stat=%08X mdr= %08X fmr= %08X\n",
+		ctrl->status, ctrl->mdr, lbc->fmr);
+
+	/* returns 0 on success otherwise non-zero) */
+	return ctrl->status == LTESR_CC ? 0 : -EIO;
+}
+
+static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
+{
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct elbc_regs __iomem *lbc = ctrl->regs;
+
+	if (priv->page_size) {
+		out_be32(&lbc->fir,
+		         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+		         (FIR_OP_CA  << FIR_OP1_SHIFT) |
+		         (FIR_OP_PA  << FIR_OP2_SHIFT) |
+		         (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+		         (FIR_OP_RBW << FIR_OP4_SHIFT));
+
+		out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
+		                    (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
+	} else {
+		out_be32(&lbc->fir,
+		         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+		         (FIR_OP_CA  << FIR_OP1_SHIFT) |
+		         (FIR_OP_PA  << FIR_OP2_SHIFT) |
+		         (FIR_OP_RBW << FIR_OP3_SHIFT));
+
+		if (oob)
+			out_be32(&lbc->fcr, NAND_CMD_READOOB << FCR_CMD0_SHIFT);
+		else
+			out_be32(&lbc->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
+	}
+}
+
+/* cmdfunc send commands to the FCM */
+static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
+                             int column, int page_addr)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct elbc_regs __iomem *lbc = ctrl->regs;
+
+	ctrl->use_mdr = 0;
+
+	/* clear the read buffer */
+	ctrl->read_bytes = 0;
+	if (command != NAND_CMD_PAGEPROG)
+		ctrl->index = 0;
+
+	switch (command) {
+	/* READ0 and READ1 read the entire buffer to use hardware ECC. */
+	case NAND_CMD_READ1:
+		column += 256;
+
+	/* fall-through */
+	case NAND_CMD_READ0:
+		FCM_DEBUG(2, "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
+			    " 0x%x, column: 0x%x.\n", page_addr, column);
+
+
+		out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
+
+		set_addr(mtd, 0, page_addr, 0);
+
+		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+		ctrl->index += column;
+
+		fsl_elbc_do_read(chip, 0);
+		fsl_elbc_run_command(mtd);
+		return;
+
+	/* READOOB reads only the OOB because no ECC is performed. */
+	case NAND_CMD_READOOB:
+		FCM_DEBUG(2, "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
+			    " 0x%x, column: 0x%x.\n", page_addr, column);
+
+		out_be32(&lbc->fbcr, mtd->oobsize - column);
+		set_addr(mtd, column, page_addr, 1);
+
+		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+
+		fsl_elbc_do_read(chip, 1);
+		fsl_elbc_run_command(mtd);
+		return;
+
+	/* READID must read all 5 possible bytes while CEB is active */
+	case NAND_CMD_READID:
+		FCM_DEBUG(2, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
+
+		out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
+		                    (FIR_OP_RBW << FIR_OP2_SHIFT));
+		out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
+		/* 5 bytes for manuf, device and exts */
+		out_be32(&lbc->fbcr, 5);
+		ctrl->read_bytes = 5;
+		ctrl->use_mdr = 1;
+		ctrl->mdr = 0;
+
+		set_addr(mtd, 0, 0, 0);
+		fsl_elbc_run_command(mtd);
+		return;
+
+	/* ERASE1 stores the block and page address */
+	case NAND_CMD_ERASE1:
+		FCM_DEBUG(2, "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, page_addr:"
+			    " 0x%x.\n", page_addr);
+		set_addr(mtd, 0, page_addr, 0);
+		return;
+
+	/* ERASE2 uses the block and page address from ERASE1 */
+	case NAND_CMD_ERASE2:
+		FCM_DEBUG(2, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
+
+		out_be32(&lbc->fir,
+		         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+		         (FIR_OP_PA  << FIR_OP1_SHIFT) |
+		         (FIR_OP_CM1 << FIR_OP2_SHIFT));
+
+		out_be32(&lbc->fcr,
+		         (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
+		         (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT));
+
+		out_be32(&lbc->fbcr, 0);
+		ctrl->read_bytes = 0;
+
+		fsl_elbc_run_command(mtd);
+		return;
+
+	/* SEQIN sets up the addr buffer and all registers except the length */
+	case NAND_CMD_SEQIN: {
+		__be32 fcr;
+		FCM_DEBUG(2, "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, page_addr:"
+			    " 0x%x, column: 0x%x.\n", page_addr, column);
+
+		ctrl->column = column;
+		ctrl->oob = 0;
+
+		fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
+		      (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
+
+		if (priv->page_size) {
+			out_be32(&lbc->fir,
+			         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+			         (FIR_OP_CA  << FIR_OP1_SHIFT) |
+			         (FIR_OP_PA  << FIR_OP2_SHIFT) |
+			         (FIR_OP_WB  << FIR_OP3_SHIFT) |
+			         (FIR_OP_CW1 << FIR_OP4_SHIFT));
+
+			fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
+		} else {
+			out_be32(&lbc->fir,
+			         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+			         (FIR_OP_CM2 << FIR_OP1_SHIFT) |
+			         (FIR_OP_CA  << FIR_OP2_SHIFT) |
+			         (FIR_OP_PA  << FIR_OP3_SHIFT) |
+			         (FIR_OP_WB  << FIR_OP4_SHIFT) |
+			         (FIR_OP_CW1 << FIR_OP5_SHIFT));
+
+			if (column >= mtd->writesize) {
+				/* OOB area --> READOOB */
+				column -= mtd->writesize;
+				fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
+				ctrl->oob = 1;
+			} else if (column < 256) {
+				/* First 256 bytes --> READ0 */
+				fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
+			} else {
+				/* Second 256 bytes --> READ1 */
+				fcr |= NAND_CMD_READ1 << FCR_CMD0_SHIFT;
+			}
+		}
+
+		out_be32(&lbc->fcr, fcr);
+		set_addr(mtd, column, page_addr, ctrl->oob);
+		return;
+	}
+
+	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
+	case NAND_CMD_PAGEPROG: {
+		int full_page;
+		FCM_DEBUG(2, "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG"
+			    " writing %d bytes.\n",ctrl->index);
+
+		/* if the write did not start at 0 or is not a full page
+		 * then set the exact length, otherwise use a full page
+		 * write so the HW generates the ECC.
+		 */
+		if (ctrl->oob || ctrl->column != 0 ||
+		    ctrl->index != mtd->writesize + mtd->oobsize) {
+			out_be32(&lbc->fbcr, ctrl->index);
+			full_page = 0;
+		} else {
+			out_be32(&lbc->fbcr, 0);
+			full_page = 1;
+		}
+
+		fsl_elbc_run_command(mtd);
+
+		/* Read back the page in order to fill in the ECC for the caller.
+		 * Is this really needed?
+		 */
+		if (full_page && ctrl->oob_poi) {
+			out_be32(&lbc->fbcr, 3);
+			set_addr(mtd, 6, page_addr, 1);
+
+			ctrl->read_bytes = mtd->writesize + 9;
+
+			fsl_elbc_do_read(chip, 1);
+			fsl_elbc_run_command(mtd);
+
+			memcpy_fromio(ctrl->oob_poi + 6, &ctrl->addr[ctrl->index], 3);
+			ctrl->index += 3;
+		}
+
+		ctrl->oob_poi = NULL;
+		return;
+	}
+
+	/* CMD_STATUS must read the status byte while CEB is active */
+	/* Note - it does not wait for the ready line */
+	case NAND_CMD_STATUS:
+		out_be32(&lbc->fir,
+		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
+		         (FIR_OP_RBW << FIR_OP1_SHIFT));
+		out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
+		out_be32(&lbc->fbcr, 1);
+		set_addr(mtd, 0, 0, 0);
+		ctrl->read_bytes = 1;
+
+		fsl_elbc_run_command(mtd);
+
+		// The chip always seems to report that it is write-protected,
+		// even when it is not.
+		setbits8(ctrl->addr, NAND_STATUS_WP);
+		return;
+
+	/* RESET without waiting for the ready line */
+	case NAND_CMD_RESET:
+		FCM_DEBUG(2, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
+		out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
+		out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
+		fsl_elbc_run_command(mtd);
+		return;
+
+	default:
+		printk("fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
+		       command);
+	}
+}
+
+static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
+{
+	/* The hardware does not seem to support multiple
+	 * chips per bank.
+	 */
+}
+
+/*
+ * Write buf to the FCM Controller Data Buffer
+ */
+static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	unsigned int bufsize = mtd->writesize + mtd->oobsize;
+
+	if (len < 0) {
+		dev_err(ctrl->dev, "write_buf of %d bytes", len);
+		ctrl->status = 0;
+		return;
+	}
+
+	if ((unsigned int)len > bufsize - ctrl->index) {
+		dev_err(ctrl->dev,
+		        "write_buf beyond end of buffer "
+		        "(%d requested, %u available)\n",
+		        len, bufsize - ctrl->index);
+		printk("index %x\n", ctrl->index);
+		BUG();
+
+		len = bufsize - ctrl->index;
+	}
+
+	memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
+	ctrl->index += len;
+}
+
+/*
+ * read a byte from either the FCM hardware buffer if it has any data left
+ * otherwise issue a command to read a single byte.
+ */
+static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+
+	/* If there are still bytes in the FCM, then use the next byte. */
+	if (ctrl->index < ctrl->read_bytes)
+		return in_8(&ctrl->addr[ctrl->index++]);
+
+	dev_err(ctrl->dev, "read_byte beyond end of buffer\n");
+	return ERR_BYTE;
+}
+
+/*
+ * Read from the FCM Controller Data Buffer
+ */
+static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	int avail;
+
+	if (len < 0)
+		return;
+
+	avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
+	memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
+	ctrl->index += avail;
+
+	if (len > avail)
+		dev_err(ctrl->dev,
+		        "read_buf beyond end of buffer "
+		        "(%d requested, %d available)\n",
+		        len, avail);
+}
+
+/*
+ * Verify buffer against the FCM Controller Data Buffer
+ */
+static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	int i;
+
+	if (len < 0) {
+		dev_err(ctrl->dev, "write_buf of %d bytes", len);
+		return -EINVAL;
+	}
+
+	if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
+		dev_err(ctrl->dev,
+		        "verify_buf beyond end of buffer "
+		        "(%d requested, %u available)\n",
+		        len, ctrl->read_bytes - ctrl->index);
+
+		ctrl->index = ctrl->read_bytes;
+		return -EINVAL;
+	}
+
+	for (i = 0; i < len; i++)
+		if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
+			break;
+
+	ctrl->index += len;
+	return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
+}
+
+/* This function is called after Program and Erase Operations to
+ * check for success or failure.
+ */
+static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
+{
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct elbc_regs __iomem *lbc = ctrl->regs;
+
+	if (ctrl->status != LTESR_CC)
+		return NAND_STATUS_FAIL;
+
+	/* Use READ_STATUS command, but wait for the device to be ready */
+	ctrl->use_mdr = 0;
+	out_be32(&lbc->fir,
+	         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+	         (FIR_OP_RBW << FIR_OP1_SHIFT));
+	out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
+	out_be32(&lbc->fbcr, 1);
+	set_addr(mtd, 0, 0, 0);
+	ctrl->read_bytes = 1;
+
+	fsl_elbc_run_command(mtd);
+
+	if (ctrl->status != LTESR_CC)
+		return NAND_STATUS_FAIL;
+
+	// The chip always seems to report that it is write-protected,
+	// even when it is not.
+	setbits8(ctrl->addr, NAND_STATUS_WP);
+	return fsl_elbc_read_byte(mtd);
+}
+
+static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct elbc_regs __iomem *lbc = ctrl->regs;
+	unsigned int al;
+
+	/* calculate FMR Address Length field */
+	al = 0;
+	if (chip->pagemask & 0xffff0000)
+		al++;
+	if (chip->pagemask & 0xff000000)
+		al++;
+
+	/* add to ECCM mode set in fsl_elbc_init */
+	priv->fmr |= (12 << FMR_CWTO_SHIFT) |  /* Timeout > 12 ms */
+	             (al << FMR_AL_SHIFT);
+
+	FCM_DEBUG(1, "fsl_elbc_init: nand->numchips = %10d\n", chip->numchips);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->chipsize = %10ld\n", chip->chipsize);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->pagemask = %10X\n", chip->pagemask);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->chip_delay = %8d\n", chip->chip_delay);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->badblockpos = %7d\n", chip->badblockpos);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->chip_shift = %8d\n", chip->chip_shift);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->page_shift = %8d\n", chip->page_shift);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->phys_erase_shift = %2d\n",
+						      chip->phys_erase_shift);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->ecclayout= %10p\n", chip->ecclayout);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->eccmode  = %10d\n", chip->ecc.mode );
+	FCM_DEBUG(1, "fsl_elbc_init: nand->eccsteps = %10d\n", chip->ecc.steps);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->eccbytes = %10d\n", chip->ecc.bytes);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->ecctotal = %10d\n", chip->ecc.total);
+	FCM_DEBUG(1, "fsl_elbc_init: nand->ecclayout= %10p\n", chip->ecc.layout);
+	FCM_DEBUG(1, "fsl_elbc_init: mtd->flags     =   %08X\n", mtd->flags);
+	FCM_DEBUG(1, "fsl_elbc_init: mtd->size      = %10d\n", mtd->size);
+	FCM_DEBUG(1, "fsl_elbc_init: mtd->erasesize = %10d\n", mtd->erasesize);
+	FCM_DEBUG(1, "fsl_elbc_init: mtd->writesize = %10d\n", mtd->writesize);
+	FCM_DEBUG(1, "fsl_elbc_init: mtd->oobsize   = %10d\n", mtd->oobsize);
+
+	/* adjust Option Register and ECC to match Flash page size */
+	if (mtd->writesize == 512) {
+		priv->page_size = 0;
+		clrbits32(&lbc->bank[priv->bank].or, ~OR_FCM_PGS);
+	} else if (mtd->writesize == 2048) {
+		priv->page_size = 1;
+		setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
+		/* adjust ecc setup if needed */
+		if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) ==
+		    BR_DECC_CHK_GEN) {
+			chip->ecc.size = 512;
+			chip->ecc.layout = (priv->fmr & FMR_ECCM) ?
+			                   &fsl_elbc_oob_lp_eccm1 :
+			                   &fsl_elbc_oob_lp_eccm0;
+			mtd->ecclayout = chip->ecc.layout;
+			mtd->oobavail = chip->ecc.layout->oobavail;
+		}
+	} else {
+		printk("fsl_elbc_init: page size %d is not supported\n",
+		       mtd->writesize);
+		return -1;
+	}
+
+	/* The default u-boot configuration on MPC8313ERDB causes errors;
+	 * more delay is needed.  This should be safe for other boards
+	 * as well.
+	 */
+	setbits32(&lbc->bank[priv->bank].or, 0x70);
+	return 0;
+}
+
+static int fsl_elbc_read_page(struct mtd_info *mtd,
+                              struct nand_chip *chip,
+                              uint8_t *buf)
+{
+	fsl_elbc_read_buf(mtd, buf, mtd->writesize);
+	fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL)
+		mtd->ecc_stats.failed++;
+
+	return 0;
+}
+
+/* ECC will be calculated automatically, and errors will be detected in
+ * waitfunc.
+ */
+static void fsl_elbc_write_page(struct mtd_info *mtd,
+                                struct nand_chip *chip,
+                                const uint8_t *buf)
+{
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+
+	fsl_elbc_write_buf(mtd, buf, mtd->writesize);
+	fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	ctrl->oob_poi = chip->oob_poi;
+}
+
+static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
+{
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct nand_chip *chip = &priv->chip;
+
+	dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
+
+	/* Fill in fsl_elbc_mtd structure */
+	priv->mtd.priv = chip;
+	priv->mtd.owner = THIS_MODULE;
+	priv->fmr = 0; /* rest filled in later */
+
+	/* fill in nand_chip structure */
+	/* set up function call table */
+	chip->read_byte = fsl_elbc_read_byte;
+	chip->write_buf = fsl_elbc_write_buf;
+	chip->read_buf = fsl_elbc_read_buf;
+	chip->verify_buf = fsl_elbc_verify_buf;
+	chip->select_chip = fsl_elbc_select_chip;
+	chip->cmdfunc = fsl_elbc_cmdfunc;
+	chip->waitfunc = fsl_elbc_wait;
+	chip->late_init = fsl_elbc_chip_init_tail;
+
+	/* set up nand options */
+	chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR;// | NAND_SKIP_BBTSCAN;
+
+	chip->controller = &ctrl->controller;
+	chip->priv = priv;
+
+	chip->ecc.read_page = fsl_elbc_read_page;
+	chip->ecc.write_page = fsl_elbc_write_page;
+
+	/* If CS Base Register selects full hardware ECC then use it */
+	if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) ==
+	    BR_DECC_CHK_GEN) {
+		chip->ecc.mode = NAND_ECC_HW;
+		/* put in small page settings and adjust later if needed */
+		chip->ecc.layout = (priv->fmr & FMR_ECCM) ?
+				&fsl_elbc_oob_sp_eccm1 : &fsl_elbc_oob_sp_eccm0;
+		chip->ecc.size = 512;
+		chip->ecc.bytes = 3;
+	} else {
+		/* otherwise fall back to default software ECC */
+		chip->ecc.mode = NAND_ECC_SOFT;
+	}
+
+	return 0;
+}
+
+static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
+{
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+
+	nand_release(&priv->mtd);
+
+	if (priv->vbase)
+		iounmap(priv->vbase);
+
+	ctrl->chips[priv->bank] = NULL;
+	kfree(priv);
+
+	return 0;
+}
+
+static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
+                               struct device_node *node)
+{
+	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_elbc_mtd *priv;
+	struct resource res;
+#ifdef CONFIG_MTD_PARTITIONS
+	static const char *part_probe_types[]
+		= { "cmdlinepart", "RedBoot", NULL };
+	struct mtd_partition *parts;
+#endif
+	int ret;
+	int bank;
+
+	/* get, allocate and map the memory resource */
+	ret = of_address_to_resource(node, 0, &res);
+	if (ret) {
+		dev_err(ctrl->dev, "failed to get resource\n");
+		return ret;
+	}
+
+	/* find which chip select it is connected to */
+	for (bank = 0; bank < MAX_BANKS; bank++)
+		if ((in_be32(&lbc->bank[bank].br) & BR_V) &&
+		    (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
+		    (in_be32(&lbc->bank[bank].br) &
+		     in_be32(&lbc->bank[bank].or) & BR_BA)
+		     == res.start)
+			break;
+
+	if (bank >= MAX_BANKS) {
+		dev_err(ctrl->dev, "address did not match any chip selects\n");
+		WARN_ON(1);
+		return -ENODEV;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	ctrl->chips[bank] = priv;
+	priv->bank = bank;
+	priv->ctrl = ctrl;
+	priv->dev = ctrl->dev;
+
+	priv->vbase = ioremap(res.start, res.end - res.start + 1);
+	if (!priv->vbase) {
+		dev_err(ctrl->dev, "failed to map chip region\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = fsl_elbc_chip_init(priv);
+	if (ret)
+		goto err;
+
+	ret = nand_scan(&priv->mtd, 1);
+	if (ret)
+		goto err;
+
+#ifdef CONFIG_MTD_PARTITIONS
+	/* First look for RedBoot table or partitions on the command
+	 * line, these take precedence over device tree information */
+	ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, 0);
+	if (ret < 0)
+		goto err;
+
+#ifdef CONFIG_MTD_OF_PARTS
+	if (ret == 0) {
+		ret = of_mtd_parse_partitions(priv->dev, &priv->mtd,
+		                              node, &parts);
+		if (ret < 0)
+			goto err;
+	}
+#endif
+
+	if (ret > 0)
+		add_mtd_partitions(&priv->mtd, parts, ret);
+	else
+#endif
+		add_mtd_device(&priv->mtd);
+
+	printk(KERN_INFO "eLBC NAND device at 0x%zx, bank %d\n",
+	       res.start, priv->bank);
+	return 0;
+
+err:
+	fsl_elbc_chip_remove(priv);
+	return ret;
+}
+
+static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
+{
+	struct elbc_regs __iomem *lbc = ctrl->regs;
+
+	/* clear event registers */
+	setbits32(&lbc->ltesr, LTESR_NAND_MASK);
+	out_be32(&lbc->lteatr, 0);
+
+	/* Enable interrupts for any detected events */
+	out_be32(&lbc->lteir, LTESR_NAND_MASK);
+
+	ctrl->read_bytes = 0;
+	ctrl->index = 0;
+	ctrl->addr = NULL;
+
+	return 0;
+}
+
+static int __devexit fsl_elbc_ctrl_remove(struct of_device *ofdev)
+{
+	struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
+	int i;
+
+	for (i = 0; i < MAX_BANKS; i++)
+		if (ctrl->chips[i])
+			fsl_elbc_chip_remove(ctrl->chips[i]);
+
+	if (ctrl->irq)
+		free_irq(ctrl->irq, ctrl);
+
+	if (ctrl->regs)
+		iounmap(ctrl->regs);
+
+	dev_set_drvdata(&ofdev->dev, NULL);
+	kfree(ctrl);
+	return 0;
+}
+
+/* interrupt handler code */
+
+static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
+{
+	struct fsl_elbc_ctrl *ctrl = data;
+	struct elbc_regs __iomem *lbc = ctrl->regs;
+	__be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
+
+	if (status) {
+		out_be32(&lbc->ltesr, status);
+		out_be32(&lbc->lteatr, 0);
+
+		ctrl->irq_status = status;
+		smp_wmb();
+		wake_up(&ctrl->irq_wait);
+
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+/* fsl_elbc_ctrl_probe
+ *
+ * called by device layer when it finds a device matching
+ * one our driver can handled. This code allocates all of
+ * the resources needed for the controller only.  The
+ * resources for the NAND banks themselves are allocated
+ * in the chip probe function.
+*/
+
+static int __devinit fsl_elbc_ctrl_probe(struct of_device *ofdev,
+                                         const struct of_device_id *match)
+{
+	struct device_node *child;
+	struct fsl_elbc_ctrl *ctrl;
+	int ret;
+
+	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+	if (!ctrl)
+		return -ENOMEM;
+
+	dev_set_drvdata(&ofdev->dev, ctrl);
+
+	spin_lock_init(&ctrl->controller.lock);
+	init_waitqueue_head(&ctrl->controller.wq);
+	init_waitqueue_head(&ctrl->irq_wait);
+
+	ctrl->regs = of_iomap(ofdev->node, 0);
+	if (!ctrl->regs) {
+		dev_err(&ofdev->dev, "failed to get memory region\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	ctrl->irq = of_irq_to_resource(ofdev->node, 0, NULL);
+	if (ctrl->irq == NO_IRQ) {
+		dev_err(&ofdev->dev, "failed to get irq resource\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	ctrl->dev = &ofdev->dev;
+
+	ret = fsl_elbc_ctrl_init(ctrl);
+	if (ret < 0)
+		goto err;
+
+	ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl);
+	if (ret != 0) {
+		dev_err(&ofdev->dev, "failed to install irq (%d)\n",
+		        ctrl->irq);
+		ret = ctrl->irq;
+		goto err;
+	}
+
+	child = NULL;
+	while ((child = of_get_next_child(ofdev->node, child)))
+		if (of_device_is_compatible(child, "fsl,elbc-fcm-nand"))
+			fsl_elbc_chip_probe(ctrl, child);
+
+	return 0;
+
+err:
+	fsl_elbc_ctrl_remove(ofdev);
+	return ret;
+}
+
+static struct of_device_id fsl_elbc_match[] = {
+	{
+		.compatible = "fsl,elbc",
+	},
+	{}
+};
+
+static struct of_platform_driver fsl_elbc_ctrl_driver = {
+	.name	= "fsl-elbc",
+	.match_table = fsl_elbc_match,
+	.probe = fsl_elbc_ctrl_probe,
+	.remove = __devexit_p(fsl_elbc_ctrl_remove),
+};
+
+static int __init fsl_elbc_init(void)
+{
+	return of_register_platform_driver(&fsl_elbc_ctrl_driver);
+}
+
+static void __exit fsl_elbc_exit(void)
+{
+	of_unregister_platform_driver(&fsl_elbc_ctrl_driver);
+}
+
+module_init(fsl_elbc_init);
+module_exit(fsl_elbc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale");
+MODULE_DESCRIPTION("Freescale Enhanced Local Bus Controller MTD NAND driver");
-- 
1.5.3.7

^ permalink raw reply related

* [PATCH v2 2/4] mpc8313erdb: Add NAND to device tree, and call of_platform_bus_probe().
From: Scott Wood @ 2007-12-14 18:58 UTC (permalink / raw)
  To: galak; +Cc: linuxppc-dev

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
As requested, compatible is used rather than name for probing.
The simple-bus name comes from ePAPR drafts.

 arch/powerpc/boot/dts/mpc8313erdb.dts     |   38 +++++++++++++++++++++++++++++
 arch/powerpc/platforms/83xx/mpc8313_rdb.c |   16 ++++++++++++
 2 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts
index c5b6665..66b53ec 100644
--- a/arch/powerpc/boot/dts/mpc8313erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8313erdb.dts
@@ -45,10 +45,48 @@
 		reg = <00000000 08000000>;	// 128MB at 0
 	};
 
+	localbus {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8313-elbc", "fsl,elbc", "simple-bus";
+		reg = <e0005000 1000>;
+		interrupts = <d#77 8>;
+		interrupt-parent = <&ipic>;
+
+		// CS0 and CS1 are swapped when
+		// booting from nand, but the
+		// addresses are the same.
+		ranges = <0 0 fe000000 00800000
+		          1 0 e2800000 00008000
+		          2 0 f0000000 00020000
+		          3 0 fa000000 00008000>;
+
+		nand@1,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8313-fcm-nand", "fsl,elbc-fcm-nand";
+			reg = <1 0 2000>;
+
+			u-boot@0 {
+				reg = <0 100000>;
+				read-only;
+			};
+
+			kernel@100000 {
+				reg = <100000 300000>;
+			};
+
+			fs@400000 {
+				reg = <400000 1c00000>;
+			};
+		};
+	};
+
 	soc8313@e0000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		device_type = "soc";
+		compatible = "simple-bus";
 		ranges = <0 e0000000 00100000>;
 		reg = <e0000000 00000200>;
 		bus-frequency = <0>;
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
index 6fb8299..4e57448 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -14,6 +14,7 @@
  */
 
 #include <linux/pci.h>
+#include <linux/of_platform.h>
 
 #include <asm/time.h>
 #include <asm/ipic.h>
@@ -75,6 +76,21 @@ static int __init mpc8313_rdb_probe(void)
 	return of_flat_dt_is_compatible(root, "MPC8313ERDB");
 }
 
+static struct of_device_id __initdata of_bus_ids[] = {
+	{ .compatible = "simple-bus" },
+	{},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+	if (!machine_is(mpc8313_rdb))
+		return 0;
+
+	of_platform_bus_probe(NULL, of_bus_ids, NULL);
+	return 0;
+}
+device_initcall(declare_of_platform_devices);
+
 define_machine(mpc8313_rdb) {
 	.name			= "MPC8313 RDB",
 	.probe			= mpc8313_rdb_probe,
-- 
1.5.3.7

^ permalink raw reply related

* Re: [PATCH v2 4/4] Freescale enhanced Local Bus Controller FCM NAND support.
From: Anton Vorontsov @ 2007-12-14 19:24 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, dwmw2, linux-mtd
In-Reply-To: <20071214185624.GA10584@loki.buserror.net>

On Fri, Dec 14, 2007 at 12:56:24PM -0600, Scott Wood wrote:
> Signed-off-by: Nick Spence <nick.spence@freescale.com>
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> Respun according to feedback; also, fixed a couple direct accesses
> of iomem.
> 
>  drivers/mtd/nand/Kconfig         |    9 +
>  drivers/mtd/nand/Makefile        |    1 +
>  drivers/mtd/nand/fsl_elbc_nand.c | 1217 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 1227 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mtd/nand/fsl_elbc_nand.c
> 
[...]
> +#if 0
> +#define ELBC_NAND_DEBUG_LVL 6
> +#endif
> +
> +#ifdef ELBC_NAND_DEBUG_LVL
> +static int fcm_debug_level = ELBC_NAND_DEBUG_LVL;
> +#define FCM_DEBUG(n, args...)		\
> +	do {					\
> +		if (n <= fcm_debug_level)	\
> +			pr_dbg(args);	\
> +	} while(0)
> +#else
> +#define FCM_DEBUG(n, dev, args...) do { } while(0)
> +#endif

Only 1, 2 and 5 debug levels are used. Maybe better use dev_dbg
and dev_vdbg instead?

Btw, checkpatch result:
total: 69 errors, 14 warnings, 1236 lines checked

This isn't very friendly to the people going to look into.

> +#define MAX_BANKS 8
> +#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
> +#define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
> +
> +struct elbc_bank {
> +	__be32 br;             /**< Base Register  */
> +#define BR_BA           0xFFFF8000
> +#define BR_BA_SHIFT             15
> +#define BR_PS           0x00001800
> +#define BR_PS_SHIFT             11
> +#define BR_PS_8         0x00000800  /* Port Size 8 bit */
> +#define BR_PS_16        0x00001000  /* Port Size 16 bit */
> +#define BR_PS_32        0x00001800  /* Port Size 32 bit */
> +#define BR_DECC         0x00000600
> +#define BR_DECC_SHIFT            9
> +#define BR_DECC_OFF     0x00000000  /* HW ECC checking and generation off */
> +#define BR_DECC_CHK     0x00000200  /* HW ECC checking on, generation off */
> +#define BR_DECC_CHK_GEN 0x00000400  /* HW ECC checking and generation on */
> +#define BR_WP           0x00000100
> +#define BR_WP_SHIFT              8
> +#define BR_MSEL         0x000000E0
> +#define BR_MSEL_SHIFT            5
> +#define BR_MS_GPCM      0x00000000  /* GPCM */
> +#define BR_MS_FCM       0x00000020  /* FCM */
> +#define BR_MS_SDRAM     0x00000060  /* SDRAM */
> +#define BR_MS_UPMA      0x00000080  /* UPMA */
> +#define BR_MS_UPMB      0x000000A0  /* UPMB */
> +#define BR_MS_UPMC      0x000000C0  /* UPMC */
> +#define BR_V            0x00000001
> +#define BR_V_SHIFT               0
> +#define BR_RES          ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
> +
> +	__be32 or;             /**< Base Register  */
> +#define OR0 0x5004
> +#define OR1 0x500C
> +#define OR2 0x5014
> +#define OR3 0x501C
> +#define OR4 0x5024
> +#define OR5 0x502C
> +#define OR6 0x5034
> +#define OR7 0x503C
> +
> +#define OR_FCM_AM               0xFFFF8000
> +#define OR_FCM_AM_SHIFT                 15
> +#define OR_FCM_BCTLD            0x00001000
> +#define OR_FCM_BCTLD_SHIFT              12
> +#define OR_FCM_PGS              0x00000400
> +#define OR_FCM_PGS_SHIFT                10
> +#define OR_FCM_CSCT             0x00000200
> +#define OR_FCM_CSCT_SHIFT                9
> +#define OR_FCM_CST              0x00000100
> +#define OR_FCM_CST_SHIFT                 8
> +#define OR_FCM_CHT              0x00000080
> +#define OR_FCM_CHT_SHIFT                 7
> +#define OR_FCM_SCY              0x00000070
> +#define OR_FCM_SCY_SHIFT                 4
> +#define OR_FCM_SCY_1            0x00000010
> +#define OR_FCM_SCY_2            0x00000020
> +#define OR_FCM_SCY_3            0x00000030
> +#define OR_FCM_SCY_4            0x00000040
> +#define OR_FCM_SCY_5            0x00000050
> +#define OR_FCM_SCY_6            0x00000060
> +#define OR_FCM_SCY_7            0x00000070
> +#define OR_FCM_RST              0x00000008
> +#define OR_FCM_RST_SHIFT                 3
> +#define OR_FCM_TRLX             0x00000004
> +#define OR_FCM_TRLX_SHIFT                2
> +#define OR_FCM_EHTR             0x00000002
> +#define OR_FCM_EHTR_SHIFT                1
> +};
> +
> +struct elbc_regs {
> +	struct elbc_bank bank[8];
> +	u8 res0[0x28];
> +	__be32 mar;             /**< UPM Address Register */
> +	u8 res1[0x4];
> +	__be32 mamr;            /**< UPMA Mode Register */
> +	__be32 mbmr;            /**< UPMB Mode Register */
> +	__be32 mcmr;            /**< UPMC Mode Register */
> +	u8 res2[0x8];
> +	__be32 mrtpr;           /**< Memory Refresh Timer Prescaler Register */
> +	__be32 mdr;             /**< UPM Data Register */
> +	u8 res3[0x4];
> +	__be32 lsor;            /**< Special Operation Initiation Register */
> +	__be32 lsdmr;           /**< SDRAM Mode Register */
> +	u8 res4[0x8];
> +	__be32 lurt;            /**< UPM Refresh Timer */
> +	__be32 lsrt;            /**< SDRAM Refresh Timer */
> +	u8 res5[0x8];
> +	__be32 ltesr;           /**< Transfer Error Status Register */
> +#define LTESR_BM   0x80000000
> +#define LTESR_FCT  0x40000000
> +#define LTESR_PAR  0x20000000
> +#define LTESR_WP   0x04000000
> +#define LTESR_ATMW 0x00800000
> +#define LTESR_ATMR 0x00400000
> +#define LTESR_CS   0x00080000
> +#define LTESR_CC   0x00000001
> +#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
> +	__be32 ltedr;           /**< Transfer Error Disable Register */
> +	__be32 lteir;           /**< Transfer Error Interrupt Register */
> +	__be32 lteatr;          /**< Transfer Error Attributes Register */
> +	__be32 ltear;           /**< Transfer Error Address Register */
> +	u8 res6[0xC];
> +	__be32 lbcr;            /**< Configuration Register */
> +#define LBCR_LDIS  0x80000000
> +#define LBCR_LDIS_SHIFT    31
> +#define LBCR_BCTLC 0x00C00000
> +#define LBCR_BCTLC_SHIFT   22
> +#define LBCR_AHD   0x00200000
> +#define LBCR_LPBSE 0x00020000
> +#define LBCR_LPBSE_SHIFT   17
> +#define LBCR_EPAR  0x00010000
> +#define LBCR_EPAR_SHIFT    16
> +#define LBCR_BMT   0x0000FF00
> +#define LBCR_BMT_SHIFT      8
> +#define LBCR_INIT  0x00040000
> +	__be32 lcrr;            /**< Clock Ratio Register */
> +#define LCRR_DBYP    0x80000000
> +#define LCRR_DBYP_SHIFT      31
> +#define LCRR_BUFCMDC 0x30000000
> +#define LCRR_BUFCMDC_SHIFT   28
> +#define LCRR_ECL     0x03000000
> +#define LCRR_ECL_SHIFT       24
> +#define LCRR_EADC    0x00030000
> +#define LCRR_EADC_SHIFT      16
> +#define LCRR_CLKDIV  0x0000000F
> +#define LCRR_CLKDIV_SHIFT     0
> +	u8 res7[0x8];
> +	__be32 fmr;             /**< Flash Mode Register */
> +#define FMR_CWTO     0x0000F000
> +#define FMR_CWTO_SHIFT       12
> +#define FMR_BOOT     0x00000800
> +#define FMR_ECCM     0x00000100
> +#define FMR_AL       0x00000030
> +#define FMR_AL_SHIFT          4
> +#define FMR_OP       0x00000003
> +#define FMR_OP_SHIFT          0
> +	__be32 fir;             /**< Flash Instruction Register */
> +#define FIR_OP0      0xF0000000
> +#define FIR_OP0_SHIFT        28
> +#define FIR_OP1      0x0F000000
> +#define FIR_OP1_SHIFT        24
> +#define FIR_OP2      0x00F00000
> +#define FIR_OP2_SHIFT        20
> +#define FIR_OP3      0x000F0000
> +#define FIR_OP3_SHIFT        16
> +#define FIR_OP4      0x0000F000
> +#define FIR_OP4_SHIFT        12
> +#define FIR_OP5      0x00000F00
> +#define FIR_OP5_SHIFT         8
> +#define FIR_OP6      0x000000F0
> +#define FIR_OP6_SHIFT         4
> +#define FIR_OP7      0x0000000F
> +#define FIR_OP7_SHIFT         0
> +#define FIR_OP_NOP   0x0	/* No operation and end of sequence */
> +#define FIR_OP_CA    0x1        /* Issue current column address */
> +#define FIR_OP_PA    0x2        /* Issue current block+page address */
> +#define FIR_OP_UA    0x3        /* Issue user defined address */
> +#define FIR_OP_CM0   0x4        /* Issue command from FCR[CMD0] */
> +#define FIR_OP_CM1   0x5        /* Issue command from FCR[CMD1] */
> +#define FIR_OP_CM2   0x6        /* Issue command from FCR[CMD2] */
> +#define FIR_OP_CM3   0x7        /* Issue command from FCR[CMD3] */
> +#define FIR_OP_WB    0x8        /* Write FBCR bytes from FCM buffer */
> +#define FIR_OP_WS    0x9        /* Write 1 or 2 bytes from MDR[AS] */
> +#define FIR_OP_RB    0xA        /* Read FBCR bytes to FCM buffer */
> +#define FIR_OP_RS    0xB        /* Read 1 or 2 bytes to MDR[AS] */
> +#define FIR_OP_CW0   0xC        /* Wait then issue FCR[CMD0] */
> +#define FIR_OP_CW1   0xD        /* Wait then issue FCR[CMD1] */
> +#define FIR_OP_RBW   0xE        /* Wait then read FBCR bytes */
> +#define FIR_OP_RSW   0xE        /* Wait then read 1 or 2 bytes */
> +	__be32 fcr;             /**< Flash Command Register */
> +#define FCR_CMD0     0xFF000000
> +#define FCR_CMD0_SHIFT       24
> +#define FCR_CMD1     0x00FF0000
> +#define FCR_CMD1_SHIFT       16
> +#define FCR_CMD2     0x0000FF00
> +#define FCR_CMD2_SHIFT        8
> +#define FCR_CMD3     0x000000FF
> +#define FCR_CMD3_SHIFT        0
> +	__be32 fbar;            /**< Flash Block Address Register */
> +#define FBAR_BLK     0x00FFFFFF
> +	__be32 fpar;            /**< Flash Page Address Register */
> +#define FPAR_SP_PI   0x00007C00
> +#define FPAR_SP_PI_SHIFT     10
> +#define FPAR_SP_MS   0x00000200
> +#define FPAR_SP_CI   0x000001FF
> +#define FPAR_SP_CI_SHIFT      0
> +#define FPAR_LP_PI   0x0003F000
> +#define FPAR_LP_PI_SHIFT     12
> +#define FPAR_LP_MS   0x00000800
> +#define FPAR_LP_CI   0x000007FF
> +#define FPAR_LP_CI_SHIFT      0
> +	__be32 fbcr;            /**< Flash Byte Count Register */
> +#define FBCR_BC      0x00000FFF
> +	u8 res11[0x8];
> +	u8 res8[0xF00];
> +};
> +

Maybe this desires its own header?


Thanks!

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.net/bd2

^ permalink raw reply

* Re: [PATCH v2 4/4] Freescale enhanced Local Bus Controller FCM NAND support.
From: Scott Wood @ 2007-12-14 19:33 UTC (permalink / raw)
  To: avorontsov; +Cc: linuxppc-dev, dwmw2, linux-mtd
In-Reply-To: <20071214192446.GA3355@localhost.localdomain>

Anton Vorontsov wrote:
> On Fri, Dec 14, 2007 at 12:56:24PM -0600, Scott Wood wrote:
>> +#if 0
>> +#define ELBC_NAND_DEBUG_LVL 6
>> +#endif
>> +
>> +#ifdef ELBC_NAND_DEBUG_LVL
>> +static int fcm_debug_level = ELBC_NAND_DEBUG_LVL;
>> +#define FCM_DEBUG(n, args...)		\
>> +	do {					\
>> +		if (n <= fcm_debug_level)	\
>> +			pr_dbg(args);	\
>> +	} while(0)
>> +#else
>> +#define FCM_DEBUG(n, dev, args...) do { } while(0)
>> +#endif
> 
> Only 1, 2 and 5 debug levels are used. Maybe better use dev_dbg
> and dev_vdbg instead?

Yeah, probably...

> Btw, checkpatch result:
> total: 69 errors, 14 warnings, 1236 lines checked

Most of those are errors in checkpatch, wherein it fails to understand 
the difference between aligning with spaces (good) and indenting with 
spaces (bad).  Checkpatch spits out so many of those that other things 
get lost in the noise, so I don't usually bother to run it.

I also do not understand the allergy to C99 comments in the Linux 
community, though I'll change the few that slipped in by accident.

I'll fix the few legitimate ones.

> This isn't very friendly to the people going to look into.

You should have seen what it looked like before I touched it. :-P

> Maybe this desires its own header?

It can be factored out if anything else ever uses it.

-Scott

^ permalink raw reply

* Re: [PATCH v2 4/4] Freescale enhanced Local Bus Controller FCM NAND support.
From: Anton Vorontsov @ 2007-12-14 19:59 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, dwmw2, linux-mtd
In-Reply-To: <4762DA95.90000@freescale.com>

On Fri, Dec 14, 2007 at 01:33:41PM -0600, Scott Wood wrote:
> Anton Vorontsov wrote:
> >On Fri, Dec 14, 2007 at 12:56:24PM -0600, Scott Wood wrote:
> >>+#if 0
> >>+#define ELBC_NAND_DEBUG_LVL 6
> >>+#endif
> >>+
> >>+#ifdef ELBC_NAND_DEBUG_LVL
> >>+static int fcm_debug_level = ELBC_NAND_DEBUG_LVL;
> >>+#define FCM_DEBUG(n, args...)		\
> >>+	do {					\
> >>+		if (n <= fcm_debug_level)	\
> >>+			pr_dbg(args);	\
> >>+	} while(0)
> >>+#else
> >>+#define FCM_DEBUG(n, dev, args...) do { } while(0)
> >>+#endif
> >
> >Only 1, 2 and 5 debug levels are used. Maybe better use dev_dbg
> >and dev_vdbg instead?
> 
> Yeah, probably...
> 
> >Btw, checkpatch result:
> >total: 69 errors, 14 warnings, 1236 lines checked
> 
> Most of those are errors in checkpatch, wherein it fails to understand 
> the difference between aligning with spaces (good) and indenting with 
> spaces (bad).  Checkpatch spits out so many of those that other things 
> get lost in the noise, so I don't usually bother to run it.
> 
> I also do not understand the allergy to C99 comments in the Linux 
> community, though I'll change the few that slipped in by accident.
> 
> I'll fix the few legitimate ones.
> 
> >This isn't very friendly to the people going to look into.
> 
> You should have seen what it looked like before I touched it. :-P

I have seen that. ;-) Its previous name was fsl_fcm, and I shuddered
from it, honestly. I must admit that you've done great work on this!

> >Maybe this desires its own header?
> 
> It can be factored out if anything else ever uses it.

It's just confusing to parse lbc-specific and nand-specific code
placed in the same file.


Thanks,

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.net/bd2

^ permalink raw reply

* Re: [PATCH 8/8] gianfar: Magic Packet and suspend/resume support.
From: Jeff Garzik @ 2007-12-14 20:24 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, paulus, netdev
In-Reply-To: <20071212173607.GG5596@loki.buserror.net>

Scott Wood wrote:
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> Jeff, can you ack this to go through Paul's tree
> (assuming nothing wrong with it)?
> 
>  drivers/net/gianfar.c         |  137 ++++++++++++++++++++++++++++++++++++++++-
>  drivers/net/gianfar.h         |   13 +++-
>  drivers/net/gianfar_ethtool.c |   41 ++++++++++++-
>  3 files changed, 185 insertions(+), 6 deletions(-)

ACK

^ permalink raw reply

* Re: [PATCH v2 4/4] Freescale enhanced Local Bus Controller FCM NAND support.
From: Arnd Bergmann @ 2007-12-14 21:40 UTC (permalink / raw)
  To: linuxppc-dev, avorontsov; +Cc: linux-mtd, dwmw2
In-Reply-To: <20071214195917.GA18616@localhost.localdomain>

On Friday 14 December 2007, Anton Vorontsov wrote:
> > >Maybe this desires its own header?
> > 
> > It can be factored out if anything else ever uses it.
> 
> It's just confusing to parse lbc-specific and nand-specific code
> placed in the same file.

In that case, you could argue for splitting the implementation into
two C files. I don't see any reason to move stuff into a header
when it's not an interface between two parts of the code, but
only describes a hardware interface used by a single driver.

	Arnd <><

^ permalink raw reply


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