LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: Problem with full speed devices on PowerPC MPC5121 host port
From: Matthias Fuchs @ 2012-01-18 13:42 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: linuxppc-dev, linux-usb
In-Reply-To: <20120118120811.04f7c601@wker>

Hi Anatolij,

On 18.01.2012 12:08, Anatolij Gustschin wrote:
> Hi Matthias,
> 
> On Tue, 17 Jan 2012 15:12:50 +0100
> Matthias Fuchs <matthias.fuchs@esd.eu> wrote:
> 
>> On 06.01.2012 19:03, Alan Stern wrote:
>>> On Fri, 6 Jan 2012, Matthias Fuchs wrote:
>>>
>>>> For my eyes it does not really look like a general USB issue.
>>>> It looks like a problem with the Freescale EHCI implementation that is
>>>> influenced by high interrupt or internal bus load caused by the flood ping.
>>>
>>> Indeed, it might be a problem with the built-in Transaction Translator.  
>>> That would explain why it affect full-speed devices.
>>>
>>> However, I would expect the resetting the controller hardware (which 
>>> happens when you reload the ehci-fsl driver) would fix any such issues.  
>>> It's hard to imagine how a problem could survive a reset like that.
>>
>> I did the tests again. When the error occured I reloaded the ehci-hcd driver and reconnected the device. It ends up with some kernel messages 
>> that come up time after time:
>>
>> usb 1-1: new full-speed USB device number 2 using fsl-ehci
>> usb 1-1: device descriptor read/64, error -110
>> usb 1-1: device descriptor read/64, error -110
>> usb 1-1: new full-speed USB device number 3 using fsl-ehci
>> usb 1-1: device descriptor read/64, error -110
>> usb 1-1: device descriptor read/64, error -110
>> usb 1-1: new full-speed USB device number 4 using fsl-ehci
>> usb 1-1: device not accepting address 4, error -110
>> usb 1-1: new full-speed USB device number 5 using fsl-ehci
>> usb 1-1: device not accepting address 5, error -110
>> hub 1-0:1.0: unable to enumerate USB device on port 1
>>
>> A recommondation from freescale was to check the TXFILLTUNING register settings ("Initialization of this registers can produce problem if full-speed device is used").
>>
>> So I tried various values in the TXFILLTUNING register (I added this
>> code to ehci_reset()). Finally I disabled USB streaming mode in the USBMODE register (set bit USBMODE_SDIS - btw., it should be defined as "1 << 4" in ehci_def.h at least for the MPC5121).
>>
>> All this does not fix the problem or even have an impact.
> 
> Can you try the attached patch? Does it have an impact?

Yes, in deed, it solved my problem :-) Finally I noticed that
the problem is listed in the CPU's errata document.

You could update the comment and commit message to "... when there is
heavy simultaneus PATA write or network activity".

I vote for getting this mainline.

Tested-by: Matthias Fuchs <matthias.fuchs@esd.ue>

Matthias

^ permalink raw reply

* Re: [PATCH] powerpc/85xx:Add dr_mode property in USB nodes
From: Kumar Gala @ 2012-01-18 14:26 UTC (permalink / raw)
  To: Ramneek Mehresh; +Cc: devicetree-discuss, linuxppc-dev
In-Reply-To: <1326869326-4271-1-git-send-email-ramneek.mehresh@freescale.com>


On Jan 18, 2012, at 12:48 AM, Ramneek Mehresh wrote:

> Add usb2 controller node for P1020RDB, P2020RDB, P2020DS, P1021MDS
> 
> Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
> ---
> Applies on git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git
> (branch next)
> 
> arch/powerpc/boot/dts/p1020rdb.dtsi |    2 ++
> arch/powerpc/boot/dts/p1021mds.dts  |    3 ++-
> arch/powerpc/boot/dts/p2020ds.dtsi  |    3 ++-
> arch/powerpc/boot/dts/p2020rdb.dts  |    3 ++-
> 4 files changed, 8 insertions(+), 3 deletions(-)

applied to merge

- k

^ permalink raw reply

* Re: [PATCH] powerpc/85xx:Enable USB2 controller node for P1020RDB
From: Kumar Gala @ 2012-01-18 14:26 UTC (permalink / raw)
  To: Ramneek Mehresh; +Cc: devicetree-discuss, linuxppc-dev
In-Reply-To: <1326865839-3612-1-git-send-email-ramneek.mehresh@freescale.com>


On Jan 17, 2012, at 11:50 PM, Ramneek Mehresh wrote:

> Enable USB2 controller node for P1020RDB. USB2 controller is used only
> when board boots from SPI or SD as it is muxed with eLBC
> 
> Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
> ---
> Applies on git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git
> (branch next)
> 
> arch/powerpc/boot/dts/p1020rdb.dtsi |   11 ++++-------
> 1 files changed, 4 insertions(+), 7 deletions(-)

applied to merge

- k

^ permalink raw reply

* Re: [git pull] Please pull powerpc.git merge branch (updated)
From: Kumar Gala @ 2012-01-18 14:25 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <alpine.LFD.2.00.1201171625100.8416@right.am.freescale.net>

Ben,

Dropped the P1020RDB device tree patch as it was for the wrong board
revision and pulled in some additional usb device tree fixes.

- k


The following changes since commit c2bc3a316a7281f67e36b34dac2802cbe36a9128:

  Merge branch 'x86/rdrand' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip (2012-01-16 18:23:09 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git merge

Jerry Huang (1):
      powerpc/85xx: Fix cmd12 bug and add the chip compatible for eSDHC

Julia Lawall (1):
      arch/powerpc/sysdev/fsl_pci.c: add missing iounmap

Michael Neuling (1):
      powerpc: fix compile error with 85xx/p1022_ds.c

Ramneek Mehresh (2):
      powerpc/85xx: Enable USB2 controller node for P1020RDB
      powerpc/85xx: Add dr_mode property in USB nodes

 arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi |    4 ++++
 arch/powerpc/boot/dts/fsl/p1010si-post.dtsi   |    3 ++-
 arch/powerpc/boot/dts/fsl/p1020si-post.dtsi   |    4 ++++
 arch/powerpc/boot/dts/fsl/p1022si-post.dtsi   |    3 ++-
 arch/powerpc/boot/dts/fsl/p2020si-post.dtsi   |    4 ++++
 arch/powerpc/boot/dts/p1020rdb.dtsi           |   13 ++++++-------
 arch/powerpc/boot/dts/p1021mds.dts            |    3 ++-
 arch/powerpc/boot/dts/p2020ds.dtsi            |    3 ++-
 arch/powerpc/boot/dts/p2020rdb.dts            |    3 ++-
 arch/powerpc/platforms/85xx/p1022_ds.c        |    1 +
 arch/powerpc/sysdev/fsl_pci.c                 |    5 +++--
 11 files changed, 32 insertions(+), 14 deletions(-)

^ permalink raw reply

* [PATCH] powerpc/booke64: Configurable lazy interrupt disabling
From: Laurentiu Tudor @ 2012-01-18 14:35 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Laurentiu Tudor

This patch adds a menuconfig option that allows controlling
the lazy interrupt disabling feature implemented by this
commit:

commit d04c56f73c30a5e593202ecfcf25ed43d42363a2
Author: Paul Mackerras
Date:   Wed Oct 4 16:47:49 2006 +1000

    [POWERPC] Lazy interrupt disabling for 64-bit machines

The code in 'powerpc/include/asm/hw_irq.h' was rearranged and
cleaned-up a bit in order to reduce the number of needed #ifdef's.

Signed-off-by: Laurentiu Tudor <Laurentiu.Tudor@freescale.com>
---
Patch is against
git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next

 arch/powerpc/Kconfig                 |   16 ++++++
 arch/powerpc/include/asm/hw_irq.h    |   86 ++++++++++++++--------------------
 arch/powerpc/include/asm/irqflags.h  |   22 +++++++++
 arch/powerpc/include/asm/paca.h      |    4 ++
 arch/powerpc/kernel/asm-offsets.c    |    3 +
 arch/powerpc/kernel/entry_64.S       |    4 ++
 arch/powerpc/kernel/exceptions-64e.S |   36 +++++++++++---
 arch/powerpc/kernel/head_64.S        |   10 ++++
 arch/powerpc/kernel/idle_book3e.S    |    7 +++
 arch/powerpc/kernel/irq.c            |    5 ++
 arch/powerpc/kernel/setup_64.c       |    2 +
 11 files changed, 138 insertions(+), 57 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ce5e045..2792278 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -609,6 +609,22 @@ config SECCOMP
 
 	  If unsure, say Y. Only embedded should say N here.
 
+config PPC_LAZY_EE
+	bool
+	prompt "Lazy interrupt disabling" if PPC_BOOK3E_64
+	default y if PPC_BOOK3S_64
+	help
+	  Local interrupt disabling functions don't disable
+	  interrupts right away and instead just clear an
+	  internal 'interrupts are enabled' flag. If an
+	  interrupt is triggered during this time, the
+	  interrupt handling code checks the flag, and if
+	  interrupts are supposed to be off, disables them
+	  for real and returns, skipping interrupt handling.
+	  When interrupts are enabled back, the interrupt
+	  fires again and this time gets handled.
+
+	  If unsure, say N.
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index bb712c9..6f32593 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -13,7 +13,20 @@
 
 extern void timer_interrupt(struct pt_regs *);
 
+#ifdef CONFIG_BOOKE
+#define __hard_irq_enable()	asm volatile("wrteei 1" : : : "memory");
+#define __hard_irq_disable()	asm volatile("wrteei 0" : : : "memory");
+#else
 #ifdef CONFIG_PPC64
+#define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
+#define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
+#else
+#define __hard_irq_enable()	mtmsr(mfmsr() | MSR_EE)
+#define __hard_irq_disable()	mtmsr(mfmsr() & ~MSR_EE)
+#endif
+#endif /* CONFIG_BOOKE */
+
+#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_LAZY_EE)
 #include <asm/paca.h>
 
 static inline unsigned long arch_local_save_flags(void)
@@ -49,9 +62,11 @@ static inline void arch_local_irq_enable(void)
 	arch_local_irq_restore(1);
 }
 
-static inline unsigned long arch_local_irq_save(void)
+static inline void hard_irq_disable(void)
 {
-	return arch_local_irq_disable();
+	__hard_irq_disable();
+	get_paca()->soft_enabled = 0;
+	get_paca()->hard_enabled = 0;
 }
 
 static inline bool arch_irqs_disabled_flags(unsigned long flags)
@@ -59,29 +74,7 @@ static inline bool arch_irqs_disabled_flags(unsigned long flags)
 	return flags == 0;
 }
 
-static inline bool arch_irqs_disabled(void)
-{
-	return arch_irqs_disabled_flags(arch_local_save_flags());
-}
-
-#ifdef CONFIG_PPC_BOOK3E
-#define __hard_irq_enable()	asm volatile("wrteei 1" : : : "memory");
-#define __hard_irq_disable()	asm volatile("wrteei 0" : : : "memory");
-#else
-#define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
-#define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
-#endif
-
-#define  hard_irq_disable()			\
-	do {					\
-		__hard_irq_disable();		\
-		get_paca()->soft_enabled = 0;	\
-		get_paca()->hard_enabled = 0;	\
-	} while(0)
-
-#else /* CONFIG_PPC64 */
-
-#define SET_MSR_EE(x)	mtmsr(x)
+#else /* CONFIG_PPC64 && CONFIG_PPC_LAZY_EE */
 
 static inline unsigned long arch_local_save_flags(void)
 {
@@ -97,34 +90,24 @@ static inline void arch_local_irq_restore(unsigned long flags)
 #endif
 }
 
-static inline unsigned long arch_local_irq_save(void)
+static inline void arch_local_irq_enable(void)
 {
-	unsigned long flags = arch_local_save_flags();
-#ifdef CONFIG_BOOKE
-	asm volatile("wrteei 0" : : : "memory");
-#else
-	SET_MSR_EE(flags & ~MSR_EE);
-#endif
-	return flags;
+	__hard_irq_enable();
 }
 
-static inline void arch_local_irq_disable(void)
+static inline unsigned long arch_local_irq_disable(void)
 {
-#ifdef CONFIG_BOOKE
-	asm volatile("wrteei 0" : : : "memory");
-#else
-	arch_local_irq_save();
-#endif
+	unsigned long flags;
+
+	flags = arch_local_save_flags();
+	__hard_irq_disable();
+
+	return flags;
 }
 
-static inline void arch_local_irq_enable(void)
+static inline void hard_irq_disable(void)
 {
-#ifdef CONFIG_BOOKE
-	asm volatile("wrteei 1" : : : "memory");
-#else
-	unsigned long msr = mfmsr();
-	SET_MSR_EE(msr | MSR_EE);
-#endif
+	__hard_irq_disable();
 }
 
 static inline bool arch_irqs_disabled_flags(unsigned long flags)
@@ -132,15 +115,18 @@ static inline bool arch_irqs_disabled_flags(unsigned long flags)
 	return (flags & MSR_EE) == 0;
 }
 
+#endif /* CONFIG_PPC64 && CONFIG_PPC_LAZY_EE */
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	return arch_local_irq_disable();
+}
+
 static inline bool arch_irqs_disabled(void)
 {
 	return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
-#define hard_irq_disable()		arch_local_irq_disable()
-
-#endif /* CONFIG_PPC64 */
-
 #define ARCH_IRQ_INIT_FLAGS	IRQ_NOREQUEST
 
 /*
diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h
index b0b06d8..9685b75c 100644
--- a/arch/powerpc/include/asm/irqflags.h
+++ b/arch/powerpc/include/asm/irqflags.h
@@ -39,6 +39,8 @@
 #define TRACE_ENABLE_INTS	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on)
 #define TRACE_DISABLE_INTS	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off)
 
+#ifdef CONFIG_PPC_LAZY_EE
+
 #define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)		\
 	cmpdi	en,0;					\
 	bne	95f;					\
@@ -51,12 +53,32 @@
 	TRACE_AND_RESTORE_IRQ_PARTIAL(en,96f);	\
 	stb	en,PACASOFTIRQEN(r13);		\
 96:
+
+#else /* CONFIG_PPC_LAZY_EE */
+
+#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)		\
+	cmpdi	en,0;					\
+	bne	95f;					\
+	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off)	\
+	b	skip;					\
+95:	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on)	\
+	li	en,1;
+#define TRACE_AND_RESTORE_IRQ(en)		\
+	TRACE_AND_RESTORE_IRQ_PARTIAL(en,96f);	\
+96:
+
+#endif /* CONFIG_PPC_LAZY_EE */
+
 #else
 #define TRACE_ENABLE_INTS
 #define TRACE_DISABLE_INTS
 #define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)
+#ifdef CONFIG_PPC_LAZY_EE
 #define TRACE_AND_RESTORE_IRQ(en)		\
 	stb	en,PACASOFTIRQEN(r13)
+#else
+#define TRACE_AND_RESTORE_IRQ(en)
+#endif
 #endif
 #endif
 
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 269c05a..b74c2b1 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -131,8 +131,12 @@ struct paca_struct {
 	u64 saved_r1;			/* r1 save for RTAS calls or PM */
 	u64 saved_msr;			/* MSR saved here by enter_rtas */
 	u16 trap_save;			/* Used when bad stack is encountered */
+
+#ifdef CONFIG_PPC_LAZY_EE
 	u8 soft_enabled;		/* irq soft-enable flag */
 	u8 hard_enabled;		/* set if irqs are enabled in MSR */
+#endif
+
 	u8 io_sync;			/* writel() needs spin_unlock sync */
 	u8 irq_work_pending;		/* IRQ_WORK interrupt while soft-disable */
 	u8 nap_state_lost;		/* NV GPR values lost in power7_idle */
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 04caee7..5b1fac9 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -146,8 +146,11 @@ int main(void)
 	DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
 	DEFINE(PACAKBASE, offsetof(struct paca_struct, kernelbase));
 	DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
+#ifdef CONFIG_PPC_LAZY_EE
 	DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
 	DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
+#endif
+
 	DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
 #ifdef CONFIG_PPC_MM_SLICES
 	DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index d834425..ce7620b 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -124,8 +124,10 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
 	ld	r12,_MSR(r1)
 #endif /* CONFIG_TRACE_IRQFLAGS */
 	li	r10,1
+#ifdef CONFIG_PPC_LAZY_EE
 	stb	r10,PACASOFTIRQEN(r13)
 	stb	r10,PACAHARDIRQEN(r13)
+#endif
 	std	r10,SOFTE(r1)
 #ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
@@ -602,10 +604,12 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
 2:
 	TRACE_AND_RESTORE_IRQ(r5);
 
+#ifdef CONFIG_PPC_LAZY_EE
 	/* extract EE bit and use it to restore paca->hard_enabled */
 	ld	r3,_MSR(r1)
 	rldicl	r4,r3,49,63		/* r0 = (r3 >> 15) & 1 */
 	stb	r4,PACAHARDIRQEN(r13)
+#endif
 
 #ifdef CONFIG_PPC_BOOK3E
 	b	.exception_return_book3e
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 429983c..d17abb3 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -96,11 +96,6 @@
 #define PROLOG_ADDITION_NONE_DBG
 #define PROLOG_ADDITION_NONE_MC
 
-#define PROLOG_ADDITION_MASKABLE_GEN					    \
-	lbz	r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */	    \
-	cmpwi	cr0,r11,0;		/* yes -> go out of line */	    \
-	beq	masked_interrupt_book3e;
-
 #define PROLOG_ADDITION_2REGS_GEN					    \
 	std	r14,PACA_EXGEN+EX_R14(r13);				    \
 	std	r15,PACA_EXGEN+EX_R15(r13)
@@ -120,11 +115,29 @@
 	std	r14,PACA_EXMC+EX_R14(r13);				    \
 	std	r15,PACA_EXMC+EX_R15(r13)
 
+#ifdef CONFIG_PPC_LAZY_EE
+#define PROLOG_ADDITION_MASKABLE_GEN					    \
+	lbz	r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */	    \
+	cmpwi	cr0,r11,0;		/* yes -> go out of line */	    \
+	beq	masked_interrupt_book3e;
+
 #define PROLOG_ADDITION_DOORBELL_GEN					    \
 	lbz	r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */	    \
 	cmpwi	cr0,r11,0;		/* yes -> go out of line */	    \
 	beq	masked_doorbell_book3e
-
+#else /* CONFIG_PPC_LAZY_EE */
+#define PROLOG_ADDITION_MASKABLE_GEN
+#define PROLOG_ADDITION_DOORBELL_GEN
+#endif /* CONFIG_PPC_LAZY_EE */
+
+#ifdef CONFIG_PPC_LAZY_EE
+#define GET_IRQ_SOFT_ENABLED						    \
+	lbz	r11,PACASOFTIRQEN(r13)
+#else
+#define GET_IRQ_SOFT_ENABLED						    \
+	mfmsr	r11;							    \
+	rlwimi	r11,r11,0,16,16
+#endif
 
 /* Core exception code for all exceptions except TLB misses.
  * XXX: Needs to make SPRN_SPRG_GEN depend on exception type
@@ -148,7 +161,7 @@
 	mfspr	r8,SPRN_XER;		/* save XER in stackframe */	    \
 	ld	r9,excf+EX_R1(r13);	/* load orig r1 back from PACA */   \
 	lwz	r10,excf+EX_CR(r13);	/* load orig CR back from PACA	*/  \
-	lbz	r11,PACASOFTIRQEN(r13);	/* get current IRQ softe */	    \
+	GET_IRQ_SOFT_ENABLED;		/* get current IRQ softe */	    \
 	ld	r12,exception_marker@toc(r2);				    \
 	li	r0,0;							    \
 	std	r3,GPR10(r1);		/* save r10 to stackframe */	    \
@@ -169,11 +182,18 @@
 
 /* Variants for the "ints" argument */
 #define INTS_KEEP
+
+#ifdef CONFIG_PPC_LAZY_EE
 #define INTS_DISABLE_SOFT						    \
 	stb	r0,PACASOFTIRQEN(r13);	/* mark interrupts soft-disabled */ \
 	TRACE_DISABLE_INTS;
 #define INTS_DISABLE_HARD						    \
 	stb	r0,PACAHARDIRQEN(r13); /* and hard disabled */
+#else
+#define INTS_DISABLE_SOFT
+#define INTS_DISABLE_HARD
+#endif
+
 #define INTS_DISABLE_ALL						    \
 	INTS_DISABLE_SOFT						    \
 	INTS_DISABLE_HARD
@@ -553,6 +573,7 @@ kernel_dbg_exc:
 	MASKABLE_EXCEPTION(0x320, ehpriv, .unknown_exception, ACK_NONE)
 
 
+#ifdef CONFIG_PPC_LAZY_EE
 /*
  * An interrupt came in while soft-disabled; clear EE in SRR1,
  * clear paca->hard_enabled and return.
@@ -577,6 +598,7 @@ masked_interrupt_book3e_common:
 	mfspr	r13,SPRN_SPRG_GEN_SCRATCH;
 	rfi
 	b	.
+#endif /* CONFIG_PPC_LAZY_EE */
 
 /*
  * This is called from 0x300 and 0x400 handlers after the prologs with
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 06c7251..017d669 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -559,12 +559,14 @@ _GLOBAL(pmac_secondary_start)
 	add	r13,r13,r4		/* for this processor.		*/
 	SET_PACA(r13)			/* Save vaddr of paca in an SPRG*/
 
+#ifdef CONFIG_PPC_LAZY_EE
 	/* Mark interrupts soft and hard disabled (they might be enabled
 	 * in the PACA when doing hotplug)
 	 */
 	li	r0,0
 	stb	r0,PACASOFTIRQEN(r13)
 	stb	r0,PACAHARDIRQEN(r13)
+#endif
 
 	/* Create a temp kernel stack for use before relocation is on.	*/
 	ld	r1,PACAEMERGSP(r13)
@@ -621,14 +623,18 @@ __secondary_start:
 #ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
 	ori	r4,r4,MSR_EE
+#ifdef CONFIG_PPC_LAZY_EE
 	li	r8,1
 	stb	r8,PACAHARDIRQEN(r13)
+#endif
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
+#ifdef CONFIG_PPC_LAZY_EE
 BEGIN_FW_FTR_SECTION
 	stb	r7,PACAHARDIRQEN(r13)
 END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
 	stb	r7,PACASOFTIRQEN(r13)
+#endif
 
 	mtspr	SPRN_SRR0,r3
 	mtspr	SPRN_SRR1,r4
@@ -775,8 +781,10 @@ _INIT_GLOBAL(start_here_common)
 
 	/* Load up the kernel context */
 5:
+#ifdef CONFIG_PPC_LAZY_EE
 	li	r5,0
 	stb	r5,PACASOFTIRQEN(r13)	/* Soft Disabled */
+#endif
 #ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
 	mfmsr	r5
@@ -785,7 +793,9 @@ BEGIN_FW_FTR_SECTION
 	li	r5,1
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
+#ifdef CONFIG_PPC_LAZY_EE
 	stb	r5,PACAHARDIRQEN(r13)	/* Hard Disabled on others */
+#endif
 
 	bl	.start_kernel
 
diff --git a/arch/powerpc/kernel/idle_book3e.S b/arch/powerpc/kernel/idle_book3e.S
index 16c002d..34b09e0 100644
--- a/arch/powerpc/kernel/idle_book3e.S
+++ b/arch/powerpc/kernel/idle_book3e.S
@@ -28,6 +28,7 @@ _GLOBAL(book3e_idle)
 	/* Hard disable interrupts */
 	wrteei	0
 
+#ifdef CONFIG_PPC_LAZY_EE
 	/* Now check if an interrupt came in while we were soft disabled
 	 * since we may otherwise lose it (doorbells etc...). We know
 	 * that since PACAHARDIRQEN will have been cleared in that case.
@@ -35,6 +36,7 @@ _GLOBAL(book3e_idle)
 	lbz	r3,PACAHARDIRQEN(r13)
 	cmpwi	cr0,r3,0
 	beqlr
+#endif
 
 	/* Now we are going to mark ourselves as soft and hard enables in
 	 * order to be able to take interrupts while asleep. We inform lockdep
@@ -44,9 +46,12 @@ _GLOBAL(book3e_idle)
 	stdu    r1,-128(r1)
 	bl	.trace_hardirqs_on
 #endif
+
+#ifdef CONFIG_PPC_LAZY_EE
 	li	r0,1
 	stb	r0,PACASOFTIRQEN(r13)
 	stb	r0,PACAHARDIRQEN(r13)
+#endif
 	
 	/* Interrupts will make use return to LR, so get something we want
 	 * in there
@@ -56,10 +61,12 @@ _GLOBAL(book3e_idle)
 	/* Hard disable interrupts again */
 	wrteei	0
 
+#ifdef CONFIG_PPC_LAZY_EE
 	/* Mark them off again in the PACA as well */
 	li	r0,0
 	stb	r0,PACASOFTIRQEN(r13)
 	stb	r0,PACAHARDIRQEN(r13)
+#endif
 
 	/* Tell lockdep about it */
 #ifdef CONFIG_TRACE_IRQFLAGS
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 701d4ac..e2d1784 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -99,6 +99,8 @@ EXPORT_SYMBOL(irq_desc);
 
 int distribute_irqs = 1;
 
+#ifdef CONFIG_PPC_LAZY_EE
+
 static inline notrace unsigned long get_hard_enabled(void)
 {
 	unsigned long enabled;
@@ -193,6 +195,9 @@ notrace void arch_local_irq_restore(unsigned long en)
 	__hard_irq_enable();
 }
 EXPORT_SYMBOL(arch_local_irq_restore);
+
+#endif /* CONFIG_PPC_LAZY_EE */
+
 #endif /* CONFIG_PPC64 */
 
 int arch_show_interrupts(struct seq_file *p, int prec)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 4cb8f1e..06f5b19 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -233,8 +233,10 @@ void __init early_setup(unsigned long dt_ptr)
 #ifdef CONFIG_SMP
 void early_setup_secondary(void)
 {
+#ifdef CONFIG_PPC_LAZY_EE
 	/* Mark interrupts enabled in PACA */
 	get_paca()->soft_enabled = 0;
+#endif
 
 	/* Initialize the hash table or TLB handling */
 	early_init_mmu_secondary();
-- 
1.7.5.1

^ permalink raw reply related

* [PATCH 1/2] powerpc/fsl-booke: Fixup calc_cam_sz to support MMU v2
From: Kumar Gala @ 2012-01-18 19:39 UTC (permalink / raw)
  To: linuxppc-dev

The registers that describe size supported by TLB are different on MMU
v2 as well as we support power of two page sizes.  For now we continue
to assume that FSL variable size array supports all page sizes up to the
maximum one reported in TLB1PS.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 arch/powerpc/include/asm/reg_booke.h |    1 +
 arch/powerpc/mm/fsl_booke_mmu.c      |   19 +++++++++++++------
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 500fe1d..8a97aa7 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -62,6 +62,7 @@
 #define SPRN_DVC2	0x13F	/* Data Value Compare Register 2 */
 #define SPRN_MAS8	0x155	/* MMU Assist Register 8 */
 #define SPRN_TLB0PS	0x158	/* TLB 0 Page Size Register */
+#define SPRN_TLB1PS	0x159	/* TLB 1 Page Size Register */
 #define SPRN_MAS5_MAS6	0x15c	/* MMU Assist Register 5 || 6 */
 #define SPRN_MAS8_MAS1	0x15d	/* MMU Assist Register 8 || 1 */
 #define SPRN_EPTCFG	0x15e	/* Embedded Page Table Config */
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index 66a6fd3..07ba45b 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -149,12 +149,19 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
 unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
 			  phys_addr_t phys)
 {
-	unsigned int camsize = __ilog2(ram) & ~1U;
-	unsigned int align = __ffs(virt | phys) & ~1U;
-	unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
-
-	/* Convert (4^max) kB to (2^max) bytes */
-	max_cam = max_cam * 2 + 10;
+	unsigned int camsize = __ilog2(ram);
+	unsigned int align = __ffs(virt | phys);
+	unsigned long max_cam;
+
+	if ((mfspr(SPRN_MMUCFG) & MMUCFG_MAVN) == MMUCFG_MAVN_V1) {
+		/* Convert (4^max) kB to (2^max) bytes */
+		max_cam = ((mfspr(SPRN_TLB1CFG) >> 16) & 0xf) * 2 + 10;
+		camsize &= ~1U;
+		align &= ~1U;
+	} else {
+		/* Convert (2^max) kB to (2^max) bytes */
+		max_cam = __ilog2(mfspr(SPRN_TLB1PS)) + 10;
+	}
 
 	if (camsize > align)
 		camsize = align;
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH 2/2] powerpc: Add initial e6500 cpu support
From: Kumar Gala @ 2012-01-18 19:39 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1326915580-19652-1-git-send-email-galak@kernel.crashing.org>

Add basic support for e6500 core in its single threaded mode.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 arch/powerpc/include/asm/cputable.h |   12 ++++++++----
 arch/powerpc/kernel/cputable.c      |   18 ++++++++++++++++++
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index ad55a1c..b9219e9 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -390,6 +390,10 @@ extern const char *powerpc_base_platform;
 	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
 	    CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
 	    CPU_FTR_DEBUG_LVL_EXC)
+#define CPU_FTRS_E6500	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
+	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
+	    CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
+	    CPU_FTR_DEBUG_LVL_EXC)
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
@@ -442,7 +446,7 @@ extern const char *powerpc_base_platform;
 
 #ifdef __powerpc64__
 #ifdef CONFIG_PPC_BOOK3E
-#define CPU_FTRS_POSSIBLE	(CPU_FTRS_E5500 | CPU_FTRS_A2)
+#define CPU_FTRS_POSSIBLE	(CPU_FTRS_E6500 | CPU_FTRS_E5500 | CPU_FTRS_A2)
 #else
 #define CPU_FTRS_POSSIBLE	\
 	    (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |	\
@@ -483,7 +487,7 @@ enum {
 #endif
 #ifdef CONFIG_E500
 	    CPU_FTRS_E500 | CPU_FTRS_E500_2 | CPU_FTRS_E500MC |
-	    CPU_FTRS_E5500 |
+	    CPU_FTRS_E5500 | CPU_FTRS_E6500 |
 #endif
 	    0,
 };
@@ -491,7 +495,7 @@ enum {
 
 #ifdef __powerpc64__
 #ifdef CONFIG_PPC_BOOK3E
-#define CPU_FTRS_ALWAYS		(CPU_FTRS_E5500 & CPU_FTRS_A2)
+#define CPU_FTRS_ALWAYS		(CPU_FTRS_E6500 & CPU_FTRS_E5500 & CPU_FTRS_A2)
 #else
 #define CPU_FTRS_ALWAYS		\
 	    (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 &	\
@@ -528,7 +532,7 @@ enum {
 #endif
 #ifdef CONFIG_E500
 	    CPU_FTRS_E500 & CPU_FTRS_E500_2 & CPU_FTRS_E500MC &
-	    CPU_FTRS_E5500 &
+	    CPU_FTRS_E5500 & CPU_FTRS_E6500 &
 #endif
 	    CPU_FTRS_POSSIBLE,
 };
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 81db9e2..4dccf51 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -2019,6 +2019,24 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce5500",
 	},
+	{	/* e6500 */
+		.pvr_mask		= 0xffff0000,
+		.pvr_value		= 0x80400000,
+		.cpu_name		= "e6500",
+		.cpu_features		= CPU_FTRS_E6500,
+		.cpu_user_features	= COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
+		.mmu_features		= MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
+			MMU_FTR_USE_TLBILX,
+		.icache_bsize		= 64,
+		.dcache_bsize		= 64,
+		.num_pmcs		= 4,
+		.oprofile_cpu_type	= "ppc/e6500",
+		.oprofile_type		= PPC_OPROFILE_FSL_EMB,
+		.cpu_setup		= __setup_cpu_e5500,
+		.cpu_restore		= __restore_cpu_e5500,
+		.machine_check		= machine_check_e500mc,
+		.platform		= "ppce6500",
+	},
 #ifdef CONFIG_PPC32
 	{	/* default match */
 		.pvr_mask		= 0x00000000,
-- 
1.7.3.4

^ permalink raw reply related

* Re: [PATCH] powerpc/booke64: Configurable lazy interrupt disabling
From: Benjamin Herrenschmidt @ 2012-01-18 21:10 UTC (permalink / raw)
  To: Laurentiu Tudor; +Cc: linuxppc-dev
In-Reply-To: <1326897306-3924-1-git-send-email-Laurentiu.Tudor@freescale.com>

On Wed, 2012-01-18 at 16:35 +0200, Laurentiu Tudor wrote:
> This patch adds a menuconfig option that allows controlling
> the lazy interrupt disabling feature implemented by this
> commit:
> 
> commit d04c56f73c30a5e593202ecfcf25ed43d42363a2
> Author: Paul Mackerras
> Date:   Wed Oct 4 16:47:49 2006 +1000
> 
>     [POWERPC] Lazy interrupt disabling for 64-bit machines
> 
> The code in 'powerpc/include/asm/hw_irq.h' was rearranged and
> cleaned-up a bit in order to reduce the number of needed #ifdef's.

It's still nasty. Do you have numbers showing that it's worth disabling
on BookE ?

Cheers,
Ben.

> Signed-off-by: Laurentiu Tudor <Laurentiu.Tudor@freescale.com>
> ---
> Patch is against
> git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next
> 
>  arch/powerpc/Kconfig                 |   16 ++++++
>  arch/powerpc/include/asm/hw_irq.h    |   86 ++++++++++++++--------------------
>  arch/powerpc/include/asm/irqflags.h  |   22 +++++++++
>  arch/powerpc/include/asm/paca.h      |    4 ++
>  arch/powerpc/kernel/asm-offsets.c    |    3 +
>  arch/powerpc/kernel/entry_64.S       |    4 ++
>  arch/powerpc/kernel/exceptions-64e.S |   36 +++++++++++---
>  arch/powerpc/kernel/head_64.S        |   10 ++++
>  arch/powerpc/kernel/idle_book3e.S    |    7 +++
>  arch/powerpc/kernel/irq.c            |    5 ++
>  arch/powerpc/kernel/setup_64.c       |    2 +
>  11 files changed, 138 insertions(+), 57 deletions(-)
> 
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index ce5e045..2792278 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -609,6 +609,22 @@ config SECCOMP
>  
>  	  If unsure, say Y. Only embedded should say N here.
>  
> +config PPC_LAZY_EE
> +	bool
> +	prompt "Lazy interrupt disabling" if PPC_BOOK3E_64
> +	default y if PPC_BOOK3S_64
> +	help
> +	  Local interrupt disabling functions don't disable
> +	  interrupts right away and instead just clear an
> +	  internal 'interrupts are enabled' flag. If an
> +	  interrupt is triggered during this time, the
> +	  interrupt handling code checks the flag, and if
> +	  interrupts are supposed to be off, disables them
> +	  for real and returns, skipping interrupt handling.
> +	  When interrupts are enabled back, the interrupt
> +	  fires again and this time gets handled.
> +
> +	  If unsure, say N.
>  endmenu
>  
>  config ISA_DMA_API
> diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
> index bb712c9..6f32593 100644
> --- a/arch/powerpc/include/asm/hw_irq.h
> +++ b/arch/powerpc/include/asm/hw_irq.h
> @@ -13,7 +13,20 @@
>  
>  extern void timer_interrupt(struct pt_regs *);
>  
> +#ifdef CONFIG_BOOKE
> +#define __hard_irq_enable()	asm volatile("wrteei 1" : : : "memory");
> +#define __hard_irq_disable()	asm volatile("wrteei 0" : : : "memory");
> +#else
>  #ifdef CONFIG_PPC64
> +#define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
> +#define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
> +#else
> +#define __hard_irq_enable()	mtmsr(mfmsr() | MSR_EE)
> +#define __hard_irq_disable()	mtmsr(mfmsr() & ~MSR_EE)
> +#endif
> +#endif /* CONFIG_BOOKE */
> +
> +#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_LAZY_EE)
>  #include <asm/paca.h>
>  
>  static inline unsigned long arch_local_save_flags(void)
> @@ -49,9 +62,11 @@ static inline void arch_local_irq_enable(void)
>  	arch_local_irq_restore(1);
>  }
>  
> -static inline unsigned long arch_local_irq_save(void)
> +static inline void hard_irq_disable(void)
>  {
> -	return arch_local_irq_disable();
> +	__hard_irq_disable();
> +	get_paca()->soft_enabled = 0;
> +	get_paca()->hard_enabled = 0;
>  }
>  
>  static inline bool arch_irqs_disabled_flags(unsigned long flags)
> @@ -59,29 +74,7 @@ static inline bool arch_irqs_disabled_flags(unsigned long flags)
>  	return flags == 0;
>  }
>  
> -static inline bool arch_irqs_disabled(void)
> -{
> -	return arch_irqs_disabled_flags(arch_local_save_flags());
> -}
> -
> -#ifdef CONFIG_PPC_BOOK3E
> -#define __hard_irq_enable()	asm volatile("wrteei 1" : : : "memory");
> -#define __hard_irq_disable()	asm volatile("wrteei 0" : : : "memory");
> -#else
> -#define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
> -#define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
> -#endif
> -
> -#define  hard_irq_disable()			\
> -	do {					\
> -		__hard_irq_disable();		\
> -		get_paca()->soft_enabled = 0;	\
> -		get_paca()->hard_enabled = 0;	\
> -	} while(0)
> -
> -#else /* CONFIG_PPC64 */
> -
> -#define SET_MSR_EE(x)	mtmsr(x)
> +#else /* CONFIG_PPC64 && CONFIG_PPC_LAZY_EE */
>  
>  static inline unsigned long arch_local_save_flags(void)
>  {
> @@ -97,34 +90,24 @@ static inline void arch_local_irq_restore(unsigned long flags)
>  #endif
>  }
>  
> -static inline unsigned long arch_local_irq_save(void)
> +static inline void arch_local_irq_enable(void)
>  {
> -	unsigned long flags = arch_local_save_flags();
> -#ifdef CONFIG_BOOKE
> -	asm volatile("wrteei 0" : : : "memory");
> -#else
> -	SET_MSR_EE(flags & ~MSR_EE);
> -#endif
> -	return flags;
> +	__hard_irq_enable();
>  }
>  
> -static inline void arch_local_irq_disable(void)
> +static inline unsigned long arch_local_irq_disable(void)
>  {
> -#ifdef CONFIG_BOOKE
> -	asm volatile("wrteei 0" : : : "memory");
> -#else
> -	arch_local_irq_save();
> -#endif
> +	unsigned long flags;
> +
> +	flags = arch_local_save_flags();
> +	__hard_irq_disable();
> +
> +	return flags;
>  }
>  
> -static inline void arch_local_irq_enable(void)
> +static inline void hard_irq_disable(void)
>  {
> -#ifdef CONFIG_BOOKE
> -	asm volatile("wrteei 1" : : : "memory");
> -#else
> -	unsigned long msr = mfmsr();
> -	SET_MSR_EE(msr | MSR_EE);
> -#endif
> +	__hard_irq_disable();
>  }
>  
>  static inline bool arch_irqs_disabled_flags(unsigned long flags)
> @@ -132,15 +115,18 @@ static inline bool arch_irqs_disabled_flags(unsigned long flags)
>  	return (flags & MSR_EE) == 0;
>  }
>  
> +#endif /* CONFIG_PPC64 && CONFIG_PPC_LAZY_EE */
> +
> +static inline unsigned long arch_local_irq_save(void)
> +{
> +	return arch_local_irq_disable();
> +}
> +
>  static inline bool arch_irqs_disabled(void)
>  {
>  	return arch_irqs_disabled_flags(arch_local_save_flags());
>  }
>  
> -#define hard_irq_disable()		arch_local_irq_disable()
> -
> -#endif /* CONFIG_PPC64 */
> -
>  #define ARCH_IRQ_INIT_FLAGS	IRQ_NOREQUEST
>  
>  /*
> diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h
> index b0b06d8..9685b75c 100644
> --- a/arch/powerpc/include/asm/irqflags.h
> +++ b/arch/powerpc/include/asm/irqflags.h
> @@ -39,6 +39,8 @@
>  #define TRACE_ENABLE_INTS	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on)
>  #define TRACE_DISABLE_INTS	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off)
>  
> +#ifdef CONFIG_PPC_LAZY_EE
> +
>  #define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)		\
>  	cmpdi	en,0;					\
>  	bne	95f;					\
> @@ -51,12 +53,32 @@
>  	TRACE_AND_RESTORE_IRQ_PARTIAL(en,96f);	\
>  	stb	en,PACASOFTIRQEN(r13);		\
>  96:
> +
> +#else /* CONFIG_PPC_LAZY_EE */
> +
> +#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)		\
> +	cmpdi	en,0;					\
> +	bne	95f;					\
> +	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off)	\
> +	b	skip;					\
> +95:	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on)	\
> +	li	en,1;
> +#define TRACE_AND_RESTORE_IRQ(en)		\
> +	TRACE_AND_RESTORE_IRQ_PARTIAL(en,96f);	\
> +96:
> +
> +#endif /* CONFIG_PPC_LAZY_EE */
> +
>  #else
>  #define TRACE_ENABLE_INTS
>  #define TRACE_DISABLE_INTS
>  #define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)
> +#ifdef CONFIG_PPC_LAZY_EE
>  #define TRACE_AND_RESTORE_IRQ(en)		\
>  	stb	en,PACASOFTIRQEN(r13)
> +#else
> +#define TRACE_AND_RESTORE_IRQ(en)
> +#endif
>  #endif
>  #endif
>  
> diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
> index 269c05a..b74c2b1 100644
> --- a/arch/powerpc/include/asm/paca.h
> +++ b/arch/powerpc/include/asm/paca.h
> @@ -131,8 +131,12 @@ struct paca_struct {
>  	u64 saved_r1;			/* r1 save for RTAS calls or PM */
>  	u64 saved_msr;			/* MSR saved here by enter_rtas */
>  	u16 trap_save;			/* Used when bad stack is encountered */
> +
> +#ifdef CONFIG_PPC_LAZY_EE
>  	u8 soft_enabled;		/* irq soft-enable flag */
>  	u8 hard_enabled;		/* set if irqs are enabled in MSR */
> +#endif
> +
>  	u8 io_sync;			/* writel() needs spin_unlock sync */
>  	u8 irq_work_pending;		/* IRQ_WORK interrupt while soft-disable */
>  	u8 nap_state_lost;		/* NV GPR values lost in power7_idle */
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index 04caee7..5b1fac9 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -146,8 +146,11 @@ int main(void)
>  	DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
>  	DEFINE(PACAKBASE, offsetof(struct paca_struct, kernelbase));
>  	DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
> +#ifdef CONFIG_PPC_LAZY_EE
>  	DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
>  	DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
> +#endif
> +
>  	DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
>  #ifdef CONFIG_PPC_MM_SLICES
>  	DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
> diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
> index d834425..ce7620b 100644
> --- a/arch/powerpc/kernel/entry_64.S
> +++ b/arch/powerpc/kernel/entry_64.S
> @@ -124,8 +124,10 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
>  	ld	r12,_MSR(r1)
>  #endif /* CONFIG_TRACE_IRQFLAGS */
>  	li	r10,1
> +#ifdef CONFIG_PPC_LAZY_EE
>  	stb	r10,PACASOFTIRQEN(r13)
>  	stb	r10,PACAHARDIRQEN(r13)
> +#endif
>  	std	r10,SOFTE(r1)
>  #ifdef CONFIG_PPC_ISERIES
>  BEGIN_FW_FTR_SECTION
> @@ -602,10 +604,12 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
>  2:
>  	TRACE_AND_RESTORE_IRQ(r5);
>  
> +#ifdef CONFIG_PPC_LAZY_EE
>  	/* extract EE bit and use it to restore paca->hard_enabled */
>  	ld	r3,_MSR(r1)
>  	rldicl	r4,r3,49,63		/* r0 = (r3 >> 15) & 1 */
>  	stb	r4,PACAHARDIRQEN(r13)
> +#endif
>  
>  #ifdef CONFIG_PPC_BOOK3E
>  	b	.exception_return_book3e
> diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
> index 429983c..d17abb3 100644
> --- a/arch/powerpc/kernel/exceptions-64e.S
> +++ b/arch/powerpc/kernel/exceptions-64e.S
> @@ -96,11 +96,6 @@
>  #define PROLOG_ADDITION_NONE_DBG
>  #define PROLOG_ADDITION_NONE_MC
>  
> -#define PROLOG_ADDITION_MASKABLE_GEN					    \
> -	lbz	r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */	    \
> -	cmpwi	cr0,r11,0;		/* yes -> go out of line */	    \
> -	beq	masked_interrupt_book3e;
> -
>  #define PROLOG_ADDITION_2REGS_GEN					    \
>  	std	r14,PACA_EXGEN+EX_R14(r13);				    \
>  	std	r15,PACA_EXGEN+EX_R15(r13)
> @@ -120,11 +115,29 @@
>  	std	r14,PACA_EXMC+EX_R14(r13);				    \
>  	std	r15,PACA_EXMC+EX_R15(r13)
>  
> +#ifdef CONFIG_PPC_LAZY_EE
> +#define PROLOG_ADDITION_MASKABLE_GEN					    \
> +	lbz	r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */	    \
> +	cmpwi	cr0,r11,0;		/* yes -> go out of line */	    \
> +	beq	masked_interrupt_book3e;
> +
>  #define PROLOG_ADDITION_DOORBELL_GEN					    \
>  	lbz	r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */	    \
>  	cmpwi	cr0,r11,0;		/* yes -> go out of line */	    \
>  	beq	masked_doorbell_book3e
> -
> +#else /* CONFIG_PPC_LAZY_EE */
> +#define PROLOG_ADDITION_MASKABLE_GEN
> +#define PROLOG_ADDITION_DOORBELL_GEN
> +#endif /* CONFIG_PPC_LAZY_EE */
> +
> +#ifdef CONFIG_PPC_LAZY_EE
> +#define GET_IRQ_SOFT_ENABLED						    \
> +	lbz	r11,PACASOFTIRQEN(r13)
> +#else
> +#define GET_IRQ_SOFT_ENABLED						    \
> +	mfmsr	r11;							    \
> +	rlwimi	r11,r11,0,16,16
> +#endif
>  
>  /* Core exception code for all exceptions except TLB misses.
>   * XXX: Needs to make SPRN_SPRG_GEN depend on exception type
> @@ -148,7 +161,7 @@
>  	mfspr	r8,SPRN_XER;		/* save XER in stackframe */	    \
>  	ld	r9,excf+EX_R1(r13);	/* load orig r1 back from PACA */   \
>  	lwz	r10,excf+EX_CR(r13);	/* load orig CR back from PACA	*/  \
> -	lbz	r11,PACASOFTIRQEN(r13);	/* get current IRQ softe */	    \
> +	GET_IRQ_SOFT_ENABLED;		/* get current IRQ softe */	    \
>  	ld	r12,exception_marker@toc(r2);				    \
>  	li	r0,0;							    \
>  	std	r3,GPR10(r1);		/* save r10 to stackframe */	    \
> @@ -169,11 +182,18 @@
>  
>  /* Variants for the "ints" argument */
>  #define INTS_KEEP
> +
> +#ifdef CONFIG_PPC_LAZY_EE
>  #define INTS_DISABLE_SOFT						    \
>  	stb	r0,PACASOFTIRQEN(r13);	/* mark interrupts soft-disabled */ \
>  	TRACE_DISABLE_INTS;
>  #define INTS_DISABLE_HARD						    \
>  	stb	r0,PACAHARDIRQEN(r13); /* and hard disabled */
> +#else
> +#define INTS_DISABLE_SOFT
> +#define INTS_DISABLE_HARD
> +#endif
> +
>  #define INTS_DISABLE_ALL						    \
>  	INTS_DISABLE_SOFT						    \
>  	INTS_DISABLE_HARD
> @@ -553,6 +573,7 @@ kernel_dbg_exc:
>  	MASKABLE_EXCEPTION(0x320, ehpriv, .unknown_exception, ACK_NONE)
>  
> 
> +#ifdef CONFIG_PPC_LAZY_EE
>  /*
>   * An interrupt came in while soft-disabled; clear EE in SRR1,
>   * clear paca->hard_enabled and return.
> @@ -577,6 +598,7 @@ masked_interrupt_book3e_common:
>  	mfspr	r13,SPRN_SPRG_GEN_SCRATCH;
>  	rfi
>  	b	.
> +#endif /* CONFIG_PPC_LAZY_EE */
>  
>  /*
>   * This is called from 0x300 and 0x400 handlers after the prologs with
> diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
> index 06c7251..017d669 100644
> --- a/arch/powerpc/kernel/head_64.S
> +++ b/arch/powerpc/kernel/head_64.S
> @@ -559,12 +559,14 @@ _GLOBAL(pmac_secondary_start)
>  	add	r13,r13,r4		/* for this processor.		*/
>  	SET_PACA(r13)			/* Save vaddr of paca in an SPRG*/
>  
> +#ifdef CONFIG_PPC_LAZY_EE
>  	/* Mark interrupts soft and hard disabled (they might be enabled
>  	 * in the PACA when doing hotplug)
>  	 */
>  	li	r0,0
>  	stb	r0,PACASOFTIRQEN(r13)
>  	stb	r0,PACAHARDIRQEN(r13)
> +#endif
>  
>  	/* Create a temp kernel stack for use before relocation is on.	*/
>  	ld	r1,PACAEMERGSP(r13)
> @@ -621,14 +623,18 @@ __secondary_start:
>  #ifdef CONFIG_PPC_ISERIES
>  BEGIN_FW_FTR_SECTION
>  	ori	r4,r4,MSR_EE
> +#ifdef CONFIG_PPC_LAZY_EE
>  	li	r8,1
>  	stb	r8,PACAHARDIRQEN(r13)
> +#endif
>  END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
>  #endif
> +#ifdef CONFIG_PPC_LAZY_EE
>  BEGIN_FW_FTR_SECTION
>  	stb	r7,PACAHARDIRQEN(r13)
>  END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
>  	stb	r7,PACASOFTIRQEN(r13)
> +#endif
>  
>  	mtspr	SPRN_SRR0,r3
>  	mtspr	SPRN_SRR1,r4
> @@ -775,8 +781,10 @@ _INIT_GLOBAL(start_here_common)
>  
>  	/* Load up the kernel context */
>  5:
> +#ifdef CONFIG_PPC_LAZY_EE
>  	li	r5,0
>  	stb	r5,PACASOFTIRQEN(r13)	/* Soft Disabled */
> +#endif
>  #ifdef CONFIG_PPC_ISERIES
>  BEGIN_FW_FTR_SECTION
>  	mfmsr	r5
> @@ -785,7 +793,9 @@ BEGIN_FW_FTR_SECTION
>  	li	r5,1
>  END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
>  #endif
> +#ifdef CONFIG_PPC_LAZY_EE
>  	stb	r5,PACAHARDIRQEN(r13)	/* Hard Disabled on others */
> +#endif
>  
>  	bl	.start_kernel
>  
> diff --git a/arch/powerpc/kernel/idle_book3e.S b/arch/powerpc/kernel/idle_book3e.S
> index 16c002d..34b09e0 100644
> --- a/arch/powerpc/kernel/idle_book3e.S
> +++ b/arch/powerpc/kernel/idle_book3e.S
> @@ -28,6 +28,7 @@ _GLOBAL(book3e_idle)
>  	/* Hard disable interrupts */
>  	wrteei	0
>  
> +#ifdef CONFIG_PPC_LAZY_EE
>  	/* Now check if an interrupt came in while we were soft disabled
>  	 * since we may otherwise lose it (doorbells etc...). We know
>  	 * that since PACAHARDIRQEN will have been cleared in that case.
> @@ -35,6 +36,7 @@ _GLOBAL(book3e_idle)
>  	lbz	r3,PACAHARDIRQEN(r13)
>  	cmpwi	cr0,r3,0
>  	beqlr
> +#endif
>  
>  	/* Now we are going to mark ourselves as soft and hard enables in
>  	 * order to be able to take interrupts while asleep. We inform lockdep
> @@ -44,9 +46,12 @@ _GLOBAL(book3e_idle)
>  	stdu    r1,-128(r1)
>  	bl	.trace_hardirqs_on
>  #endif
> +
> +#ifdef CONFIG_PPC_LAZY_EE
>  	li	r0,1
>  	stb	r0,PACASOFTIRQEN(r13)
>  	stb	r0,PACAHARDIRQEN(r13)
> +#endif
>  	
>  	/* Interrupts will make use return to LR, so get something we want
>  	 * in there
> @@ -56,10 +61,12 @@ _GLOBAL(book3e_idle)
>  	/* Hard disable interrupts again */
>  	wrteei	0
>  
> +#ifdef CONFIG_PPC_LAZY_EE
>  	/* Mark them off again in the PACA as well */
>  	li	r0,0
>  	stb	r0,PACASOFTIRQEN(r13)
>  	stb	r0,PACAHARDIRQEN(r13)
> +#endif
>  
>  	/* Tell lockdep about it */
>  #ifdef CONFIG_TRACE_IRQFLAGS
> diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
> index 701d4ac..e2d1784 100644
> --- a/arch/powerpc/kernel/irq.c
> +++ b/arch/powerpc/kernel/irq.c
> @@ -99,6 +99,8 @@ EXPORT_SYMBOL(irq_desc);
>  
>  int distribute_irqs = 1;
>  
> +#ifdef CONFIG_PPC_LAZY_EE
> +
>  static inline notrace unsigned long get_hard_enabled(void)
>  {
>  	unsigned long enabled;
> @@ -193,6 +195,9 @@ notrace void arch_local_irq_restore(unsigned long en)
>  	__hard_irq_enable();
>  }
>  EXPORT_SYMBOL(arch_local_irq_restore);
> +
> +#endif /* CONFIG_PPC_LAZY_EE */
> +
>  #endif /* CONFIG_PPC64 */
>  
>  int arch_show_interrupts(struct seq_file *p, int prec)
> diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
> index 4cb8f1e..06f5b19 100644
> --- a/arch/powerpc/kernel/setup_64.c
> +++ b/arch/powerpc/kernel/setup_64.c
> @@ -233,8 +233,10 @@ void __init early_setup(unsigned long dt_ptr)
>  #ifdef CONFIG_SMP
>  void early_setup_secondary(void)
>  {
> +#ifdef CONFIG_PPC_LAZY_EE
>  	/* Mark interrupts enabled in PACA */
>  	get_paca()->soft_enabled = 0;
> +#endif
>  
>  	/* Initialize the hash table or TLB handling */
>  	early_init_mmu_secondary();

^ permalink raw reply

* [PATCH 1/2] powerpc/dts: Add dts for p1020rdb-pc
From: Zhicheng Fan @ 2012-01-19  9:06 UTC (permalink / raw)
  To: galak, linuxppc-dev; +Cc: Fanzc

From: Fanzc <b32736@freeescale.com>

P1020RDB-PC Overview
------------------
1Gbyte DDR3 SDRAM
32 Mbyte NAND flash
10 16Mbyte NOR flash
16 Mbyte SPI flash
SD connector to interface with the SD memory card
Real-time clock on I2C bus

PCIe:
- x1 PCIe slot
- x1 mini-PCIe slot

10/100/1000 BaseT Ethernet ports:
- eTSEC1, RGMII: one 10/100/1000 port using VitesseTM VSC7385 L2 switch
- eTSEC2, SGMII: one 10/100/1000 port using VitesseTM VSC8221
- eTSEC3, RGMII: one 10/100/1000 port using AtherosTM AR8021

USB 2.0 port:
- Two USB2.0 Type A receptacles
- One USB2.0 signal to Mini PCIe slot

Dual RJ45 UART ports:
- DUART interface: supports two UARTs up to 115200 bps for console display

Signed-off-by: Fanzc <b32736@freeescale.com>
---
 arch/powerpc/boot/dts/p1020rdb-pc.dts            |   67 ++++++
 arch/powerpc/boot/dts/p1020rdb-pc.dtsi           |  251 ++++++++++++++++++++++
 arch/powerpc/boot/dts/p1020rdb-pc_36b.dts        |   67 ++++++
 arch/powerpc/boot/dts/p1020rdb-pc_camp_core0.dts |   63 ++++++
 arch/powerpc/boot/dts/p1020rdb-pc_camp_core1.dts |  141 ++++++++++++
 5 files changed, 589 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/p1020rdb-pc.dts
 create mode 100644 arch/powerpc/boot/dts/p1020rdb-pc.dtsi
 create mode 100644 arch/powerpc/boot/dts/p1020rdb-pc_36b.dts
 create mode 100644 arch/powerpc/boot/dts/p1020rdb-pc_camp_core0.dts
 create mode 100644 arch/powerpc/boot/dts/p1020rdb-pc_camp_core1.dts

diff --git a/arch/powerpc/boot/dts/p1020rdb-pc.dts b/arch/powerpc/boot/dts/p1020rdb-pc.dts
new file mode 100644
index 0000000..e283b94
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb-pc.dts
@@ -0,0 +1,67 @@
+/*
+ * P1020 RDB-PC Device Tree Source
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+	model = "fsl,P1020RDB-PC";
+	compatible = "fsl,P1020RDB-PC";
+
+	memory {
+		device_type = "memory";
+	};
+
+	lbc: localbus@ffe05000 {
+		reg = <0 0xffe05000 0 0x1000>;
+
+		/* NOR, NAND Flashes and Vitesse 5 port L2 switch */
+		ranges = <0x0 0x0 0x0 0xef000000 0x01000000
+			  0x1 0x0 0x0 0xff800000 0x00040000
+			  0x2 0x0 0x0 0xffb00000 0x00020000
+			  0x3 0x0 0x0 0xffa00000 0x00020000>;
+	};
+
+	soc: soc@ffe00000 {
+		ranges = <0x0 0x0 0xffe00000 0x100000>;
+	};
+
+	pci0: pcie@ffe09000 {
+		ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+		reg = <0 0xffe09000 0 0x1000>;
+		pcie@0 {
+			ranges = <0x2000000 0x0 0xa0000000
+				  0x2000000 0x0 0xa0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	pci1: pcie@ffe0a000 {
+		reg = <0 0xffe0a000 0 0x1000>;
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+		pcie@0 {
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+};
+
+/include/ "p1020rdb-pc.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1020rdb-pc.dtsi b/arch/powerpc/boot/dts/p1020rdb-pc.dtsi
new file mode 100644
index 0000000..1c4003f
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb-pc.dtsi
@@ -0,0 +1,251 @@
+/*
+ * P1020 RDB-PC Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&lbc {
+	nor@0,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "cfi-flash";
+		reg = <0x0 0x0 0x1000000>;
+		bank-width = <2>;
+		device-width = <1>;
+
+		partition@0 {
+			/* This location must not be altered  */
+			/* 256KB for Vitesse 7385 Switch firmware */
+			reg = <0x0 0x00040000>;
+			label = "NOR (RO) Vitesse-7385 Firmware";
+			read-only;
+		};
+
+		partition@40000 {
+			/* 256KB for DTB Image */
+			reg = <0x00040000 0x00040000>;
+			label = "NOR (RO) DTB Image";
+			read-only;
+		};
+
+		partition@80000 {
+			/* 3.5 MB for Linux Kernel Image */
+			reg = <0x00080000 0x00380000>;
+			label = "NOR (RO) Linux Kernel Image";
+			read-only;
+		};
+
+		partition@400000 {
+			/* 11MB for JFFS2 based Root file System */
+			reg = <0x00400000 0x00b00000>;
+			label = "NOR (RW) JFFS2 Root File System";
+		};
+
+		partition@f00000 {
+			/* This location must not be altered  */
+			/* 512KB for u-boot Bootloader Image */
+			/* 512KB for u-boot Environment Variables */
+			reg = <0x00f00000 0x00100000>;
+			label = "NOR (RO) U-Boot Image";
+			read-only;
+		};
+	};
+
+	nand@1,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,p1020-fcm-nand",
+			     "fsl,elbc-fcm-nand";
+		reg = <0x1 0x0 0x40000>;
+
+		partition@0 {
+			/* This location must not be altered  */
+			/* 1MB for u-boot Bootloader Image */
+			reg = <0x0 0x00100000>;
+			label = "NAND (RO) U-Boot Image";
+			read-only;
+		};
+
+		partition@100000 {
+			/* 1MB for DTB Image */
+			reg = <0x00100000 0x00100000>;
+			label = "NAND (RO) DTB Image";
+			read-only;
+		};
+
+		partition@200000 {
+			/* 4MB for Linux Kernel Image */
+			reg = <0x00200000 0x00400000>;
+			label = "NAND (RO) Linux Kernel Image";
+			read-only;
+		};
+
+		partition@600000 {
+			/* 4MB for Compressed Root file System Image */
+			reg = <0x00600000 0x00400000>;
+			label = "NAND (RO) Compressed RFS Image";
+			read-only;
+		};
+
+		partition@a00000 {
+			/* 7MB for JFFS2 based Root file System */
+			reg = <0x00a00000 0x00700000>;
+			label = "NAND (RW) JFFS2 Root File System";
+		};
+
+		partition@1100000 {
+			/* 15MB for JFFS2 based Root file System */
+			reg = <0x01100000 0x00f00000>;
+			label = "NAND (RW) Writable User area";
+		};
+	};
+
+	L2switch@2,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "vitesse-7385";
+		reg = <0x2 0x0 0x20000>;
+	};
+
+	cpld@3,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "cpld";
+		reg = <0x3 0x0 0x20000>;
+		read-only;
+	};
+};
+
+&soc {
+	i2c@3000 {
+		rtc@68 {
+			compatible = "pericom,pt7c4338";
+			reg = <0x68>;
+		};
+	};
+
+	spi@7000 {
+		flash@0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "spansion,s25sl12801";
+			reg = <0>;
+			spi-max-frequency = <40000000>; /* input clock */
+
+			partition@u-boot {
+				/* 512KB for u-boot Bootloader Image */
+				reg = <0x0 0x00080000>;
+				label = "u-boot";
+				read-only;
+			};
+
+			partition@dtb {
+				/* 512KB for DTB Image*/
+				reg = <0x00080000 0x00080000>;
+				label = "dtb";
+				read-only;
+			};
+
+			partition@kernel {
+				/* 4MB for Linux Kernel Image */
+				reg = <0x00100000 0x00400000>;
+				label = "kernel";
+				read-only;
+			};
+
+			partition@fs {
+				/* 4MB for Compressed RFS Image */
+				reg = <0x00500000 0x00400000>;
+				label = "file system";
+				read-only;
+			};
+
+			partition@jffs-fs {
+				/* 7MB for JFFS2 based RFS */
+				reg = <0x00900000 0x00700000>;
+				label = "file system jffs2";
+			};
+		};
+	};
+
+	usb@22000 {
+		phy_type = "ulpi";
+	};
+
+	mdio@24000 {
+		phy0: ethernet-phy@0 {
+			interrupt-parent = <&mpic>;
+			interrupts = <3 1>;
+			reg = <0x0>;
+		};
+
+		phy1: ethernet-phy@1 {
+			interrupt-parent = <&mpic>;
+			interrupts = <2 1>;
+			reg = <0x1>;
+		};
+
+		tbi-phy@2 {
+			device_type = "tbi-phy";
+			reg = <0x2>;
+		};
+
+		tbi0: tbi-phy@11 {
+			reg = <0x11>;
+			device_type = "tbi-phy";
+		};
+
+	};
+
+	mdio@25000 {
+		tbi1: tbi-phy@11 {
+			reg = <0x11>;
+			device_type = "tbi-phy";
+		};
+	};
+
+	enet0: ethernet@b0000 {
+		fixed-link = <1 1 1000 0 0>;
+		phy-connection-type = "rgmii-id";
+
+	};
+
+	enet1: ethernet@b1000 {
+		phy-handle = <&phy0>;
+		tbi-handle = <&tbi1>;
+		phy-connection-type = "sgmii";
+	};
+
+	enet2: ethernet@b2000 {
+		phy-handle = <&phy1>;
+		phy-connection-type = "rgmii-id";
+	};
+};
diff --git a/arch/powerpc/boot/dts/p1020rdb-pc_36b.dts b/arch/powerpc/boot/dts/p1020rdb-pc_36b.dts
new file mode 100644
index 0000000..dfe0ddc
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb-pc_36b.dts
@@ -0,0 +1,67 @@
+/*
+ * P1020 RDB-PC Device Tree Source (36-bit address map)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+	model = "fsl,P1020RDB-PC";
+	compatible = "fsl,P1020RDB-PC";
+
+	memory {
+		device_type = "memory";
+	};
+
+	lbc: localbus@fffe05000 {
+		reg = <0xf 0xffe05000 0 0x1000>;
+
+		/* NOR, NAND Flashes and Vitesse 5 port L2 switch */
+		ranges = <0x0 0x0 0xf 0xef000000 0x01000000
+			  0x1 0x0 0xf 0xff800000 0x00040000
+			  0x2 0x0 0xf 0xffb00000 0x00040000
+			  0x3 0x0 0xf 0xffa00000 0x00020000>;
+	};
+
+	soc: soc@fffe00000 {
+		ranges = <0x0 0xf 0xffe00000 0x100000>;
+	};
+
+	pci0: pcie@fffe09000 {
+		reg = <0xf 0xffe09000 0 0x1000>;
+		ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
+		pcie@0 {
+			ranges = <0x2000000 0x0 0xc0000000
+				  0x2000000 0x0 0xc0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	pci1: pcie@fffe0a000 {
+		reg = <0xf 0xffe0a000 0 0x1000>;
+		ranges = <0x2000000 0x0 0x80000000 0xc 0x00000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
+		pcie@0 {
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+};
+
+/include/ "p1020rdb.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1020rdb-pc_camp_core0.dts b/arch/powerpc/boot/dts/p1020rdb-pc_camp_core0.dts
new file mode 100644
index 0000000..906c932
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb-pc_camp_core0.dts
@@ -0,0 +1,63 @@
+/*
+ * P1020 RDB-PC  Core0 Device Tree Source in CAMP mode.
+ *
+ * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
+ * can be shared, all the other devices must be assigned to one core only.
+ * This dts file allows core0 to have memory, l2, i2c, spi, gpio, tdm, dma, usb,
+ * eth1, eth2, sdhc, crypto, global-util, message, pci0, pci1, msi.
+ *
+ * Please note to add "-b 0" for core0's dts compiling.
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "p1020rdb-pc.dts"
+
+/ {
+	model = "fsl,P1020RDB-PC";
+	compatible = "fsl,P1020RDB-PC", "fsl,MPC85XXRDB-CAMP";
+
+	aliases {
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		serial0 = &serial0;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
+	cpus {
+		PowerPC,P1020@1 {
+			status = "disabled";
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	localbus@ffe05000 {
+		status = "disabled";
+	};
+
+	soc@ffe00000 {
+		serial1: serial@4600 {
+			status = "disabled";
+		};
+
+		enet0: ethernet@b0000 {
+			status = "disabled";
+		};
+
+		mpic: pic@40000 {
+			protected-sources = <
+			42 29 30 34	/* serial1, enet0-queue-group0 */
+			17 18 24 45	/* enet0-queue-group1, crypto */
+			>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p1020rdb-pc_camp_core1.dts b/arch/powerpc/boot/dts/p1020rdb-pc_camp_core1.dts
new file mode 100644
index 0000000..7f7232b
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb-pc_camp_core1.dts
@@ -0,0 +1,141 @@
+/*
+ * P1020 RDB-PC Core1 Device Tree Source in CAMP mode.
+ *
+ * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
+ * can be shared, all the other devices must be assigned to one core only.
+ * This dts allows core1 to have l2, eth0, crypto.
+ *
+ * Please note to add "-b 1" for core1's dts compiling.
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "p1020rdb-pc.dts"
+
+/ {
+	model = "fsl,P1020RDB-PC";
+	compatible = "fsl,P1020RDB-PC", "fsl,MPC85XXRDB-CAMP";
+
+	aliases {
+		ethernet0 = &enet0;
+		serial0 = &serial1;
+		};
+
+	cpus {
+		PowerPC,P1020@0 {
+			status = "disabled";
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	localbus@ffe05000 {
+		status = "disabled";
+	};
+
+	soc@ffe00000 {
+		ecm-law@0 {
+			status = "disabled";
+		};
+
+		ecm@1000 {
+			status = "disabled";
+		};
+
+		memory-controller@2000 {
+			status = "disabled";
+		};
+
+		i2c@3000 {
+			status = "disabled";
+		};
+
+		i2c@3100 {
+			status = "disabled";
+		};
+
+		serial0: serial@4500 {
+			status = "disabled";
+		};
+
+		spi@7000 {
+			status = "disabled";
+		};
+
+		gpio: gpio-controller@f000 {
+			status = "disabled";
+		};
+
+		dma@21300 {
+			status = "disabled";
+		};
+
+		mdio@24000 {
+			status = "disabled";
+		};
+
+		mdio@25000 {
+			status = "disabled";
+		};
+
+		enet1: ethernet@b1000 {
+			status = "disabled";
+		};
+
+		enet2: ethernet@b2000 {
+			status = "disabled";
+		};
+
+		usb@22000 {
+			status = "disabled";
+		};
+
+		sdhci@2e000 {
+			status = "disabled";
+		};
+
+		mpic: pic@40000 {
+			protected-sources = <
+			16 		/* ecm, mem, L2, pci0, pci1 */
+			43 42 59	/* i2c, serial0, spi */
+			47 63 62 	/* gpio, tdm */
+			20 21 22 23	/* dma */
+			03 02 		/* mdio */
+			35 36 40	/* enet1-queue-group0 */
+			51 52 67	/* enet1-queue-group1 */
+			31 32 33	/* enet2-queue-group0 */
+			25 26 27	/* enet2-queue-group1 */
+			28 72 58 	/* usb, sdhci, crypto */
+			0xb0 0xb1 0xb2	/* message */
+			0xb3 0xb4 0xb5
+			0xb6 0xb7
+			0xe0 0xe1 0xe2	/* msi */
+			0xe3 0xe4 0xe5
+			0xe6 0xe7		/* sdhci, crypto , pci */
+			>;
+		};
+
+		msi@41600 {
+			status = "disabled";
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			status = "disabled";
+		};
+	};
+
+	pci0: pcie@ffe09000 {
+		status = "disabled";
+	};
+
+	pci1: pcie@ffe0a000 {
+		status = "disabled";
+	};
+};
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 2/2] P1020RDB-PC: Add p1020rdb-pc platform support
From: Zhicheng Fan @ 2012-01-19  9:06 UTC (permalink / raw)
  To: galak, linuxppc-dev; +Cc: Fanzc
In-Reply-To: <1326964017-615-1-git-send-email-B32736@freescale.com>

From: Fanzc <b32736@freeescale.com>

Signed-off-by: Fanzc <b32736@freeescale.com>
---
 arch/powerpc/platforms/85xx/mpc85xx_rdb.c |   27 ++++++++++++++++++++++++++-
 1 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index ccf520e..0583d38 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -1,7 +1,7 @@
 /*
  * MPC85xx RDB Board Setup
  *
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009,2012 Freescale Semiconductor Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -90,6 +90,7 @@ static void __init mpc85xx_rdb_setup_arch(void)
 
 machine_device_initcall(p2020_rdb, mpc85xx_common_publish_devices);
 machine_device_initcall(p1020_rdb, mpc85xx_common_publish_devices);
+machine_device_initcall(p1020_rdb_pc, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
@@ -112,6 +113,15 @@ static int __init p1020_rdb_probe(void)
 	return 0;
 }
 
+static int __init p1020_rdb_pc_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "fsl,P1020RDB-PC"))
+		return 1;
+	return 0;
+}
+
 define_machine(p2020_rdb) {
 	.name			= "P2020 RDB",
 	.probe			= p2020_rdb_probe,
@@ -139,3 +149,18 @@ define_machine(p1020_rdb) {
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
 };
+
+define_machine(p1020_rdb_pc) {
+	.name			= "P1020RDB-PC",
+	.probe			= p1020_rdb_pc_probe,
+	.setup_arch		= mpc85xx_rdb_setup_arch,
+	.init_IRQ		= mpc85xx_rdb_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
+
-- 
1.7.0.4

^ permalink raw reply related

* Re: Problem with full speed devices on PowerPC MPC5121 host port
From: Anatolij Gustschin @ 2012-01-19  9:34 UTC (permalink / raw)
  To: Matthias Fuchs; +Cc: linuxppc-dev, linux-usb
In-Reply-To: <4F16CC3C.6060005@esd.eu>

Hi Matthias,

On Wed, 18 Jan 2012 14:42:20 +0100
Matthias Fuchs <matthias.fuchs@esd.eu> wrote:
...
> > Can you try the attached patch? Does it have an impact?
> 
> Yes, in deed, it solved my problem :-) Finally I noticed that
> the problem is listed in the CPU's errata document.
> 
> You could update the comment and commit message to "... when there is
> heavy simultaneus PATA write or network activity".
> 
> I vote for getting this mainline.
> 
> Tested-by: Matthias Fuchs <matthias.fuchs@esd.ue>

Thanks for testing! I'll rework to remove ifdef in the patch
and fix commit message and then resubmit.

Anatolij

^ permalink raw reply

* Re: [PATCH] powerpc/booke64: Configurable lazy interrupt disabling
From: Tudor Laurentiu @ 2012-01-19 13:18 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1326921026.26116.34.camel@pasglop>

Hi Ben,

On 01/18/2012 11:10 PM, Benjamin Herrenschmidt wrote:
> On Wed, 2012-01-18 at 16:35 +0200, Laurentiu Tudor wrote:
>> This patch adds a menuconfig option that allows controlling
>> the lazy interrupt disabling feature implemented by this
>> commit:
>>
>> commit d04c56f73c30a5e593202ecfcf25ed43d42363a2
>> Author: Paul Mackerras
>> Date:   Wed Oct 4 16:47:49 2006 +1000
>>
>>      [POWERPC] Lazy interrupt disabling for 64-bit machines
>>
>> The code in 'powerpc/include/asm/hw_irq.h' was rearranged and
>> cleaned-up a bit in order to reduce the number of needed #ifdef's.
>
> It's still nasty.

Yep, there is still room for improvement. Perhaps trimming some of those 
various interrupt enable/disable functions & macros. However I don't 
think I have enough experience to do this ... so, any suggestions are 
welcomed.

> Do you have numbers showing that it's worth disabling
> on BookE ?

On fsl's p5020 there should be some performance gains because disabling 
"lazy ee" allows enabling the "external proxy" feature.
The thing is I can't prove this because I have no idea what benchmark to 
run. Let me know if you guys know of any relevant benchmark I could try.

---
Best Regards, Laurentiu

^ permalink raw reply

* Re: [PATCH] powerpc/booke64: Configurable lazy interrupt disabling
From: Stuart Yoder @ 2012-01-19 19:21 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Laurentiu Tudor, linuxppc-dev
In-Reply-To: <1326921026.26116.34.camel@pasglop>

On Wed, Jan 18, 2012 at 3:10 PM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Wed, 2012-01-18 at 16:35 +0200, Laurentiu Tudor wrote:
>> This patch adds a menuconfig option that allows controlling
>> the lazy interrupt disabling feature implemented by this
>> commit:
>>
>> commit d04c56f73c30a5e593202ecfcf25ed43d42363a2
>> Author: Paul Mackerras
>> Date: =A0 Wed Oct 4 16:47:49 2006 +1000
>>
>> =A0 =A0 [POWERPC] Lazy interrupt disabling for 64-bit machines
>>
>> The code in 'powerpc/include/asm/hw_irq.h' was rearranged and
>> cleaned-up a bit in order to reduce the number of needed #ifdef's.
>
> It's still nasty. Do you have numbers showing that it's worth disabling
> on BookE ?

It's not just about bare metal performance-- some platforms such as
the Freescale
Topaz hypervisor don't provide legacy IACK type interrupt
acknowledgment, and expect
the guest to support the external proxy mechanism.

With Topaz, interrupts go directly to guests and we don't want to require a
trap/hcall to do an IACK, as that adds potentially thousands of cycles of
latency to every interrupt.

As you know, with external proxy interrupts are acknowledged by the
hardware and it becomes problematic to replay the interrupt in
the context of lazy EE when interrupts are re-enabled.   The interrupt
will not fire again when you enable EE.

That is currently the issue, as we can't run the 64-bit kernel on Topaz.
Our option are:
  1) to provide an option to disable lazy EE
  2) do some kind of hack to replay interrupts with lazy EE
  3) change Topaz to support legacy IACK, but this gets ugly for
      various reasons.

Providing a config option to disable lazy EE seemed to be a good
approach.

Stuart

^ permalink raw reply

* Re: [PATCH] powerpc/booke64: Configurable lazy interrupt disabling
From: Stuart Yoder @ 2012-01-19 19:29 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Laurentiu Tudor, linuxppc-dev
In-Reply-To: <CALRxmdC_E4Z==4R_2MGHAi3T7mdF9oHx3rBE6Meb+3R1gWF5VQ@mail.gmail.com>

On Thu, Jan 19, 2012 at 1:21 PM, Stuart Yoder <b08248@gmail.com> wrote:
> On Wed, Jan 18, 2012 at 3:10 PM, Benjamin Herrenschmidt
> <benh@kernel.crashing.org> wrote:
>> On Wed, 2012-01-18 at 16:35 +0200, Laurentiu Tudor wrote:
>>> This patch adds a menuconfig option that allows controlling
>>> the lazy interrupt disabling feature implemented by this
>>> commit:
>>>
>>> commit d04c56f73c30a5e593202ecfcf25ed43d42363a2
>>> Author: Paul Mackerras
>>> Date: =A0 Wed Oct 4 16:47:49 2006 +1000
>>>
>>> =A0 =A0 [POWERPC] Lazy interrupt disabling for 64-bit machines
>>>
>>> The code in 'powerpc/include/asm/hw_irq.h' was rearranged and
>>> cleaned-up a bit in order to reduce the number of needed #ifdef's.
>>
>> It's still nasty. Do you have numbers showing that it's worth disabling
>> on BookE ?
>
> It's not just about bare metal performance-- some platforms such as
> the Freescale
> Topaz hypervisor don't provide legacy IACK type interrupt
> acknowledgment, and expect
> the guest to support the external proxy mechanism.
>
> With Topaz, interrupts go directly to guests and we don't want to require=
 a
> trap/hcall to do an IACK, as that adds potentially thousands of cycles of
> latency to every interrupt.
>
> As you know, with external proxy interrupts are acknowledged by the
> hardware and it becomes problematic to replay the interrupt in
> the context of lazy EE when interrupts are re-enabled. =A0 The interrupt
> will not fire again when you enable EE.
>
> That is currently the issue, as we can't run the 64-bit kernel on Topaz.
> Our option are:
> =A01) to provide an option to disable lazy EE
> =A02) do some kind of hack to replay interrupts with lazy EE
> =A03) change Topaz to support legacy IACK, but this gets ugly for
> =A0 =A0 =A0various reasons.
>
> Providing a config option to disable lazy EE seemed to be a good
> approach.

Also, Scott had posted an approach to do option #2 a while back,
but as I  recall there was some negative feedback about this.  See:
<http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-August/092103.html>

Stuart

^ permalink raw reply

* ata/ide driver for MPC512x
From: Matthias Fuchs @ 2012-01-19 21:28 UTC (permalink / raw)
  To: linuxppc-dev

Hi,

do we have an ata/ide driver for MPC512x internal ATA controller?
So something that is compatible to "fsl,mpc5121-pata"?

Matthias

^ permalink raw reply

* [PATCH] powerpc/85xx: fix Kconfig warning about missing 8250 dependency
From: Paul Gortmaker @ 2012-01-20  1:23 UTC (permalink / raw)
  To: galak, benh, paulus; +Cc: Paul Gortmaker, linuxppc-dev

The SERIAL_8250_EXTENDED option just enables access to other
less regularly used options, like SERIAL_8250_SHARE_IRQ.
Select it to get rid of this warning when selecting the child
option living underneath it.

  warning: (FSL_SOC_BOOKE && SERIAL_8250_RM9K) selects
  SERIAL_8250_SHARE_IRQ which has unmet direct dependencies
  (HAS_IOMEM && SERIAL_8250_EXTENDED)

Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>

diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index d7946be..b221236 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -6,6 +6,7 @@ menuconfig FSL_SOC_BOOKE
 	select MPIC
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
+	select SERIAL_8250_EXTENDED if SERIAL_8250
 	select SERIAL_8250_SHARE_IRQ if SERIAL_8250
 	default y
 
-- 
1.7.7.2

^ permalink raw reply related

* [PATCH V2] fsl-sata: I/O load balancing
From: qiang.liu @ 2012-01-20  2:19 UTC (permalink / raw)
  To: jgarzik, linux-ide; +Cc: Qiang Liu, linuxppc-dev, linux-kernel

From: Qiang Liu <qiang.liu@freescale.com>

Reduce interrupt signals through reset Interrupt Coalescing Control Reg.
Provide dynamic method to adjust interrupt signals and timer ticks by sysfs.
It is a tradeoff for different applications.

Signed-off-by: Qiang Liu <qiang.liu@freescale.com>
---

change for V2
	support dynamic config interrupt coalescing register by /sysfs
	test random small file with iometer
Description:
  1. fsl-sata interrupt will be raised 130 thousand times when write 8G file
    (dd if=/dev/zero of=/dev/sda2 bs=128K count=65536);
  2. most of interrupts raised because of only 1-4 commands completed;
  3. only 30 thousand times will be raised after set max interrupt threshold,
    more interrupts are coalesced as the description of ICC;

Test methods and results:
  1. test sequential large file performance,
  [root@p2020ds root]# echo 31 524287 > \
  	/sys/devices/soc.0/ffe18000.sata/intr_coalescing
  [root@p2020ds root]# dd if=/dev/zero of=/dev/sda2 bs=128K count=65536 &
  [root@p2020ds root]# top

  CPU %  |  dd   |  flush-8:0 | softirq
  ---------------------------------------
  before | 20-22 |    17-19   |    7
  ---------------------------------------
  after  | 18-21 |    15-16   |    5
  ---------------------------------------
  2. test random small file with iometer,
 iometer paramters:
   4 I/Os burst length, 1MB transfer request size, 100% write, 2MB file size
   as default configuration of interrupt coalescing register, 1 interrupts and
 no timeout config, total write performance is 119MB per second,
   after config with the maximum value, write performance is 110MB per second.

  After compare the test results, a configuable interrupt coalescing should be
  better when cope with flexible context.

 drivers/ata/sata_fsl.c |  111 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 107 insertions(+), 4 deletions(-)

diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 3547000..41ca495 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -6,7 +6,7 @@
  * Author: Ashish Kalra <ashish.kalra@freescale.com>
  * Li Yang <leoli@freescale.com>
  *
- * Copyright (c) 2006-2007, 2011 Freescale Semiconductor, Inc.
+ * Copyright (c) 2006-2007, 2011-2012 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -26,6 +26,15 @@
 #include <asm/io.h>
 #include <linux/of_platform.h>

+static unsigned int intr_coalescing_count;
+module_param(intr_coalescing_count, int, S_IRUGO);
+MODULE_PARM_DESC(intr_coalescing_count,
+				 "INT coalescing count threshold (1..31)");
+
+static unsigned int intr_coalescing_ticks;
+module_param(intr_coalescing_ticks, int, S_IRUGO);
+MODULE_PARM_DESC(intr_coalescing_ticks,
+				 "INT coalescing timer threshold in AHB ticks");
 /* Controller information */
 enum {
 	SATA_FSL_QUEUE_DEPTH	= 16,
@@ -83,6 +92,16 @@ enum {
 };

 /*
+ * Interrupt Coalescing Control Register bitdefs  */
+enum {
+	ICC_MIN_INT_COUNT_THRESHOLD	= 1,
+	ICC_MAX_INT_COUNT_THRESHOLD	= ((1 << 5) - 1),
+	ICC_MIN_INT_TICKS_THRESHOLD	= 0,
+	ICC_MAX_INT_TICKS_THRESHOLD	= ((1 << 19) - 1),
+	ICC_SAFE_INT_TICKS		= 1,
+};
+
+/*
 * Host Controller command register set - per port
 */
 enum {
@@ -263,9 +282,66 @@ struct sata_fsl_host_priv {
 	int irq;
 	int data_snoop;
 	u32 quirks;
+	struct device_attribute intr_coalescing;
 #define SATA_FSL_QUIRK_P3P5_ERRATA	(1 << 0)
 };

+static void fsl_sata_set_irq_coalescing(struct ata_host *host,
+		unsigned int count, unsigned int ticks)
+{
+	struct sata_fsl_host_priv *host_priv = host->private_data;
+	void __iomem *hcr_base = host_priv->hcr_base;
+
+	if (count > ICC_MAX_INT_COUNT_THRESHOLD)
+		count = ICC_MAX_INT_COUNT_THRESHOLD;
+	else if (count < ICC_MIN_INT_COUNT_THRESHOLD)
+		count = ICC_MIN_INT_COUNT_THRESHOLD;
+
+	if (ticks > ICC_MAX_INT_TICKS_THRESHOLD)
+		ticks = ICC_MAX_INT_TICKS_THRESHOLD;
+	else if ((ICC_MIN_INT_TICKS_THRESHOLD == ticks) &&
+			(count > ICC_MIN_INT_COUNT_THRESHOLD))
+		ticks = ICC_SAFE_INT_TICKS;
+
+	spin_lock(&host->lock);
+	iowrite32((count << 24 | ticks), hcr_base + ICC);
+
+	intr_coalescing_count = count;
+	intr_coalescing_ticks = ticks;
+	spin_unlock(&host->lock);
+
+	DPRINTK("intrrupt coalescing, count = 0x%x, ticks = %x\n",
+			intr_coalescing_count, intr_coalescing_ticks);
+	DPRINTK("ICC register status: (hcr base: 0x%x) = 0x%x\n",
+			hcr_base, ioread32(hcr_base + ICC));
+}
+
+static ssize_t fsl_sata_intr_coalescing_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d	%d\n",
+			intr_coalescing_count, intr_coalescing_ticks);
+}
+
+static ssize_t fsl_sata_intr_coalescing_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	unsigned int coalescing_count,	coalescing_ticks;
+
+	if (sscanf(buf, "%d%d",
+				&coalescing_count,
+				&coalescing_ticks) != 2) {
+		printk(KERN_ERR "fsl-sata: wrong parameter format.\n");
+		return -EINVAL;
+	}
+
+	fsl_sata_set_irq_coalescing(dev_get_drvdata(dev),
+			coalescing_count, coalescing_ticks);
+
+	return strlen(buf);
+}
+
 static void sata_fsl_dev_config(struct ata_device *dev)
 {
 		dev->max_sectors = 16;
@@ -352,11 +428,11 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
 			(unsigned long long)sg_addr, sg_len);

 		/* warn if each s/g element is not dword aligned */
-		if (sg_addr & 0x03)
+		if (unlikely(sg_addr & 0x03))
 			ata_port_printk(qc->ap, KERN_ERR,
 					"s/g addr unaligned : 0x%llx\n",
 					(unsigned long long)sg_addr);
-		if (sg_len & 0x03)
+		if (unlikely(sg_len & 0x03))
 			ata_port_printk(qc->ap, KERN_ERR,
 					"s/g len unaligned : 0x%x\n", sg_len);

@@ -1305,6 +1381,13 @@ static int sata_fsl_init_controller(struct ata_host *host)
 	iowrite32(0x00000FFFF, hcr_base + DE);

 	/*
+	 * reset the number of command complete bits which will cause the
+	 * interrupt to be signaled
+	 */
+	fsl_sata_set_irq_coalescing(host, intr_coalescing_count,
+			intr_coalescing_ticks);
+
+	/*
 	 * host controller will be brought on-line, during xx_port_start()
 	 * callback, that should also initiate the OOB, COMINIT sequence
 	 */
@@ -1368,7 +1451,7 @@ static int sata_fsl_probe(struct platform_device *ofdev)
 	void __iomem *csr_base = NULL;
 	struct sata_fsl_host_priv *host_priv = NULL;
 	int irq;
-	struct ata_host *host;
+	struct ata_host *host = NULL;
 	u32 temp;

 	struct ata_port_info pi = sata_fsl_port_info[0];
@@ -1430,6 +1513,10 @@ static int sata_fsl_probe(struct platform_device *ofdev)

 	/* allocate host structure */
 	host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS);
+	if (!host) {
+		retval = -ENOMEM;
+		goto error_exit_with_cleanup;
+	}

 	/* host->iomap is not used currently */
 	host->private_data = host_priv;
@@ -1447,10 +1534,24 @@ static int sata_fsl_probe(struct platform_device *ofdev)

 	dev_set_drvdata(&ofdev->dev, host);

+	host_priv->intr_coalescing.show = fsl_sata_intr_coalescing_show;
+	host_priv->intr_coalescing.store = fsl_sata_intr_coalescing_store;
+	sysfs_attr_init(&host_priv->intr_coalescing.attr);
+	host_priv->intr_coalescing.attr.name = "intr_coalescing";
+	host_priv->intr_coalescing.attr.mode = S_IRUGO | S_IWUSR;
+	retval = device_create_file(host->dev, &host_priv->intr_coalescing);
+	if (retval)
+		goto error_exit_with_cleanup;
+
 	return 0;

 error_exit_with_cleanup:

+	if (host) {
+		dev_set_drvdata(&ofdev->dev, NULL);
+		ata_host_detach(host);
+	}
+
 	if (hcr_base)
 		iounmap(hcr_base);
 	if (host_priv)
@@ -1464,6 +1565,8 @@ static int sata_fsl_remove(struct platform_device *ofdev)
 	struct ata_host *host = dev_get_drvdata(&ofdev->dev);
 	struct sata_fsl_host_priv *host_priv = host->private_data;

+	device_remove_file(&ofdev->dev, &host_priv->intr_coalescing);
+
 	ata_host_detach(host);

 	dev_set_drvdata(&ofdev->dev, NULL);
--
1.7.5.1

^ permalink raw reply related

* [PATCH 2/2] powerpc: Abstract common define of signal multiplex control for qe
From: Zhicheng Fan @ 2012-01-20  5:00 UTC (permalink / raw)
  To: galak, linuxppc-dev; +Cc: Fanzc
In-Reply-To: <1327035611-22794-1-git-send-email-B32736@freescale.com>

From: Fanzc <b32736@freeescale.com>

The mpc85xx_rdb and mpc85xx_mds have commom define of signal multiplex for qe ,so
they need to go in common header, the patch abstract them to fsl_guts.h

Signed-off-by: Fanzc <b32736@freeescale.com>
---
 arch/powerpc/include/asm/fsl_guts.h       |   19 +++++++++++++++++++
 arch/powerpc/platforms/85xx/mpc85xx_mds.c |    7 ++-----
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index bebd124..efacfe3 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -114,6 +114,25 @@ struct ccsr_guts_86xx {
 	__be32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
 } __attribute__ ((packed));
 
+#ifdef CONFIG_PPC_85xx
+
+/* Alternate function signal multiplex control */
+#define MPC85xx_PMUXCR_OFFSET           0x60
+#define MPC85xx_PMUXCR_QE0              0x00008000
+#define MPC85xx_PMUXCR_QE2              0x00002000
+#define MPC85xx_PMUXCR_QE3              0x00001000
+#define MPC85xx_PMUXCR_QE4              0x00000800
+#define MPC85xx_PMUXCR_QE5              0x00000400
+#define MPC85xx_PMUXCR_QE6              0x00000200
+#define MPC85xx_PMUXCR_QE7              0x00000100
+#define MPC85xx_PMUXCR_QE8              0x00000080
+#define MPC85xx_PMUXCR_QE9              0x00000040
+#define MPC85xx_PMUXCR_QE10             0x00000020
+#define MPC85xx_PMUXCR_QE11             0x00000010
+#define MPC85xx_PMUXCR_QE12             0x00000008
+
+#endif
+
 #ifdef CONFIG_PPC_86xx
 
 #define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 1d15a0c..1bd339a 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -51,6 +51,7 @@
 #include <asm/qe_ic.h>
 #include <asm/mpic.h>
 #include <asm/swiotlb.h>
+#include <asm/fsl_guts.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
@@ -268,11 +269,7 @@ static void __init mpc85xx_mds_qe_init(void)
 	mpc85xx_mds_reset_ucc_phys();
 
 	if (machine_is(p1021_mds)) {
-#define MPC85xx_PMUXCR_OFFSET           0x60
-#define MPC85xx_PMUXCR_QE0              0x00008000
-#define MPC85xx_PMUXCR_QE3              0x00001000
-#define MPC85xx_PMUXCR_QE9              0x00000040
-#define MPC85xx_PMUXCR_QE12             0x00000008
+
 		static __be32 __iomem *pmuxcr;
 
 		np = of_find_node_by_name(NULL, "global-utilities");
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 1/2] P1025RDB: add Quicc Engine support
From: Zhicheng Fan @ 2012-01-20  5:00 UTC (permalink / raw)
  To: galak, linuxppc-dev; +Cc: Fanzc

From: Fanzc <b32736@freeescale.com>

Signed-off-by: Fanzc <b32736@freeescale.com>
---
 arch/powerpc/platforms/85xx/mpc85xx_rdb.c |   79 ++++++++++++++++++++++++++++-
 1 files changed, 78 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 1950076..1ba67aa 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -26,6 +26,9 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <asm/mpic.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
@@ -47,6 +50,10 @@ void __init mpc85xx_rdb_pic_init(void)
 	struct mpic *mpic;
 	unsigned long root = of_get_flat_dt_root();
 
+#ifdef CONFIG_QUICC_ENGINE
+	struct device_node *np;
+#endif
+
 	if (of_flat_dt_is_compatible(root, "fsl,MPC85XXRDB-CAMP")) {
 		mpic = mpic_alloc(NULL, 0,
 			MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
@@ -62,6 +69,18 @@ void __init mpc85xx_rdb_pic_init(void)
 
 	BUG_ON(mpic == NULL);
 	mpic_init(mpic);
+
+#ifdef CONFIG_QUICC_ENGINE
+	np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
+	if (np) {
+		qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
+				qe_ic_cascade_high_mpic);
+		of_node_put(np);
+
+	} else
+		printk(KERN_ERR "Could not find qe-ic node\n");
+#endif
+
 }
 
 /*
@@ -69,7 +88,7 @@ void __init mpc85xx_rdb_pic_init(void)
  */
 static void __init mpc85xx_rdb_setup_arch(void)
 {
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
 	struct device_node *np;
 #endif
 
@@ -85,6 +104,64 @@ static void __init mpc85xx_rdb_setup_arch(void)
 #endif
 
 	mpc85xx_smp_init();
+
+#ifdef CONFIG_QUICC_ENGINE
+	np = of_find_compatible_node(NULL, NULL, "fsl,qe");
+	if (!np) {
+		printk(KERN_ERR "Could not find Quicc Engine node\n");
+		goto qe_fail;
+	}
+
+	qe_reset();
+	of_node_put(np);
+
+	np = of_find_node_by_name(NULL, "par_io");
+	if (np) {
+		struct device_node *ucc;
+
+		par_io_init(np);
+		of_node_put(np);
+
+		for_each_node_by_name(ucc, "ucc")
+			par_io_of_config(ucc);
+
+	}
+	if (machine_is(p1025_rdb)) {
+
+		__be32 __iomem *pmuxcr;
+
+		np = of_find_node_by_name(NULL, "global-utilities");
+
+		if (np) {
+			pmuxcr = of_iomap(np, 0) + MPC85xx_PMUXCR_OFFSET;
+
+			if (!pmuxcr)
+				pr_err(KERN_EMERG "Error: Alternate function"
+					" signal multiplex control register not"
+					" mapped!\n");
+			else {
+#if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE)
+			/* P1025 has pins muxed for QE and other functions. To
+			* enable QE UEC mode, we need to set bit QE0 for UCC1
+			* in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
+			* and QE12 for QE MII management singals in PMUXCR
+			* register.
+			*/
+				setbits32(pmuxcr, MPC85xx_PMUXCR_QE0 |
+						MPC85xx_PMUXCR_QE3 |
+						MPC85xx_PMUXCR_QE9 |
+						MPC85xx_PMUXCR_QE12);
+#endif
+			}
+
+			of_node_put(np);
+		}
+
+	}
+
+qe_fail:
+#endif	/* CONFIG_QUICC_ENGINE */
+
 	printk(KERN_INFO "MPC85xx RDB board from Freescale Semiconductor\n");
 }
 
-- 
1.7.0.4

^ permalink raw reply related

* linux-next: build failure after merge of the final tree
From: Stephen Rothwell @ 2012-01-20  7:21 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev
  Cc: Deepthi Dharwar, Arun R Bharadwaj, linux-next, linux-kernel,
	Trinabh Gupta

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

Hi all,

After merging the final tree, today's linux-next build (powerpc
allmodconfig) failed like this:

arch/powerpc/platforms/pseries/processor_idle.c:35:6: error: redefinition of 'update_smt_snooze_delay'
arch/powerpc/include/asm/system.h:230:20: note: previous definition of 'update_smt_snooze_delay' was here
arch/powerpc/platforms/pseries/processor_idle.c:175:5: error: redefinition of 'pseries_notify_cpuidle_add_cpu'
arch/powerpc/include/asm/system.h:231:19: note: previous definition of 'pseries_notify_cpuidle_add_cpu' was here

Caused by commit 707827f3387d ("powerpc/cpuidle: cpuidle driver for
pSeries").  For this build, CONFIG_PSERIES_IDLE is "m".

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: linux-next: build failure after merge of the final tree
From: Deepthi Dharwar @ 2012-01-20  9:08 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: Trinabh Gupta, Arun R Bharadwaj, linux-kernel, linux-next,
	Paul Mackerras, linuxppc-dev
In-Reply-To: <20120120182117.01a6eb5d3cfb3f2bdfb32ae4@canb.auug.org.au>

On 01/20/2012 12:51 PM, Stephen Rothwell wrote:

> Hi all,
> 
> After merging the final tree, today's linux-next build (powerpc
> allmodconfig) failed like this:
> 
> arch/powerpc/platforms/pseries/processor_idle.c:35:6: error: redefinition of 'update_smt_snooze_delay'
> arch/powerpc/include/asm/system.h:230:20: note: previous definition of 'update_smt_snooze_delay' was here
> arch/powerpc/platforms/pseries/processor_idle.c:175:5: error: redefinition of 'pseries_notify_cpuidle_add_cpu'
> arch/powerpc/include/asm/system.h:231:19: note: previous definition of 'pseries_notify_cpuidle_add_cpu' was here
> 
> Caused by commit 707827f3387d ("powerpc/cpuidle: cpuidle driver for
> pSeries").  For this build, CONFIG_PSERIES_IDLE is "m".
> 
> 
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev




Hi Stephen,

We had a discussion on this particular problem on ppcdev list a few
days back and concluded that it is best not have pseries_idle
as a module.

http://old.nabble.com/-PATCH--cpuidle%3A-Default-y-for-pseries-to33118294.html#a33127587

The following patch disables pseries cpuidle driver to be loaded as a
module as there are build problems reported when one is trying to do so.

arch/powerpc/platforms/pseries/processor_idle.c:35:6: error:
redefinition of 'update_smt_snooze_delay'
arch/powerpc/include/asm/system.h:230:20: note:
previous definition of 'update_smt_snooze_delay' was here
arch/powerpc/platforms/pseries/processor_idle.c:175:5:
error: redefinition of 'pseries_notify_cpuidle_add_cpu'
arch/powerpc/include/asm/system.h:231:19: note:
previous definition of 'pseries_notify_cpuidle_add_cpu' was here

Since the above two functions
are used in core power architecture functions (store_smt_snooze_delay
at kernel/sysfs.c and smp_xics_setup_cpu at platforms/pseries/smp.c),
this requires some rework in these interactions. For now please
disable PSERIES_IDLE to be built as a module for now.

Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/pseries/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/Kconfig
b/arch/powerpc/platforms/pseries/Kconfig
index ae7b6d4..31f22c1 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -122,7 +122,7 @@ config DTL
 	  Say N if you are unsure.

 config PSERIES_IDLE
-	tristate "Cpuidle driver for pSeries platforms"
+	bool "Cpuidle driver for pSeries platforms"
 	depends on CPU_IDLE
 	depends on PPC_PSERIES
 	default y

Regards,
Deepthi

^ permalink raw reply related

* [PATCH][v3] NAND Machine support for Integrated Flash Controller
From: Prabhakar Kushwaha @ 2012-01-20 12:52 UTC (permalink / raw)
  To: linuxppc-dev, linux-mtd
  Cc: Poonam Aggrwal, Liu Shuo, Scott Wood, Dipen Dudhat,
	Prabhakar Kushwaha

Integrated Flash Controller(IFC) can be used to hook NAND Flash
chips using NAND Flash Machine available on it.

Signed-off-by: Dipen Dudhat <Dipen.Dudhat@freescale.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Liu Shuo <b35362@freescale.com>
Signed-off-by: Poonam Aggrwal <poonam.aggrwal@freescale.com>
Signed-off-by: Prabhakar Kushwaha <prabhakar@freescale.com>
---
 Based upon git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git (branch next)

 Tested on P1010RDB

 Changes for v2: Ported IFC driver for linux-3.2.0-rc3 
	- Use chip->bbt_options for BBT
	- Use mtd_device_parse_register instead of old parse_mtd_partitions

  Changes for v3: Squashed following patch to make singe NAND driver patch
	- mtd/nand:Fix wrong usage of is_blank() in fsl_ifc_run_command
		http://patchwork.ozlabs.org/patch/136547/
	- mtd/nand: Fix IFC driver to support 2K NAND page
		http://patchwork.ozlabs.org/patch/135010/

 drivers/mtd/nand/Kconfig        |   10 +
 drivers/mtd/nand/Makefile       |    1 +
 drivers/mtd/nand/fsl_ifc_nand.c | 1071 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 1082 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/fsl_ifc_nand.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index cce7b70..2fff5c7 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -463,6 +463,16 @@ config MTD_NAND_FSL_ELBC
 	  Enabling this option will enable you to use this to control
 	  external NAND devices.
 
+config MTD_NAND_FSL_IFC
+	tristate "NAND support for Freescale IFC controller"
+	depends on MTD_NAND && FSL_SOC
+	select FSL_IFC
+	help
+	  Various Freescale chips e.g P1010, include a NAND Flash machine
+	  with built-in hardware ECC capabilities.
+	  Enabling this option will enable you to use this to control
+	  external NAND devices.
+
 config MTD_NAND_FSL_UPM
 	tristate "Support for NAND on Freescale UPM"
 	depends on PPC_83xx || PPC_85xx
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 618f4ba..19bc8cb 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_MTD_ALAUDA)		+= alauda.o
 obj-$(CONFIG_MTD_NAND_PASEMI)		+= pasemi_nand.o
 obj-$(CONFIG_MTD_NAND_ORION)		+= orion_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_ELBC)		+= fsl_elbc_nand.o
+obj-$(CONFIG_MTD_NAND_FSL_IFC)		+= fsl_ifc_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_UPM)		+= fsl_upm.o
 obj-$(CONFIG_MTD_NAND_SH_FLCTL)		+= sh_flctl.o
 obj-$(CONFIG_MTD_NAND_MXC)		+= mxc_nand.o
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
new file mode 100644
index 0000000..33b55d2
--- /dev/null
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -0,0 +1,1071 @@
+/*
+ * Freescale Integrated Flash Controller NAND driver
+ *
+ * Copyright 2011,2012 Freescale Semiconductor, Inc
+ *
+ * Author: Dipen Dudhat <Dipen.Dudhat@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/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand_ecc.h>
+#include <asm/fsl_ifc.h>
+
+#define ERR_BYTE		0xFF /* Value returned for read
+					bytes when read failed	*/
+#define IFC_TIMEOUT_MSECS	500  /* Maximum number of mSecs to wait
+					for IFC NAND Machine	*/
+
+struct fsl_ifc_ctrl;
+
+/* mtd information per set */
+struct fsl_ifc_mtd {
+	struct mtd_info mtd;
+	struct nand_chip chip;
+	struct fsl_ifc_ctrl *ctrl;
+
+	struct device *dev;
+	int bank;		/* Chip select bank number		*/
+	unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */
+	u8 __iomem *vbase;      /* Chip select base virtual address	*/
+};
+
+/* overview of the fsl ifc controller */
+struct fsl_ifc_nand_ctrl {
+	struct nand_hw_control controller;
+	struct fsl_ifc_mtd *chips[FSL_IFC_BANK_COUNT];
+
+	u8 __iomem *addr;	/* Address of assigned IFC 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 oob;	/* Non zero if operating on OOB data	*/
+	unsigned int eccread;	/* Non zero for a full-page ECC read	*/
+	unsigned int counter;	/* counter for the initializations	*/
+};
+
+static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl;
+
+/* 512-byte page with 4-bit ECC, 8-bit */
+static struct nand_ecclayout oob_512_8bit_ecc4 = {
+	.eccbytes = 8,
+	.eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
+	.oobfree = { {0, 5}, {6, 2} },
+};
+
+/* 512-byte page with 4-bit ECC, 16-bit */
+static struct nand_ecclayout oob_512_16bit_ecc4 = {
+	.eccbytes = 8,
+	.eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
+	.oobfree = { {2, 6}, },
+};
+
+/* 2048-byte page size with 4-bit ECC */
+static struct nand_ecclayout oob_2048_ecc4 = {
+	.eccbytes = 32,
+	.eccpos = {
+		8, 9, 10, 11, 12, 13, 14, 15,
+		16, 17, 18, 19, 20, 21, 22, 23,
+		24, 25, 26, 27, 28, 29, 30, 31,
+		32, 33, 34, 35, 36, 37, 38, 39,
+	},
+	.oobfree = { {2, 6}, {40, 24} },
+};
+
+/* 4096-byte page size with 4-bit ECC */
+static struct nand_ecclayout oob_4096_ecc4 = {
+	.eccbytes = 64,
+	.eccpos = {
+		8, 9, 10, 11, 12, 13, 14, 15,
+		16, 17, 18, 19, 20, 21, 22, 23,
+		24, 25, 26, 27, 28, 29, 30, 31,
+		32, 33, 34, 35, 36, 37, 38, 39,
+		40, 41, 42, 43, 44, 45, 46, 47,
+		48, 49, 50, 51, 52, 53, 54, 55,
+		56, 57, 58, 59, 60, 61, 62, 63,
+		64, 65, 66, 67, 68, 69, 70, 71,
+	},
+	.oobfree = { {2, 6}, {72, 56} },
+};
+
+/* 4096-byte page size with 8-bit ECC -- requires 218-byte OOB */
+static struct nand_ecclayout oob_4096_ecc8 = {
+	.eccbytes = 128,
+	.eccpos = {
+		8, 9, 10, 11, 12, 13, 14, 15,
+		16, 17, 18, 19, 20, 21, 22, 23,
+		24, 25, 26, 27, 28, 29, 30, 31,
+		32, 33, 34, 35, 36, 37, 38, 39,
+		40, 41, 42, 43, 44, 45, 46, 47,
+		48, 49, 50, 51, 52, 53, 54, 55,
+		56, 57, 58, 59, 60, 61, 62, 63,
+		64, 65, 66, 67, 68, 69, 70, 71,
+		72, 73, 74, 75, 76, 77, 78, 79,
+		80, 81, 82, 83, 84, 85, 86, 87,
+		88, 89, 90, 91, 92, 93, 94, 95,
+		96, 97, 98, 99, 100, 101, 102, 103,
+		104, 105, 106, 107, 108, 109, 110, 111,
+		112, 113, 114, 115, 116, 117, 118, 119,
+		120, 121, 122, 123, 124, 125, 126, 127,
+		128, 129, 130, 131, 132, 133, 134, 135,
+	},
+	.oobfree = { {2, 6}, {136, 82} },
+};
+
+
+/*
+ * Generic flash bbt descriptors
+ */
+static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
+static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+		   NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	2, /* 0 on 8-bit small page */
+	.len = 4,
+	.veroffs = 6,
+	.maxblocks = 4,
+	.pattern = bbt_pattern,
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+		   NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	2, /* 0 on 8-bit small page */
+	.len = 4,
+	.veroffs = 6,
+	.maxblocks = 4,
+	.pattern = mirror_pattern,
+};
+
+/*
+ * Set up the IFC hardware block and page address fields, and the ifc nand
+ * structure addr field to point to the correct IFC 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_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+	int buf_num;
+
+	ifc_nand_ctrl->page = page_addr;
+	/* Program ROW0/COL0 */
+	out_be32(&ifc->ifc_nand.row0, page_addr);
+	out_be32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column);
+
+	buf_num = page_addr & priv->bufnum_mask;
+
+	ifc_nand_ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2);
+	ifc_nand_ctrl->index = column;
+
+	/* for OOB data point to the second half of the buffer */
+	if (oob)
+		ifc_nand_ctrl->index += mtd->writesize;
+}
+
+static int is_blank(struct mtd_info *mtd, unsigned int bufnum)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
+	u32 __iomem *mainarea = (u32 *)addr;
+	u8 __iomem *oob = addr + mtd->writesize;
+	int i;
+
+	for (i = 0; i < mtd->writesize / 4; i++) {
+		if (__raw_readl(&mainarea[i]) != 0xffffffff)
+			return 0;
+	}
+
+	for (i = 0; i < chip->ecc.layout->eccbytes; i++) {
+		int pos = chip->ecc.layout->eccpos[i];
+
+		if (__raw_readb(&oob[pos]) != 0xff)
+			return 0;
+	}
+
+	return 1;
+}
+
+/* returns nonzero if entire page is blank */
+static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
+			  u32 *eccstat, unsigned int bufnum)
+{
+	u32 reg = eccstat[bufnum / 4];
+	int errors;
+
+	errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
+
+	return errors;
+}
+
+/*
+ * execute IFC NAND command and wait for it to complete
+ */
+static void fsl_ifc_run_command(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+	u32 eccstat[4];
+	int i;
+
+	/* set the chip select for NAND Transaction */
+	out_be32(&ifc->ifc_nand.nand_csel, priv->bank << IFC_NAND_CSEL_SHIFT);
+
+	dev_vdbg(priv->dev,
+			"%s: fir0=%08x fcr0=%08x\n",
+			__func__,
+			in_be32(&ifc->ifc_nand.nand_fir0),
+			in_be32(&ifc->ifc_nand.nand_fcr0));
+
+	ctrl->nand_stat = 0;
+
+	/* start read/write seq */
+	out_be32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
+
+	/* wait for command complete flag or timeout */
+	wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat,
+			   IFC_TIMEOUT_MSECS * HZ/1000);
+
+	if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_FTOER)
+		dev_err(priv->dev, "NAND Flash Timeout Error\n");
+	if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_WPER)
+		dev_err(priv->dev, "NAND Flash Write Protect Error\n");
+
+	if (nctrl->eccread) {
+		int errors;
+		int bufnum = nctrl->page & priv->bufnum_mask;
+		int sector = bufnum * chip->ecc.steps;
+		int sector_end = sector + chip->ecc.steps - 1;
+
+		for (i = sector / 4; i <= sector_end / 4; i++)
+			eccstat[i] = in_be32(&ifc->ifc_nand.nand_eccstat[i]);
+
+		for (i = sector; i <= sector_end; i++) {
+			errors = check_read_ecc(mtd, ctrl, eccstat, i);
+
+			if (errors == 15) {
+				/*
+				 * Uncorrectable error.
+				 * OK only if the whole page is blank.
+				 *
+				 * We disable ECCER reporting due to...
+				 * erratum IFC-A002770 -- so report it now if we
+				 * see an uncorrectable error in ECCSTAT.
+				 */
+				if (!is_blank(mtd, bufnum))
+					ctrl->nand_stat |=
+						IFC_NAND_EVTER_STAT_ECCER;
+				break;
+			}
+
+			mtd->ecc_stats.corrected += errors;
+		}
+
+		nctrl->eccread = 0;
+	}
+}
+
+static void fsl_ifc_do_read(struct nand_chip *chip,
+			    int oob,
+			    struct mtd_info *mtd)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+
+	/* Program FIR/IFC_NAND_FCR0 for Small/Large page */
+	if (mtd->writesize > 512) {
+		out_be32(&ifc->ifc_nand.nand_fir0,
+			 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+			 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
+			 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
+		out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
+
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+			(NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
+			(NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
+	} else {
+		out_be32(&ifc->ifc_nand.nand_fir0,
+			 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			 (IFC_FIR_OP_RA0  << IFC_NAND_FIR0_OP2_SHIFT) |
+			 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
+		out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
+
+		if (oob)
+			out_be32(&ifc->ifc_nand.nand_fcr0,
+				 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
+		else
+			out_be32(&ifc->ifc_nand.nand_fcr0,
+				NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
+	}
+}
+
+/* cmdfunc send commands to the IFC NAND Machine */
+static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
+			     int column, int page_addr) {
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+
+	/* clear the read buffer */
+	ifc_nand_ctrl->read_bytes = 0;
+	if (command != NAND_CMD_PAGEPROG)
+		ifc_nand_ctrl->index = 0;
+
+	switch (command) {
+	/* READ0 read the entire buffer to use hardware ECC. */
+	case NAND_CMD_READ0:
+		out_be32(&ifc->ifc_nand.nand_fbcr, 0);
+		set_addr(mtd, 0, page_addr, 0);
+
+		ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+		ifc_nand_ctrl->index += column;
+
+		if (chip->ecc.mode == NAND_ECC_HW)
+			ifc_nand_ctrl->eccread = 1;
+
+		fsl_ifc_do_read(chip, 0, mtd);
+		fsl_ifc_run_command(mtd);
+		return;
+
+	/* READOOB reads only the OOB because no ECC is performed. */
+	case NAND_CMD_READOOB:
+		out_be32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
+		set_addr(mtd, column, page_addr, 1);
+
+		ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+
+		fsl_ifc_do_read(chip, 1, mtd);
+		fsl_ifc_run_command(mtd);
+
+		return;
+
+	/* READID must read all 8 possible bytes */
+	case NAND_CMD_READID:
+		out_be32(&ifc->ifc_nand.nand_fir0,
+				(IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				(IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
+				(IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+				NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
+		/* 8 bytes for manuf, device and exts */
+		out_be32(&ifc->ifc_nand.nand_fbcr, 8);
+		ifc_nand_ctrl->read_bytes = 8;
+
+		set_addr(mtd, 0, 0, 0);
+		fsl_ifc_run_command(mtd);
+		return;
+
+	/* ERASE1 stores the block and page address */
+	case NAND_CMD_ERASE1:
+		set_addr(mtd, 0, page_addr, 0);
+		return;
+
+	/* ERASE2 uses the block and page address from ERASE1 */
+	case NAND_CMD_ERASE2:
+		out_be32(&ifc->ifc_nand.nand_fir0,
+			 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
+
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+			 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
+			 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
+
+		out_be32(&ifc->ifc_nand.nand_fbcr, 0);
+		ifc_nand_ctrl->read_bytes = 0;
+		fsl_ifc_run_command(mtd);
+		return;
+
+	/* SEQIN sets up the addr buffer and all registers except the length */
+	case NAND_CMD_SEQIN: {
+		u32 nand_fcr0;
+		ifc_nand_ctrl->column = column;
+		ifc_nand_ctrl->oob = 0;
+
+		if (mtd->writesize > 512) {
+			nand_fcr0 =
+				(NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
+				(NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT);
+
+			out_be32(&ifc->ifc_nand.nand_fir0,
+				 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+				 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+				 (IFC_FIR_OP_WBCD  << IFC_NAND_FIR0_OP3_SHIFT) |
+				 (IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT));
+		} else {
+			nand_fcr0 = ((NAND_CMD_PAGEPROG <<
+					IFC_NAND_FCR0_CMD1_SHIFT) |
+				    (NAND_CMD_SEQIN <<
+					IFC_NAND_FCR0_CMD2_SHIFT));
+
+			out_be32(&ifc->ifc_nand.nand_fir0,
+				 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
+				 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+				 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
+				 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
+			out_be32(&ifc->ifc_nand.nand_fir1,
+				 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT));
+
+			if (column >= mtd->writesize)
+				nand_fcr0 |=
+				NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
+			else
+				nand_fcr0 |=
+				NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
+		}
+
+		if (column >= mtd->writesize) {
+			/* OOB area --> READOOB */
+			column -= mtd->writesize;
+			ifc_nand_ctrl->oob = 1;
+		}
+		out_be32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
+		set_addr(mtd, column, page_addr, ifc_nand_ctrl->oob);
+		return;
+	}
+
+	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
+	case NAND_CMD_PAGEPROG: {
+		int full_page;
+		if (ifc_nand_ctrl->oob) {
+			out_be32(&ifc->ifc_nand.nand_fbcr,
+				ifc_nand_ctrl->index - ifc_nand_ctrl->column);
+			full_page = 0;
+		} else {
+			out_be32(&ifc->ifc_nand.nand_fbcr, 0);
+			full_page = 1;
+		}
+
+		fsl_ifc_run_command(mtd);
+		return;
+	}
+
+	case NAND_CMD_STATUS:
+		out_be32(&ifc->ifc_nand.nand_fir0,
+				(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				(IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+				NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
+		out_be32(&ifc->ifc_nand.nand_fbcr, 1);
+		set_addr(mtd, 0, 0, 0);
+		ifc_nand_ctrl->read_bytes = 1;
+
+		fsl_ifc_run_command(mtd);
+
+		/*
+		 * The chip always seems to report that it is
+		 * write-protected, even when it is not.
+		 */
+		setbits8(ifc_nand_ctrl->addr, NAND_STATUS_WP);
+		return;
+
+	case NAND_CMD_RESET:
+		out_be32(&ifc->ifc_nand.nand_fir0,
+				IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+				NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
+		fsl_ifc_run_command(mtd);
+		return;
+
+	default:
+		dev_err(priv->dev, "%s: error, unsupported command 0x%x.\n",
+					__func__, command);
+	}
+}
+
+static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
+{
+	/* The hardware does not seem to support multiple
+	 * chips per bank.
+	 */
+}
+
+/*
+ * Write buf to the IFC NAND Controller Data Buffer
+ */
+static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	unsigned int bufsize = mtd->writesize + mtd->oobsize;
+
+	if (len <= 0) {
+		dev_err(priv->dev, "%s: len %d bytes", __func__, len);
+		return;
+	}
+
+	if ((unsigned int)len > bufsize - ifc_nand_ctrl->index) {
+		dev_err(priv->dev,
+			"%s: beyond end of buffer (%d requested, %u available)\n",
+			__func__, len, bufsize - ifc_nand_ctrl->index);
+		len = bufsize - ifc_nand_ctrl->index;
+	}
+
+	memcpy_toio(&ifc_nand_ctrl->addr[ifc_nand_ctrl->index], buf, len);
+	ifc_nand_ctrl->index += len;
+}
+
+/*
+ * Read a byte from either the IFC hardware buffer
+ * read function for 8-bit buswidth
+ */
+static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+
+	/*
+	 * If there are still bytes in the IFC buffer, then use the
+	 * next byte.
+	 */
+	if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes)
+		return in_8(&ifc_nand_ctrl->addr[ifc_nand_ctrl->index++]);
+
+	dev_err(priv->dev, "%s: beyond end of buffer\n", __func__);
+	return ERR_BYTE;
+}
+
+/*
+ * Read two bytes from the IFC hardware buffer
+ * read function for 16-bit buswith
+ */
+static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	uint16_t data;
+
+	/*
+	 * If there are still bytes in the IFC buffer, then use the
+	 * next byte.
+	 */
+	if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes) {
+		data = in_be16((uint16_t *)&ifc_nand_ctrl->
+					addr[ifc_nand_ctrl->index]);
+		ifc_nand_ctrl->index += 2;
+		return (uint8_t) data;
+	}
+
+	dev_err(priv->dev, "%s: beyond end of buffer\n", __func__);
+	return ERR_BYTE;
+}
+
+/*
+ * Read from the IFC Controller Data Buffer
+ */
+static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	int avail;
+
+	if (len < 0) {
+		dev_err(priv->dev, "%s: len %d bytes", __func__, len);
+		return;
+	}
+
+	avail = min((unsigned int)len,
+			ifc_nand_ctrl->read_bytes - ifc_nand_ctrl->index);
+	memcpy_fromio(buf, &ifc_nand_ctrl->addr[ifc_nand_ctrl->index], avail);
+	ifc_nand_ctrl->index += avail;
+
+	if (len > avail)
+		dev_err(priv->dev,
+			"%s: beyond end of buffer (%d requested, %d available)\n",
+			__func__, len, avail);
+}
+
+/*
+ * Verify buffer against the IFC Controller Data Buffer
+ */
+static int fsl_ifc_verify_buf(struct mtd_info *mtd,
+			       const u_char *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
+	int i;
+
+	if (len < 0) {
+		dev_err(priv->dev, "%s: write_buf of %d bytes", __func__, len);
+		return -EINVAL;
+	}
+
+	if ((unsigned int)len > nctrl->read_bytes - nctrl->index) {
+		dev_err(priv->dev,
+			"%s: beyond end of buffer (%d requested, %u available)\n",
+			__func__, len, nctrl->read_bytes - nctrl->index);
+
+		nctrl->index = nctrl->read_bytes;
+		return -EINVAL;
+	}
+
+	for (i = 0; i < len; i++)
+		if (in_8(&nctrl->addr[nctrl->index + i]) != buf[i])
+			break;
+
+	nctrl->index += len;
+
+	if (i != len)
+		return -EIO;
+	if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * This function is called after Program and Erase Operations to
+ * check for success or failure.
+ */
+static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+	u32 nand_fsr;
+
+	/* Use READ_STATUS command, but wait for the device to be ready */
+	out_be32(&ifc->ifc_nand.nand_fir0,
+		 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+		 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
+	out_be32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
+			IFC_NAND_FCR0_CMD0_SHIFT);
+	out_be32(&ifc->ifc_nand.nand_fbcr, 1);
+	set_addr(mtd, 0, 0, 0);
+	ifc_nand_ctrl->read_bytes = 1;
+
+	fsl_ifc_run_command(mtd);
+
+	nand_fsr = in_be32(&ifc->ifc_nand.nand_fsr);
+
+	/*
+	 * The chip always seems to report that it is
+	 * write-protected, even when it is not.
+	 */
+	return nand_fsr | NAND_STATUS_WP;
+}
+
+static int fsl_ifc_read_page(struct mtd_info *mtd,
+			      struct nand_chip *chip,
+			      uint8_t *buf, int page)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+
+	fsl_ifc_read_buf(mtd, buf, mtd->writesize);
+	fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) {
+		dev_err(priv->dev, "NAND Flash Write Protect Error\n");
+		mtd->ecc_stats.failed++;
+	}
+
+	return 0;
+}
+
+/* ECC will be calculated automatically, and errors will be detected in
+ * waitfunc.
+ */
+static void fsl_ifc_write_page(struct mtd_info *mtd,
+				struct nand_chip *chip,
+				const uint8_t *buf)
+{
+	fsl_ifc_write_buf(mtd, buf, mtd->writesize);
+	fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
+
+static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+
+	dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__,
+							chip->numchips);
+	dev_dbg(priv->dev, "%s: nand->chipsize = %lld\n", __func__,
+							chip->chipsize);
+	dev_dbg(priv->dev, "%s: nand->pagemask = %8x\n", __func__,
+							chip->pagemask);
+	dev_dbg(priv->dev, "%s: nand->chip_delay = %d\n", __func__,
+							chip->chip_delay);
+	dev_dbg(priv->dev, "%s: nand->badblockpos = %d\n", __func__,
+							chip->badblockpos);
+	dev_dbg(priv->dev, "%s: nand->chip_shift = %d\n", __func__,
+							chip->chip_shift);
+	dev_dbg(priv->dev, "%s: nand->page_shift = %d\n", __func__,
+							chip->page_shift);
+	dev_dbg(priv->dev, "%s: nand->phys_erase_shift = %d\n", __func__,
+							chip->phys_erase_shift);
+	dev_dbg(priv->dev, "%s: nand->ecclayout = %p\n", __func__,
+							chip->ecclayout);
+	dev_dbg(priv->dev, "%s: nand->ecc.mode = %d\n", __func__,
+							chip->ecc.mode);
+	dev_dbg(priv->dev, "%s: nand->ecc.steps = %d\n", __func__,
+							chip->ecc.steps);
+	dev_dbg(priv->dev, "%s: nand->ecc.bytes = %d\n", __func__,
+							chip->ecc.bytes);
+	dev_dbg(priv->dev, "%s: nand->ecc.total = %d\n", __func__,
+							chip->ecc.total);
+	dev_dbg(priv->dev, "%s: nand->ecc.layout = %p\n", __func__,
+							chip->ecc.layout);
+	dev_dbg(priv->dev, "%s: mtd->flags = %08x\n", __func__, mtd->flags);
+	dev_dbg(priv->dev, "%s: mtd->size = %lld\n", __func__, mtd->size);
+	dev_dbg(priv->dev, "%s: mtd->erasesize = %d\n", __func__,
+							mtd->erasesize);
+	dev_dbg(priv->dev, "%s: mtd->writesize = %d\n", __func__,
+							mtd->writesize);
+	dev_dbg(priv->dev, "%s: mtd->oobsize = %d\n", __func__,
+							mtd->oobsize);
+
+	return 0;
+}
+
+static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
+{
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+	struct nand_chip *chip = &priv->chip;
+	struct nand_ecclayout *layout;
+	u32 csor;
+
+	/* Fill in fsl_ifc_mtd structure */
+	priv->mtd.priv = chip;
+	priv->mtd.owner = THIS_MODULE;
+
+	/* fill in nand_chip structure */
+	/* set up function call table */
+	if ((in_be32(&ifc->cspr_cs[priv->bank].cspr)) & CSPR_PORT_SIZE_16)
+		chip->read_byte = fsl_ifc_read_byte16;
+	else
+		chip->read_byte = fsl_ifc_read_byte;
+
+	chip->write_buf = fsl_ifc_write_buf;
+	chip->read_buf = fsl_ifc_read_buf;
+	chip->verify_buf = fsl_ifc_verify_buf;
+	chip->select_chip = fsl_ifc_select_chip;
+	chip->cmdfunc = fsl_ifc_cmdfunc;
+	chip->waitfunc = fsl_ifc_wait;
+
+	chip->bbt_td = &bbt_main_descr;
+	chip->bbt_md = &bbt_mirror_descr;
+
+	out_be32(&ifc->ifc_nand.ncfgr, 0x0);
+
+	/* set up nand options */
+	chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR;
+	chip->bbt_options = NAND_BBT_USE_FLASH;
+
+
+	if (in_be32(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) {
+		chip->read_byte = fsl_ifc_read_byte16;
+		chip->options |= NAND_BUSWIDTH_16;
+	} else {
+		chip->read_byte = fsl_ifc_read_byte;
+	}
+
+	chip->controller = &ifc_nand_ctrl->controller;
+	chip->priv = priv;
+
+	chip->ecc.read_page = fsl_ifc_read_page;
+	chip->ecc.write_page = fsl_ifc_write_page;
+
+	csor = in_be32(&ifc->csor_cs[priv->bank].csor);
+
+	/* Hardware generates ECC per 512 Bytes */
+	chip->ecc.size = 512;
+	chip->ecc.bytes = 8;
+
+	switch (csor & CSOR_NAND_PGS_MASK) {
+	case CSOR_NAND_PGS_512:
+		if (chip->options & NAND_BUSWIDTH_16) {
+			layout = &oob_512_16bit_ecc4;
+		} else {
+			layout = &oob_512_8bit_ecc4;
+
+			/* Avoid conflict with bad block marker */
+			bbt_main_descr.offs = 0;
+			bbt_mirror_descr.offs = 0;
+		}
+
+		priv->bufnum_mask = 15;
+		break;
+
+	case CSOR_NAND_PGS_2K:
+		layout = &oob_2048_ecc4;
+		priv->bufnum_mask = 3;
+		break;
+
+	case CSOR_NAND_PGS_4K:
+		if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
+		    CSOR_NAND_ECC_MODE_4) {
+			layout = &oob_4096_ecc4;
+		} else {
+			layout = &oob_4096_ecc8;
+			chip->ecc.bytes = 16;
+		}
+
+		priv->bufnum_mask = 1;
+		break;
+
+	default:
+		dev_err(priv->dev, "bad csor %#x: bad page size\n", csor);
+		return -ENODEV;
+	}
+
+	/* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
+	if (csor & CSOR_NAND_ECC_DEC_EN) {
+		chip->ecc.mode = NAND_ECC_HW;
+		chip->ecc.layout = layout;
+	} else {
+		chip->ecc.mode = NAND_ECC_SOFT;
+	}
+
+	return 0;
+}
+
+static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv)
+{
+	nand_release(&priv->mtd);
+
+	kfree(priv->mtd.name);
+
+	if (priv->vbase)
+		iounmap(priv->vbase);
+
+	ifc_nand_ctrl->chips[priv->bank] = NULL;
+	dev_set_drvdata(priv->dev, NULL);
+	kfree(priv);
+
+	return 0;
+}
+
+static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank,
+		      phys_addr_t addr)
+{
+	u32 cspr = in_be32(&ifc->cspr_cs[bank].cspr);
+
+	if (!(cspr & CSPR_V))
+		return 0;
+	if ((cspr & CSPR_MSEL) != CSPR_MSEL_NAND)
+		return 0;
+
+	return (cspr & CSPR_BA) == convert_ifc_address(addr);
+}
+
+static DEFINE_MUTEX(fsl_ifc_nand_mutex);
+
+static int __devinit fsl_ifc_nand_probe(struct platform_device *dev)
+{
+	struct fsl_ifc_regs __iomem *ifc;
+	struct fsl_ifc_mtd *priv;
+	struct resource res;
+	static const char *part_probe_types[]
+		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
+	int ret;
+	int bank;
+	struct device_node *node = dev->dev.of_node;
+	struct mtd_part_parser_data ppdata;
+
+	ppdata.of_node = dev->dev.of_node;
+	if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs)
+		return -ENODEV;
+	ifc = fsl_ifc_ctrl_dev->regs;
+
+	/* get, allocate and map the memory resource */
+	ret = of_address_to_resource(node, 0, &res);
+	if (ret) {
+		dev_err(&dev->dev, "%s: failed to get resource\n", __func__);
+		return ret;
+	}
+
+	/* find which chip select it is connected to */
+	for (bank = 0; bank < FSL_IFC_BANK_COUNT; bank++) {
+		if (match_bank(ifc, bank, res.start))
+			break;
+	}
+
+	if (bank >= FSL_IFC_BANK_COUNT) {
+		dev_err(&dev->dev, "%s: address did not match any chip selects\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	mutex_lock(&fsl_ifc_nand_mutex);
+	if (!fsl_ifc_ctrl_dev->nand) {
+		ifc_nand_ctrl = kzalloc(sizeof(*ifc_nand_ctrl), GFP_KERNEL);
+		if (!ifc_nand_ctrl) {
+			dev_err(&dev->dev, "failed to allocate memory\n");
+			mutex_unlock(&fsl_ifc_nand_mutex);
+			return -ENOMEM;
+		}
+
+		ifc_nand_ctrl->read_bytes = 0;
+		ifc_nand_ctrl->index = 0;
+		ifc_nand_ctrl->addr = NULL;
+		fsl_ifc_ctrl_dev->nand = ifc_nand_ctrl;
+
+		spin_lock_init(&ifc_nand_ctrl->controller.lock);
+		init_waitqueue_head(&ifc_nand_ctrl->controller.wq);
+	} else {
+		ifc_nand_ctrl = fsl_ifc_ctrl_dev->nand;
+	}
+	mutex_unlock(&fsl_ifc_nand_mutex);
+
+	ifc_nand_ctrl->chips[bank] = priv;
+	priv->bank = bank;
+	priv->ctrl = fsl_ifc_ctrl_dev;
+	priv->dev = &dev->dev;
+
+	priv->vbase = ioremap(res.start, resource_size(&res));
+	if (!priv->vbase) {
+		dev_err(priv->dev, "%s: failed to map chip region\n", __func__);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	dev_set_drvdata(priv->dev, priv);
+
+	out_be32(&ifc->ifc_nand.nand_evter_en,
+			IFC_NAND_EVTER_EN_OPC_EN |
+			IFC_NAND_EVTER_EN_FTOER_EN |
+			IFC_NAND_EVTER_EN_WPER_EN);
+
+	/* enable NAND Machine Interrupts */
+	out_be32(&ifc->ifc_nand.nand_evter_intr_en,
+			IFC_NAND_EVTER_INTR_OPCIR_EN |
+			IFC_NAND_EVTER_INTR_FTOERIR_EN |
+			IFC_NAND_EVTER_INTR_WPERIR_EN);
+
+	priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start);
+	if (!priv->mtd.name) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = fsl_ifc_chip_init(priv);
+	if (ret)
+		goto err;
+
+	ret = nand_scan_ident(&priv->mtd, 1, NULL);
+	if (ret)
+		goto err;
+
+	ret = fsl_ifc_chip_init_tail(&priv->mtd);
+	if (ret)
+		goto err;
+
+	ret = nand_scan_tail(&priv->mtd);
+	if (ret)
+		goto err;
+
+	/* First look for RedBoot table or partitions on the command
+	 * line, these take precedence over device tree information */
+	mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata,
+						NULL, 0);
+
+	dev_info(priv->dev, "IFC NAND device at 0x%llx, bank %d\n",
+		 (unsigned long long)res.start, priv->bank);
+	return 0;
+
+err:
+	fsl_ifc_chip_remove(priv);
+	return ret;
+}
+
+static int fsl_ifc_nand_remove(struct platform_device *dev)
+{
+	struct fsl_ifc_mtd *priv = dev_get_drvdata(&dev->dev);
+
+	fsl_ifc_chip_remove(priv);
+
+	mutex_lock(&fsl_ifc_nand_mutex);
+	ifc_nand_ctrl->counter--;
+	if (!ifc_nand_ctrl->counter) {
+		fsl_ifc_ctrl_dev->nand = NULL;
+		kfree(ifc_nand_ctrl);
+	}
+	mutex_unlock(&fsl_ifc_nand_mutex);
+
+	return 0;
+}
+
+static const struct of_device_id fsl_ifc_nand_match[] = {
+	{
+		.compatible = "fsl,ifc-nand",
+	},
+	{}
+};
+
+static struct platform_driver fsl_ifc_nand_driver = {
+	.driver = {
+		.name	= "fsl,ifc-nand",
+		.owner = THIS_MODULE,
+		.of_match_table = fsl_ifc_nand_match,
+	},
+	.probe       = fsl_ifc_nand_probe,
+	.remove      = fsl_ifc_nand_remove,
+};
+
+static int __init fsl_ifc_nand_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&fsl_ifc_nand_driver);
+	if (ret)
+		printk(KERN_ERR "fsl-ifc: Failed to register platform"
+				"driver\n");
+
+	return ret;
+}
+
+static void __exit fsl_ifc_nand_exit(void)
+{
+	platform_driver_unregister(&fsl_ifc_nand_driver);
+}
+
+module_init(fsl_ifc_nand_init);
+module_exit(fsl_ifc_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale");
+MODULE_DESCRIPTION("Freescale Integrated Flash Controller MTD NAND driver");
-- 
1.7.5.4

^ permalink raw reply related

* Re: Cannot wake-up from standby with MPC8313
From: Scott Wood @ 2012-01-20 20:05 UTC (permalink / raw)
  To: Norbert van Bolhuis; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <4F169BE3.30102@aimvalley.nl>

On 01/18/2012 04:16 AM, Norbert van Bolhuis wrote:
> Yes this is it!
> You mentioned mpc8313erdb bug before, I guess you had to mention it
> twice before
> I looked at mpc8313erdb bug description.
>=20
> The mpc8313erdb bug is described as follows:
>=20
> 3.5 Power management control (PMC) registers cannot be
> accessed?
> The PMC registers range from IMMR + 0x0B00 to IMMR + 0x0BFF. When this
> area is accessed in u-boot,
> the RDB hangs up. It appears that the PMC block is related to the JTAG
> interface; TRST must not be pulled
> down for normal operation of the PMC block. Possible workarounds are as
> follows:
> =95 Attach a debugger to drive TRST high during normal operation.
> =95 Remove the pull-down resistor (R37) for TRST. Although this tested =
on
> some RDBs without any
> problem, it violates the hardware specification. If it does not work on
> your RDB, use another workaround.
>=20
>=20
> I guess this is an MPC8313 problem rather than an MPC8313E-RDB problem =
?
> and I would expect it to be mentioned in MPC8313E Errata (which isn't t=
he
> case).

It is mentioned in the MPC8313E manual (4.2.2 step #10) that TRST must
not be asserted except when PORESET is asserted.  The mpc8313erdb bug
was that the board was not complying with this.

-Scott

^ permalink raw reply

* Re: [PATCH] mtd/nand:Fix wrong usage of is_blank() in fsl_ifc_run_command
From: Scott Wood @ 2012-01-20 20:20 UTC (permalink / raw)
  To: Prabhakar Kushwaha; +Cc: linux-mtd, linuxppc-dev, Poonam Aggrwal
In-Reply-To: <1326859991-7469-1-git-send-email-prabhakar@freescale.com>

On 01/17/2012 10:13 PM, Prabhakar Kushwaha wrote:
> +		for (i = sector; i <= sector_end; i++) {
> +			errors = check_read_ecc(mtd, ctrl, eccstat, i);
> +
> +			if (errors == 15) {
> +				/*
> +				 * Uncorrectable error.
> +				 * OK only if the whole page is blank.
> +				 *
> +				 * We disable ECCER reporting due to...

s/due to.../due to/

Otherwise looks good.

-Scott

^ permalink raw reply

* Re: [PATCH 1/2] P1025RDB: add Quicc Engine support
From: Tabi Timur-B04825 @ 2012-01-20 20:50 UTC (permalink / raw)
  To: Fan Zhicheng-B32736; +Cc: linuxppc-dev@lists.ozlabs.org, Fanzc
In-Reply-To: <1327035611-22794-1-git-send-email-B32736@freescale.com>

On Thu, Jan 19, 2012 at 11:00 PM, Zhicheng Fan <B32736@freescale.com> wrote=
:
> From: Fanzc <b32736@freeescale.com>
>
> Signed-off-by: Fanzc <b32736@freeescale.com>

Please use your full name (first and last name)

> ---
> =A0arch/powerpc/platforms/85xx/mpc85xx_rdb.c | =A0 79 +++++++++++++++++++=
+++++++++-
> =A01 files changed, 78 insertions(+), 1 deletions(-)
>
> diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/pla=
tforms/85xx/mpc85xx_rdb.c
> index 1950076..1ba67aa 100644
> --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
> +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
> @@ -26,6 +26,9 @@
> =A0#include <asm/prom.h>
> =A0#include <asm/udbg.h>
> =A0#include <asm/mpic.h>
> +#include <asm/qe.h>
> +#include <asm/qe_ic.h>
> +#include <asm/fsl_guts.h>
>
> =A0#include <sysdev/fsl_soc.h>
> =A0#include <sysdev/fsl_pci.h>
> @@ -47,6 +50,10 @@ void __init mpc85xx_rdb_pic_init(void)
> =A0 =A0 =A0 =A0struct mpic *mpic;
> =A0 =A0 =A0 =A0unsigned long root =3D of_get_flat_dt_root();
>
> +#ifdef CONFIG_QUICC_ENGINE
> + =A0 =A0 =A0 struct device_node *np;
> +#endif
> +
> =A0 =A0 =A0 =A0if (of_flat_dt_is_compatible(root, "fsl,MPC85XXRDB-CAMP"))=
 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mpic =3D mpic_alloc(NULL, 0,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0MPIC_BIG_ENDIAN | MPIC_BRO=
KEN_FRR_NIRQS |
> @@ -62,6 +69,18 @@ void __init mpc85xx_rdb_pic_init(void)
>
> =A0 =A0 =A0 =A0BUG_ON(mpic =3D=3D NULL);
> =A0 =A0 =A0 =A0mpic_init(mpic);
> +
> +#ifdef CONFIG_QUICC_ENGINE
> + =A0 =A0 =A0 np =3D of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
> + =A0 =A0 =A0 if (np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qe_ic_casca=
de_high_mpic);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put(np);
> +
> + =A0 =A0 =A0 } else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_ERR "Could not find qe-ic node\=
n");

Use pr_err instead of printk(KERN_ERR

> +#endif
> +
> =A0}
>
> =A0/*
> @@ -69,7 +88,7 @@ void __init mpc85xx_rdb_pic_init(void)
> =A0*/
> =A0static void __init mpc85xx_rdb_setup_arch(void)
> =A0{
> -#ifdef CONFIG_PCI
> +#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
> =A0 =A0 =A0 =A0struct device_node *np;
> =A0#endif
>
> @@ -85,6 +104,64 @@ static void __init mpc85xx_rdb_setup_arch(void)
> =A0#endif
>
> =A0 =A0 =A0 =A0mpc85xx_smp_init();
> +
> +#ifdef CONFIG_QUICC_ENGINE
> + =A0 =A0 =A0 np =3D of_find_compatible_node(NULL, NULL, "fsl,qe");
> + =A0 =A0 =A0 if (!np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_ERR "Could not find Quicc Engin=
e node\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto qe_fail;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 qe_reset();
> + =A0 =A0 =A0 of_node_put(np);
> +
> + =A0 =A0 =A0 np =3D of_find_node_by_name(NULL, "par_io");
> + =A0 =A0 =A0 if (np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct device_node *ucc;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 par_io_init(np);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put(np);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 for_each_node_by_name(ucc, "ucc")
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 par_io_of_config(ucc);
> +
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 if (machine_is(p1025_rdb)) {
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 __be32 __iomem *pmuxcr;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 np =3D of_find_node_by_name(NULL, "global-u=
tilities");
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pmuxcr =3D of_iomap(np, 0) =
+ MPC85xx_PMUXCR_OFFSET;

You're missing the iounmap().

--=20
Timur Tabi
Linux kernel developer at Freescale=

^ 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