LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 03/10] 8xx: Tag DAR with 0x00f0 to catch buggy instructions.
From: Joakim Tjernlund @ 2009-11-15 17:09 UTC (permalink / raw)
  To: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1258304977-11760-3-git-send-email-Joakim.Tjernlund@transmode.se>

dcbz, dcbf, dcbi, dcbst and icbi do not set DAR when they
cause a DTLB Error. Dectect this by tagging DAR with 0x00f0
at every exception exit that modifies DAR.
Test for DAR=0x00f0 in DataTLBError and bail
to handle_page_fault().

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
 arch/powerpc/kernel/head_8xx.S |   15 ++++++++++++++-
 1 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 97bd523..a9f1ace 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -206,6 +206,8 @@ MachineCheck:
 	EXCEPTION_PROLOG
 	mfspr r4,SPRN_DAR
 	stw r4,_DAR(r11)
+	li r5,0x00f0
+	mtspr SPRN_DAR,r5	/* Tag DAR, to be used in DTLB Error */
 	mfspr r5,SPRN_DSISR
 	stw r5,_DSISR(r11)
 	addi r3,r1,STACK_FRAME_OVERHEAD
@@ -222,6 +224,8 @@ DataAccess:
 	stw	r10,_DSISR(r11)
 	mr	r5,r10
 	mfspr	r4,SPRN_DAR
+	li	r10,0x00f0
+	mtspr	SPRN_DAR,r10	/* Tag DAR, to be used in DTLB Error */
 	EXC_XFER_EE_LITE(0x300, handle_page_fault)
 
 /* Instruction access exception.
@@ -244,6 +248,8 @@ Alignment:
 	EXCEPTION_PROLOG
 	mfspr	r4,SPRN_DAR
 	stw	r4,_DAR(r11)
+	li	r5,0x00f0
+	mtspr	SPRN_DAR,r5	/* Tag DAR, to be used in DTLB Error */
 	mfspr	r5,SPRN_DSISR
 	stw	r5,_DSISR(r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -445,6 +451,7 @@ DataStoreTLBMiss:
 	 * of the MMU.
 	 */
 2:	li	r11, 0x00f0
+	mtspr	SPRN_DAR,r11	/* Tag DAR */
 	rlwimi	r10, r11, 0, 24, 28	/* Set 24-27, clear 28 */
 	DO_8xx_CPU6(0x3d80, r3)
 	mtspr	SPRN_MD_RPN, r10	/* Update TLB entry */
@@ -485,6 +492,10 @@ DataTLBError:
 	stw	r10, 0(r0)
 	stw	r11, 4(r0)
 
+	mfspr	r10, SPRN_DAR
+	cmpwi	cr0, r10, 0x00f0
+	beq-	2f	/* must be a buggy dcbX, icbi insn. */
+
 	mfspr	r11, SPRN_DSISR
 	andis.	r11, r11, 0x4800	/* !translation or protection */
 	bne	2f	/* branch if either is set */
@@ -508,7 +519,8 @@ DataTLBError:
 	 * are initialized in mapin_ram().  This will avoid the problem,
 	 * assuming we only use the dcbi instruction on kernel addresses.
 	 */
-	mfspr	r10, SPRN_DAR
+
+	/* DAR is in r10 already */
 	rlwinm	r11, r10, 0, 0, 19
 	ori	r11, r11, MD_EVALID
 	mfspr	r10, SPRN_M_CASID
@@ -550,6 +562,7 @@ DataTLBError:
 	 * of the MMU.
 	 */
 	li	r11, 0x00f0
+	mtspr	SPRN_DAR,r11	/* Tag DAR */
 	rlwimi	r10, r11, 0, 24, 28	/* Set 24-27, clear 28 */
 	DO_8xx_CPU6(0x3d80, r3)
 	mtspr	SPRN_MD_RPN, r10	/* Update TLB entry */
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 04/10] 8xx: Always pin kernel instruction TLB
From: Joakim Tjernlund @ 2009-11-15 17:09 UTC (permalink / raw)
  To: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1258304977-11760-4-git-send-email-Joakim.Tjernlund@transmode.se>

Various kernel asm modifies SRR0/SRR1 just before executing
a rfi. If such code crosses a page boundary you risk a TLB miss
which will clobber SRR0/SRR1. Avoid this by always pinning
kernel instruction TLB space.

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
 arch/powerpc/kernel/head_8xx.S |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index a9f1ace..e70503d 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -705,7 +705,7 @@ start_here:
  */
 initial_mmu:
 	tlbia			/* Invalidate all TLB entries */
-#ifdef CONFIG_PIN_TLB
+#if 1 /* CONFIG_PIN_TLB */
 	lis	r8, MI_RSV4I@h
 	ori	r8, r8, 0x1c00
 #else
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 05/10] 8xx: Fixup DAR from buggy dcbX instructions.
From: Joakim Tjernlund @ 2009-11-15 17:09 UTC (permalink / raw)
  To: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1258304977-11760-5-git-send-email-Joakim.Tjernlund@transmode.se>

This is an assembler version to fixup DAR not being set
by dcbX, icbi instructions. There are two versions, one
uses selfmodifing code, the other uses a
jump table but is much bigger(default).

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
 arch/powerpc/kernel/head_8xx.S |  147 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 143 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index e70503d..f74e8a8 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -494,11 +494,16 @@ DataTLBError:
 
 	mfspr	r10, SPRN_DAR
 	cmpwi	cr0, r10, 0x00f0
-	beq-	2f	/* must be a buggy dcbX, icbi insn. */
-
+	beq-	FixupDAR	/* must be a buggy dcbX, icbi insn. */
+DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR */
 	mfspr	r11, SPRN_DSISR
-	andis.	r11, r11, 0x4800	/* !translation or protection */
-	bne	2f	/* branch if either is set */
+	/* As the DAR fixup may clear store we may have all 3 states zero.
+	 * Make sure only 0x0200(store) falls down into DIRTY handling
+	 */
+	andis.	r11, r11, 0x4a00	/* !translation, protection or store */
+	srwi	r11, r11, 16
+	cmpwi	cr0, r11, 0x0200	/* just store ? */
+	bne	2f
 	/* Only Change bit left now, do it here as it is faster
 	 * than trapping to the C fault handler.
 	*/
@@ -604,6 +609,140 @@ DataTLBError:
 
 	. = 0x2000
 
+/* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions
+ * by decoding the registers used by the dcbx instruction and adding them.
+ * DAR is set to the calculated address and r10 also holds the EA on exit.
+ */
+ /* define if you don't want to use self modifying code */
+#define NO_SELF_MODIFYING_CODE
+FixupDAR:/* Entry point for dcbx workaround. */
+	/* fetch instruction from memory. */
+	mfspr	r10, SPRN_SRR0
+	DO_8xx_CPU6(0x3780, r3)
+	mtspr	SPRN_MD_EPN, r10
+	mfspr	r11, SPRN_M_TWB	/* Get level 1 table entry address */
+	cmplwi	cr0, r11, 0x0800
+	blt-	3f		/* Branch if user space */
+	lis	r11, (swapper_pg_dir-PAGE_OFFSET)@h
+	ori	r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
+	rlwimi	r11, r10, 22, 0xffc
+3:	lwz	r11, 0(r11)	/* Get the level 1 entry */
+	DO_8xx_CPU6(0x3b80, r3)
+	mtspr	SPRN_MD_TWC, r11	/* Load pte table base address */
+	mfspr	r11, SPRN_MD_TWC	/* ....and get the pte address */
+	lwz	r11, 0(r11)	/* Get the pte */
+	/* concat physical page address(r11) and page offset(r10) */
+	rlwimi	r11, r10, 0, 20, 31
+	lwz	r11,0(r11)
+/* Check if it really is a dcbx instruction. */
+/* dcbt and dcbtst does not generate DTLB Misses/Errors,
+ * no need to include them here */
+	srwi	r10, r11, 26	/* check if major OP code is 31 */
+	cmpwi	cr0, r10, 31
+	bne-	141f
+	rlwinm	r10, r11, 0, 21, 30
+	cmpwi	cr0, r10, 2028	/* Is dcbz? */
+	beq+	142f
+	cmpwi	cr0, r10, 940	/* Is dcbi? */
+	beq+	142f
+	cmpwi	cr0, r10, 108	/* Is dcbst? */
+	beq+	144f		/* Fix up store bit! */
+	cmpwi	cr0, r10, 172	/* Is dcbf? */
+	beq+	142f
+	cmpwi	cr0, r10, 1964	/* Is icbi? */
+	beq+	142f
+141:	mfspr	r10, SPRN_DAR	/* r10 must hold DAR at exit */
+	b	DARFixed	/* Nope, go back to normal TLB processing */
+
+144:	mfspr	r10, SPRN_DSISR
+	rlwinm	r10, r10,0,7,5	/* Clear store bit for buggy dcbst insn */
+	mtspr	SPRN_DSISR, r10
+142:	/* continue, it was a dcbx, dcbi instruction. */
+#ifdef CONFIG_8xx_CPU6
+	lwz	r3, 8(r0)	/* restore r3 from memory */
+#endif
+#ifndef NO_SELF_MODIFYING_CODE
+	andis.	r10,r11,0x1f	/* test if reg RA is r0 */
+	li	r10,modified_instr@l
+	dcbtst	r0,r10		/* touch for store */
+	rlwinm	r11,r11,0,0,20	/* Zero lower 10 bits */
+	oris	r11,r11,640	/* Transform instr. to a "add r10,RA,RB" */
+	ori	r11,r11,532
+	stw	r11,0(r10)	/* store add/and instruction */
+	dcbf	0,r10		/* flush new instr. to memory. */
+	icbi	0,r10		/* invalidate instr. cache line */
+	lwz	r11, 4(r0)	/* restore r11 from memory */
+	mfspr	r10, SPRN_M_TW	/* restore r10 from M_TW */
+	isync			/* Wait until new instr is loaded from memory */
+modified_instr:
+	.space	4		/* this is where the add instr. is stored */
+	bne+	143f
+	subf	r10,r0,r10	/* r10=r10-r0, only if reg RA is r0 */
+143:	mtdar	r10		/* store faulting EA in DAR */
+	b	DARFixed	/* Go back to normal TLB handling */
+#else
+	mfctr	r10
+	mtdar	r10			/* save ctr reg in DAR */
+	rlwinm	r10, r11, 24, 24, 28	/* offset into jump table for reg RB */
+	addi	r10, r10, 150f@l	/* add start of table */
+	mtctr	r10			/* load ctr with jump address */
+	xor	r10, r10, r10		/* sum starts at zero */
+	bctr				/* jump into table */
+150:
+	add	r10, r10, r0	;b	151f
+	add	r10, r10, r1	;b	151f
+	add	r10, r10, r2	;b	151f
+	add	r10, r10, r3	;b	151f
+	add	r10, r10, r4	;b	151f
+	add	r10, r10, r5	;b	151f
+	add	r10, r10, r6	;b	151f
+	add	r10, r10, r7	;b	151f
+	add	r10, r10, r8	;b	151f
+	add	r10, r10, r9	;b	151f
+	mtctr	r11	;b	154f	/* r10 needs special handling */
+	mtctr	r11	;b	153f	/* r11 needs special handling */
+	add	r10, r10, r12	;b	151f
+	add	r10, r10, r13	;b	151f
+	add	r10, r10, r14	;b	151f
+	add	r10, r10, r15	;b	151f
+	add	r10, r10, r16	;b	151f
+	add	r10, r10, r17	;b	151f
+	add	r10, r10, r18	;b	151f
+	add	r10, r10, r19	;b	151f
+	add	r10, r10, r20	;b	151f
+	add	r10, r10, r21	;b	151f
+	add	r10, r10, r22	;b	151f
+	add	r10, r10, r23	;b	151f
+	add	r10, r10, r24	;b	151f
+	add	r10, r10, r25	;b	151f
+	add	r10, r10, r26	;b	151f
+	add	r10, r10, r27	;b	151f
+	add	r10, r10, r28	;b	151f
+	add	r10, r10, r29	;b	151f
+	add	r10, r10, r30	;b	151f
+	add	r10, r10, r31
+151:
+	rlwinm. r11,r11,19,24,28	/* offset into jump table for reg RA */
+	beq	152f			/* if reg RA is zero, don't add it */ 
+	addi	r11, r11, 150b@l	/* add start of table */
+	mtctr	r11			/* load ctr with jump address */
+	rlwinm	r11,r11,0,16,10		/* make sure we don't execute this more than once */
+	bctr				/* jump into table */
+152:
+	mfdar	r11
+	mtctr	r11			/* restore ctr reg from DAR */
+	mtdar	r10			/* save fault EA to DAR */
+	b	DARFixed		/* Go back to normal TLB handling */
+
+	/* special handling for r10,r11 since these are modified already */
+153:	lwz	r11, 4(r0)	/* load r11 from memory */
+	b	155f
+154:	mfspr	r11, SPRN_M_TW	/* load r10 from M_TW */
+155:	add	r10, r10, r11	/* add it */
+	mfctr	r11		/* restore r11 */
+	b	151b
+#endif
+
 	.globl	giveup_fpu
 giveup_fpu:
 	blr
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 06/10] 8xx: Add missing Guarded setting in DTLB Error.
From: Joakim Tjernlund @ 2009-11-15 17:09 UTC (permalink / raw)
  To: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1258304977-11760-6-git-send-email-Joakim.Tjernlund@transmode.se>

only DTLB Miss did set this bit, DTLB Error needs too otherwise
the setting is lost when the page becomes dirty.

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
 arch/powerpc/kernel/head_8xx.S |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index f74e8a8..5b1a16d 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -552,9 +552,16 @@ DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR
 	 */
 	ori	r11, r11, 1		/* Set valid bit in physical L2 page */
 	DO_8xx_CPU6(0x3b80, r3)
-	mtspr	SPRN_MD_TWC, r11		/* Load pte table base address */
-	mfspr	r11, SPRN_MD_TWC		/* ....and get the pte address */
-	lwz	r10, 0(r11)		/* Get the pte */
+	mtspr	SPRN_MD_TWC, r11	/* Load pte table base address */
+	mfspr	r10, SPRN_MD_TWC	/* ....and get the pte address */
+	lwz	r10, 0(r10)		/* Get the pte */
+	/* Insert the Guarded flag into the TWC from the Linux PTE.
+	 * It is bit 27 of both the Linux PTE and the TWC
+	 */
+	rlwimi	r11, r10, 0, 27, 27
+	DO_8xx_CPU6(0x3b80, r3)
+	mtspr	SPRN_MD_TWC, r11
+	mfspr	r11, SPRN_MD_TWC	/* get the pte address again */
 
 	ori	r10, r10, _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HWWRITE
 	stw	r10, 0(r11)		/* and update pte in table */
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 07/10] 8xx: Restore _PAGE_WRITETHRU
From: Joakim Tjernlund @ 2009-11-15 17:09 UTC (permalink / raw)
  To: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1258304977-11760-7-git-send-email-Joakim.Tjernlund@transmode.se>

8xx has not had WRITETHRU due to lack of bits in the pte.
After the recent rewrite of the 8xx TLB code, there are
two bits left. Use one of them to WRITETHRU.

Perhaps use the last SW bit to PAGE_SPECIAL or PAGE_FILE?

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
 arch/powerpc/include/asm/pte-8xx.h |    5 +++--
 arch/powerpc/kernel/head_8xx.S     |    8 ++++++++
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h
index 68ba861..d44826e 100644
--- a/arch/powerpc/include/asm/pte-8xx.h
+++ b/arch/powerpc/include/asm/pte-8xx.h
@@ -35,11 +35,12 @@
 #define _PAGE_SPECIAL	0x0008	/* SW entry, forced to 0 by the TLB miss */
 #define _PAGE_DIRTY	0x0100	/* C: page changed */
 
-/* These 3 software bits must be masked out when the entry is loaded
- * into the TLB, 2 SW bits left.
+/* These 4 software bits must be masked out when the entry is loaded
+ * into the TLB, 1 SW bit left(0x0080).
  */
 #define _PAGE_GUARDED	0x0010	/* software: guarded access */
 #define _PAGE_ACCESSED	0x0020	/* software: page referenced */
+#define _PAGE_WRITETHRU	0x0040	/* software: caching is write through */
 
 /* Setting any bits in the nibble with the follow two controls will
  * require a TLB exception handler change.  It is assumed unused bits
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 5b1a16d..90aa39e 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -422,6 +422,10 @@ DataStoreTLBMiss:
 	 * above.
 	 */
 	rlwimi	r11, r10, 0, 27, 27
+	/* Insert the WriteThru flag into the TWC from the Linux PTE.
+	 * It is bit 25 in the Linux PTE and bit 30 in the TWC
+	 */
+	rlwimi	r11, r10, 32-5, 30, 30
 	DO_8xx_CPU6(0x3b80, r3)
 	mtspr	SPRN_MD_TWC, r11
 
@@ -559,6 +563,10 @@ DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR
 	 * It is bit 27 of both the Linux PTE and the TWC
 	 */
 	rlwimi	r11, r10, 0, 27, 27
+	/* Insert the WriteThru flag into the TWC from the Linux PTE.
+	 * It is bit 25 in the Linux PTE and bit 30 in the TWC
+	 */
+	rlwimi	r11, r10, 32-5, 30, 30
 	DO_8xx_CPU6(0x3b80, r3)
 	mtspr	SPRN_MD_TWC, r11
 	mfspr	r11, SPRN_MD_TWC	/* get the pte address again */
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 08/10] 8xx: start using dcbX instructions in various copy routines
From: Joakim Tjernlund @ 2009-11-15 17:09 UTC (permalink / raw)
  To: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1258304977-11760-8-git-send-email-Joakim.Tjernlund@transmode.se>

Now that 8xx can fixup dcbX instructions, start using them
where possible like every other PowerPc arch do.

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
 arch/powerpc/kernel/misc_32.S |   18 ------------------
 arch/powerpc/lib/copy_32.S    |   24 ------------------------
 2 files changed, 0 insertions(+), 42 deletions(-)

diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index da9c0c4..8649f53 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -502,15 +502,7 @@ _GLOBAL(clear_pages)
 	li	r0,PAGE_SIZE/L1_CACHE_BYTES
 	slw	r0,r0,r4
 	mtctr	r0
-#ifdef CONFIG_8xx
-	li	r4, 0
-1:	stw	r4, 0(r3)
-	stw	r4, 4(r3)
-	stw	r4, 8(r3)
-	stw	r4, 12(r3)
-#else
 1:	dcbz	0,r3
-#endif
 	addi	r3,r3,L1_CACHE_BYTES
 	bdnz	1b
 	blr
@@ -535,15 +527,6 @@ _GLOBAL(copy_page)
 	addi	r3,r3,-4
 	addi	r4,r4,-4
 
-#ifdef CONFIG_8xx
-	/* don't use prefetch on 8xx */
-    	li	r0,4096/L1_CACHE_BYTES
-	mtctr	r0
-1:	COPY_16_BYTES
-	bdnz	1b
-	blr
-
-#else	/* not 8xx, we can prefetch */
 	li	r5,4
 
 #if MAX_COPY_PREFETCH > 1
@@ -584,7 +567,6 @@ _GLOBAL(copy_page)
 	li	r0,MAX_COPY_PREFETCH
 	li	r11,4
 	b	2b
-#endif	/* CONFIG_8xx */
 
 /*
  * void atomic_clear_mask(atomic_t mask, atomic_t *addr)
diff --git a/arch/powerpc/lib/copy_32.S b/arch/powerpc/lib/copy_32.S
index c657de5..74a7f41 100644
--- a/arch/powerpc/lib/copy_32.S
+++ b/arch/powerpc/lib/copy_32.S
@@ -98,20 +98,7 @@ _GLOBAL(cacheable_memzero)
 	bdnz	4b
 3:	mtctr	r9
 	li	r7,4
-#if !defined(CONFIG_8xx)
 10:	dcbz	r7,r6
-#else
-10:	stw	r4, 4(r6)
-	stw	r4, 8(r6)
-	stw	r4, 12(r6)
-	stw	r4, 16(r6)
-#if CACHE_LINE_SIZE >= 32
-	stw	r4, 20(r6)
-	stw	r4, 24(r6)
-	stw	r4, 28(r6)
-	stw	r4, 32(r6)
-#endif /* CACHE_LINE_SIZE */
-#endif
 	addi	r6,r6,CACHELINE_BYTES
 	bdnz	10b
 	clrlwi	r5,r8,32-LG_CACHELINE_BYTES
@@ -200,9 +187,7 @@ _GLOBAL(cacheable_memcpy)
 	mtctr	r0
 	beq	63f
 53:
-#if !defined(CONFIG_8xx)
 	dcbz	r11,r6
-#endif
 	COPY_16_BYTES
 #if L1_CACHE_BYTES >= 32
 	COPY_16_BYTES
@@ -356,14 +341,6 @@ _GLOBAL(__copy_tofrom_user)
 	li	r11,4
 	beq	63f
 
-#ifdef CONFIG_8xx
-	/* Don't use prefetch on 8xx */
-	mtctr	r0
-	li	r0,0
-53:	COPY_16_BYTES_WITHEX(0)
-	bdnz	53b
-
-#else /* not CONFIG_8xx */
 	/* Here we decide how far ahead to prefetch the source */
 	li	r3,4
 	cmpwi	r0,1
@@ -416,7 +393,6 @@ _GLOBAL(__copy_tofrom_user)
 	li	r3,4
 	li	r7,0
 	bne	114b
-#endif /* CONFIG_8xx */
 
 63:	srwi.	r0,r5,2
 	mtctr	r0
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 09/10] 8xx: Remove DIRTY pte handling in DTLB Error.
From: Joakim Tjernlund @ 2009-11-15 17:09 UTC (permalink / raw)
  To: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1258304977-11760-9-git-send-email-Joakim.Tjernlund@transmode.se>

There is no need to do set the DIRTY bit directly in DTLB Error.
Trap to do_page_fault() and let the generic MM code do the work.

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
 arch/powerpc/kernel/head_8xx.S |   96 ----------------------------------------
 1 files changed, 0 insertions(+), 96 deletions(-)

diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 90aa39e..2e9f9c0 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -500,102 +500,6 @@ DataTLBError:
 	cmpwi	cr0, r10, 0x00f0
 	beq-	FixupDAR	/* must be a buggy dcbX, icbi insn. */
 DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR */
-	mfspr	r11, SPRN_DSISR
-	/* As the DAR fixup may clear store we may have all 3 states zero.
-	 * Make sure only 0x0200(store) falls down into DIRTY handling
-	 */
-	andis.	r11, r11, 0x4a00	/* !translation, protection or store */
-	srwi	r11, r11, 16
-	cmpwi	cr0, r11, 0x0200	/* just store ? */
-	bne	2f
-	/* Only Change bit left now, do it here as it is faster
-	 * than trapping to the C fault handler.
-	*/
-
-	/* The EA of a data TLB miss is automatically stored in the MD_EPN
-	 * register.  The EA of a data TLB error is automatically stored in
-	 * the DAR, but not the MD_EPN register.  We must copy the 20 most
-	 * significant bits of the EA from the DAR to MD_EPN before we
-	 * start walking the page tables.  We also need to copy the CASID
-	 * value from the M_CASID register.
-	 * Addendum:  The EA of a data TLB error is _supposed_ to be stored
-	 * in DAR, but it seems that this doesn't happen in some cases, such
-	 * as when the error is due to a dcbi instruction to a page with a
-	 * TLB that doesn't have the changed bit set.  In such cases, there
-	 * does not appear to be any way  to recover the EA of the error
-	 * since it is neither in DAR nor MD_EPN.  As a workaround, the
-	 * _PAGE_HWWRITE bit is set for all kernel data pages when the PTEs
-	 * are initialized in mapin_ram().  This will avoid the problem,
-	 * assuming we only use the dcbi instruction on kernel addresses.
-	 */
-
-	/* DAR is in r10 already */
-	rlwinm	r11, r10, 0, 0, 19
-	ori	r11, r11, MD_EVALID
-	mfspr	r10, SPRN_M_CASID
-	rlwimi	r11, r10, 0, 28, 31
-	DO_8xx_CPU6(0x3780, r3)
-	mtspr	SPRN_MD_EPN, r11
-
-	mfspr	r10, SPRN_M_TWB	/* Get level 1 table entry address */
-
-	/* If we are faulting a kernel address, we have to use the
-	 * kernel page tables.
-	 */
-	andi.	r11, r10, 0x0800
-	beq	3f
-	lis	r11, swapper_pg_dir@h
-	ori	r11, r11, swapper_pg_dir@l
-	rlwimi	r10, r11, 0, 2, 19
-3:
-	lwz	r11, 0(r10)	/* Get the level 1 entry */
-	rlwinm.	r10, r11,0,0,19	/* Extract page descriptor page address */
-	beq	2f		/* If zero, bail */
-
-	/* We have a pte table, so fetch the pte from the table.
-	 */
-	ori	r11, r11, 1		/* Set valid bit in physical L2 page */
-	DO_8xx_CPU6(0x3b80, r3)
-	mtspr	SPRN_MD_TWC, r11	/* Load pte table base address */
-	mfspr	r10, SPRN_MD_TWC	/* ....and get the pte address */
-	lwz	r10, 0(r10)		/* Get the pte */
-	/* Insert the Guarded flag into the TWC from the Linux PTE.
-	 * It is bit 27 of both the Linux PTE and the TWC
-	 */
-	rlwimi	r11, r10, 0, 27, 27
-	/* Insert the WriteThru flag into the TWC from the Linux PTE.
-	 * It is bit 25 in the Linux PTE and bit 30 in the TWC
-	 */
-	rlwimi	r11, r10, 32-5, 30, 30
-	DO_8xx_CPU6(0x3b80, r3)
-	mtspr	SPRN_MD_TWC, r11
-	mfspr	r11, SPRN_MD_TWC	/* get the pte address again */
-
-	ori	r10, r10, _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HWWRITE
-	stw	r10, 0(r11)		/* and update pte in table */
-	xori	r10, r10, _PAGE_RW	/* RW bit is inverted */
-
-	/* The Linux PTE won't go exactly into the MMU TLB.
-	 * Software indicator bits 22 and 28 must be clear.
-	 * Software indicator bits 24, 25, 26, and 27 must be
-	 * set.  All other Linux PTE bits control the behavior
-	 * of the MMU.
-	 */
-	li	r11, 0x00f0
-	mtspr	SPRN_DAR,r11	/* Tag DAR */
-	rlwimi	r10, r11, 0, 24, 28	/* Set 24-27, clear 28 */
-	DO_8xx_CPU6(0x3d80, r3)
-	mtspr	SPRN_MD_RPN, r10	/* Update TLB entry */
-
-	mfspr	r10, SPRN_M_TW	/* Restore registers */
-	lwz	r11, 0(r0)
-	mtcr	r11
-	lwz	r11, 4(r0)
-#ifdef CONFIG_8xx_CPU6
-	lwz	r3, 8(r0)
-#endif
-	rfi
-2:
 	mfspr	r10, SPRN_M_TW	/* Restore registers */
 	lwz	r11, 0(r0)
 	mtcr	r11
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 10/10] 8xx: DTLB Miss cleanup
From: Joakim Tjernlund @ 2009-11-15 17:09 UTC (permalink / raw)
  To: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1258304977-11760-10-git-send-email-Joakim.Tjernlund@transmode.se>

Use symbolic constant for PRESENT and avoid branching.

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
 arch/powerpc/kernel/head_8xx.S |   17 +++++++++++------
 1 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 2e9f9c0..d8bf208 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -438,15 +438,20 @@ DataStoreTLBMiss:
 	 * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
 	 * r10 = (r10 & ~PRESENT) | r11;
 	 */
-	rlwinm	r11, r10, 32-5, 31, 31
+	rlwinm	r11, r10, 32-5, _PAGE_PRESENT
 	and	r11, r11, r10
-	rlwimi	r10, r11, 0, 31, 31
+	rlwimi	r10, r11, 0, _PAGE_PRESENT
 
 	/* Honour kernel RO, User NA */
-	andi.	r11, r10, _PAGE_USER | _PAGE_RW
-	bne-	cr0, 5f
-	ori	r10,r10, 0x200 /* Extended encoding, bit 22 */
-5:	xori	r10, r10, _PAGE_RW  /* invert RW bit */
+	/* 0x200 == Extended encoding, bit 22 */
+	/* r11 =  (r10 & _PAGE_USER) >> 2 */
+	rlwinm	r11, r10, 32-2, 0x200
+	or	r10, r11, r10
+	/* r11 =  (r10 & _PAGE_RW) >> 1 */
+	rlwinm	r11, r10, 32-1, 0x200
+	or	r10, r11, r10
+	/* invert RW and 0x200 bits */
+	xori	r10, r10, _PAGE_RW | 0x200
 
 	/* The Linux PTE won't go exactly into the MMU TLB.
 	 * Software indicator bits 22 and 28 must be clear.
-- 
1.6.4.4

^ permalink raw reply related

* [Q/RFC] mpc52xx gpt api
From: Albrecht Dreß @ 2009-11-15 17:17 UTC (permalink / raw)
  To: linuxppc-dev

Hi all,

I tried to use a '5200B internal timer for a very simple task - as pwm to m=
ake a led blink, but apparently the current gpt implementation from Grant's=
 tree does only support internal (cpu timer) modes which do not use the tim=
er io pin.

The first hurdle was to actually get the timer itself - mpc52xx_gpt_from_ir=
q() never returned something when I passed the timers (v)irq to it.  What i=
s the intended use of this function?  BTW, I do not need timer irq's, so I =
believe there should be an other way to grab a timer!

I made several changes to finally get the pwm timer running for me with the=
 current implementation, but IMO it might be interesting to have a more gen=
eric api.  Before digging into it, I would be interested in any comment abo=
ut the following approach, which could cover all possible gpt operating mod=
es:

* struct mpc52xx_gpt_priv *mpc52xx_gpt_grab(const char * name, mode)
  name: timer name, e.g. "f0000630.timer", or NULL for the next free cpu ti=
mer
  mode: CPU, PWM, IC or OC.  The latter three are only possible if the requ=
ested timer shall not be used as gpio (i.e. the device tree does not regist=
er it as such)
  The function shall mark the timer as being in use, to avoid access confli=
cts.
  It might also make sense to pass an irq callback function here.  The gpt =
module would catch the hw irq, clear the status flags, and then call this f=
unction.

* int mpc52xx_gpt_setup
  Configure period, continuous (cpu only), pwm width and polarity (pwm only=
).  Didn't look into the special IC/OC requirements yet.  Probably it makes=
 sense to provide different functions for the four different modes (mpc52xx=
_gpt_setup_internal, mpc52xx_gpt_setup_pwm, etc.).  We might then omit the =
mode parameter of the "grab" function, and shift the gpio vs. timer pin con=
flict check here.
  The function shall always change the timer registers, even if the timer i=
s already running, which is convenient if e.g. the pwm output waveform shal=
l be changed on the fly.

* int mpc52xx_gpt_runstate(struct mpc52xx_gpt_priv *, int running)
  Start/stop the timer

* int mpc52xx_gpt_release(struct mpc52xx_gpt_priv *)
  Release timer, so an other mpc52xx_gpt_grab() will succeed.

Opinions?

Cheers, Albrecht.

Jetzt NEU: Do it youself E-Cards bei Arcor.de!
Stellen Sie Ihr eigenes Unikat zusammen und machen Sie dem Empf=E4nger eine=
 ganz pers=F6nliche Freude!
E-Card Marke Eigenbau: HIER KLICKEN: http://www.arcor.de/rd/footer.ecard

^ permalink raw reply

* [PATCH 1/1] ata/sata_sil24: MSI support, disabled by default
From: Vivek Mahajan @ 2009-11-16  6:19 UTC (permalink / raw)
  To: linux-ide; +Cc: linuxppc-dev, Vivek Mahajan

The following patch adds MSI support. Some platforms
may have broken MSI, so those are defaulted to use
legacy PCI interrupts.

Signed-off-by: Vivek Mahajan <vivek.mahajan@freescale.com>
---
 drivers/ata/sata_sil24.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index e6946fc..1370df6 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -417,6 +417,10 @@ static struct ata_port_operations sil24_ops = {
 #endif
 };
 
+static int sata_sil24_msi;    /* Disable MSI */
+module_param_named(msi, sata_sil24_msi, bool, S_IRUGO);
+MODULE_PARM_DESC(msi, "Enable MSI (Default: false)");
+
 /*
  * Use bits 30-31 of port_flags to encode available port numbers.
  * Current maxium is 4.
@@ -1340,6 +1344,11 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	sil24_init_controller(host);
 
+	if (sata_sil24_msi && !pci_enable_msi(pdev)) {
+		dev_printk(KERN_INFO, &pdev->dev, "Using MSI\n");
+		pci_intx(pdev, 0);
+	}
+
 	pci_set_master(pdev);
 	return ata_host_activate(host, pdev->irq, sil24_interrupt, IRQF_SHARED,
 				 &sil24_sht);
-- 
1.5.6.5

^ permalink raw reply related

* Re: Bug in drivers/serial/of_serial.c?
From: Arnd Bergmann @ 2009-11-16  8:09 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Alon Ziv
In-Reply-To: <8B957E110B62714A84290A01A597805F05CA0AA0@Exchange.discretix.com>

On Sunday 15 November 2009, Alon Ziv wrote:
> *)PORT_16450, },
> -       { .type = "serial", .compatible = "ns16550",  .data = (void *)PORT_16550, },
> +       { .type = "serial", .compatible = "ns16550",  .data = (void *)PORT_16550A, },

Does not seem logical. If the device claims compatibility with ns16550, we should
not automatically assume it's an ns16550a. Why not add another line for 

{ .type = "serial", .compatible = "ns16550a",  .data = (void *)PORT_16550A, },

	Arnd <><

^ permalink raw reply

* Re: [PATCH] net/can: add driver for mscan family & mpc52xx_mscan
From: Wolfgang Grandegger @ 2009-11-16  8:40 UTC (permalink / raw)
  To: Grant Likely; +Cc: socketcan-core, netdev, David Miller, linuxppc-dev
In-Reply-To: <fa686aa40911130939x54ac53f9x173a875a5a4435d3@mail.gmail.com>

Grant Likely wrote:
> On Fri, Nov 13, 2009 at 9:14 AM, Wolfram Sang <w.sang@pengutronix.de> wrote:
>> Taken from socketcan-svn, fixed remaining todos, cleaned up, tested with a
>> phyCORE-MPC5200B-IO and a custom board.
>>
>> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
>> Cc: Wolfgang Grandegger <wg@grandegger.com>
>> Cc: Grant Likely <grant.likely@secretlab.ca>
>> Cc: David Miller <davem@davemloft.net>
> 
> I don't see any locking in this driver.  What keeps the mscan_isr or
> other routines from conflicting with each other?  What is the
> concurrency model for CAN devices?

There is concurrency between the mscan_start_xmit() and mscan_irq()
routine, which is handled by disabling/enabling the TX interrupt source.
CAN configuration (bit-timing) can only be changed when the device is
stopped (down) and bus-off recovery requires that interrupts are
disabled or the hadrware does not send/receive messages after the
bus-off occurred.

> More comments below.  I don't have the background to delve into the
> CAN details, but I can make some comments on the general structure of
> the driver.

[snip]
>> +static unsigned int  __devinit mpc52xx_can_clock_freq(struct of_device *of,
>> +                                                     int clock_src)
>> +{
>> +       unsigned int pvr;
>> +
>> +       pvr = mfspr(SPRN_PVR);
>> +
>> +       if (clock_src == MSCAN_CLKSRC_BUS || pvr == 0x80822011)
>> +               return mpc5xxx_get_bus_frequency(of->node);
>> +
>> +       return mpc52xx_can_xtal_freq(of);
>> +}
> 
> mpc52xx_can_xtal_freq() is only used by this function.  Do they need
> to be separate?

Not really, and it would save some lines of code.

[snip]
>> +static int mscan_set_mode(struct net_device *dev, u8 mode)
>> +{
>> +       struct mscan_priv *priv = netdev_priv(dev);
>> +       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
>> +       int ret = 0;
>> +       int i;
>> +       u8 canctl1;
>> +
>> +       if (mode != MSCAN_NORMAL_MODE) {
>> +
>> +               if (priv->tx_active) {
>> +                       /* Abort transfers before going to sleep */#
>> +                       out_8(&regs->cantarq, priv->tx_active);
>> +                       /* Suppress TX done interrupts */
>> +                       out_8(&regs->cantier, 0);
>> +               }
>> +
>> +               canctl1 = in_8(&regs->canctl1);
>> +               if ((mode & MSCAN_SLPRQ) && (canctl1 & MSCAN_SLPAK) == 0) {
>> +                       out_8(&regs->canctl0,
>> +                             in_8(&regs->canctl0) | MSCAN_SLPRQ);
>> +                       for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
>> +                               if (in_8(&regs->canctl1) & MSCAN_SLPAK)
>> +                                       break;
>> +                               udelay(100);
> 
> Ugh.  Can you sleep instead?  This burns a lot of CPU cycles to no purpose.

A real sleep for 100us? The usual jiffy based sleep would take 1..10 ms,
at least. I think we should check how much time/cycles it usually takes.

[snip]
>> +static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
>> +{
>> +
>> +       struct mscan_priv *priv = netdev_priv(dev);
>> +       int ret = 0;
>> +
>> +       if (!priv->open_time)
>> +               return -EINVAL;
>> +
>> +       switch (mode) {
>> +       case CAN_MODE_SLEEP:
>> +       case CAN_MODE_STOP:
>> +               netif_stop_queue(dev);
>> +               mscan_set_mode(dev,
>> +                              (mode ==
>> +                               CAN_MODE_STOP) ? MSCAN_INIT_MODE :
>> +                              MSCAN_SLEEP_MODE);
> 
> A little hard on the eyes.  Can you rework to not spill over 4 lines?
> (ie. calc mode flag on the line above?)

These cases can safely be removed as currently only CAN_MODE_START is
supported by the upper layer.

Wolfgang.

^ permalink raw reply

* Re: [PATCH] net/can: add driver for mscan family & mpc52xx_mscan
From: Wolfgang Grandegger @ 2009-11-16  8:44 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: netdev, David Miller, socketcan-core, linuxppc-dev
In-Reply-To: <1258128892-28800-1-git-send-email-w.sang@pengutronix.de>

Hi Wolfram,

thanks for pushing this driver to mainline. I think you should also add
a CC to the Devicetree-discuss ML.

Wolfram Sang wrote:
> Taken from socketcan-svn, fixed remaining todos, cleaned up, tested with a
> phyCORE-MPC5200B-IO and a custom board.
> 
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
> Cc: Wolfgang Grandegger <wg@grandegger.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: David Miller <davem@davemloft.net>
> ---
> 
> This patch is based on net-next as of yesterday.
> 
> To make the review easier for those who are already familiar with earlier
> versions of this driver (especially for Wolfgang), I put my development branch
> online, so you can check my changes incrementally:
> 
> http://git.pengutronix.de/?p=wsa/linux-2.6.git;a=summary
> 
>  Documentation/powerpc/dts-bindings/fsl/mpc5200.txt |    9 +
>  drivers/net/can/Kconfig                            |   19 +
>  drivers/net/can/Makefile                           |    1 +
>  drivers/net/can/mscan/Makefile                     |    5 +
>  drivers/net/can/mscan/mpc52xx_can.c                |  279 ++++++++

With the mpc521x in mind, please change the name to mpc5xxx_can.c. In
this file, you already use mpc5xxx_* functions.

>  drivers/net/can/mscan/mscan.c                      |  699 ++++++++++++++++++++
>  drivers/net/can/mscan/mscan.h                      |  262 ++++++++
>  7 files changed, 1274 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/can/mscan/Makefile
>  create mode 100644 drivers/net/can/mscan/mpc52xx_can.c
>  create mode 100644 drivers/net/can/mscan/mscan.c
>  create mode 100644 drivers/net/can/mscan/mscan.h
> 
> diff --git a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
> index 8447fd7..b151fb1 100644
> --- a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
> +++ b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
> @@ -178,3 +178,12 @@ External interrupts:
>  	external irq3:	interrupts = <1 3 n>;
>  'n' is sense (0: level high, 1: edge rising, 2: edge falling 3: level low)
>  
> +fsl,mpc5200-mscan nodes
> +-----------------------
> +In addition to the required compatible-, reg- and interrupt-properites, you can
> +also specify which clock shall be used for the bus:

I think "which clock source shall be used for the MSCAN controller" is
more appropriate. It's not the clock for the CAN bus.

> +
> +- fsl,mscan-clk-src	- a string describing the clock source. Valid values
> +			  are "ip" for IP_CLK and "sys" for SYS_XTAL.
> +			  "sys" is the default in case the property is not
> +			  present.

I think it's common to use long names, e.g. fsl,mscan-clock-source. Also
the "system" clock is normally not equal to the XTAL clock. "ref" for
reference clock would be more appropriate. Anyhow, in the code you only
check for "ip". If it's not defined, the other clock will be used.

> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index b819cc2..c16e6ff 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig

As the mscan driver is in a sub-directory, we should move the Kconfig
file into it. Oliver has sent a patch recently to do so for the sja1000
and usb sub-directory.

> @@ -108,6 +108,25 @@ config CAN_MCP251X
>  	---help---
>  	  Driver for the Microchip MCP251x SPI CAN controllers.
>  
> +config CAN_MSCAN
> +	depends on CAN_DEV && (PPC || M68K || M68KNOMMU)
> +	tristate "Support for Freescale MSCAN based chips"
> +	---help---
> +	  The Motorola Scalable Controller Area Network (MSCAN) definition
> +	  is based on the MSCAN12 definition which is the specific
> +	  implementation of the Motorola Scalable CAN concept targeted for
> +	  the Motorola MC68HC12 Microcontroller Family.
> +
> +config CAN_MPC52XX

s/CAN_MPC52XX/CAN_MPC5XXX/, (or CAN_MPC5xxx) see above.

> +	tristate "Freescale MPC5xxx onboard CAN controller"
> +	depends on CAN_MSCAN && PPC_MPC52xx
> +	---help---
> +	  If you say yes here you get support for Freescale's MPC52xx
> +	  onboard dualCAN controller.
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called mpc5xxx_can.

Also here you already speak about mpc5xxx. And the name of the module is
mscan-mpc52xx.ko, IIRC.

> +
>  config CAN_DEBUG_DEVICES
>  	bool "CAN devices debugging messages"
>  	depends on CAN
> diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> index 1489181..56899fe 100644
> --- a/drivers/net/can/Makefile
> +++ b/drivers/net/can/Makefile
> @@ -10,6 +10,7 @@ can-dev-y			:= dev.o
>  obj-y				+= usb/
>  
>  obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
> +obj-$(CONFIG_CAN_MSCAN)		+= mscan/
>  obj-$(CONFIG_CAN_AT91)		+= at91_can.o
>  obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o
>  obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
> diff --git a/drivers/net/can/mscan/Makefile b/drivers/net/can/mscan/Makefile
> new file mode 100644
> index 0000000..2bd9f04
> --- /dev/null
> +++ b/drivers/net/can/mscan/Makefile
> @@ -0,0 +1,5 @@
> +
> +obj-$(CONFIG_CAN_MPC52XX)	+= mscan-mpc52xx.o
> +mscan-mpc52xx-objs		:= mscan.o mpc52xx_can.o
> +
> +ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
> diff --git a/drivers/net/can/mscan/mpc52xx_can.c b/drivers/net/can/mscan/mpc52xx_can.c
> new file mode 100644
> index 0000000..4707a82
> --- /dev/null
> +++ b/drivers/net/can/mscan/mpc52xx_can.c
> @@ -0,0 +1,279 @@
> +/*
> + * CAN bus driver for the Freescale MPC5xxx embedded CPU.
> + *
> + * Copyright (C) 2004-2005 Andrey Volkov <avolkov@varma-el.com>,
> + *                         Varma Electronics Oy
> + * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
> + * Copyright (C) 2009 Wolfram Sang, Pengutronix <w.sang@pengutronix.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the version 2 of the GNU General Public License
> + * as published by the Free Software Foundation
> + *
> + * 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/kernel.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/platform_device.h>
> +#include <linux/netdevice.h>
> +#include <linux/can.h>
> +#include <linux/can/dev.h>
> +#include <linux/of_platform.h>
> +#include <sysdev/fsl_soc.h>
> +#include <linux/io.h>
> +#include <asm/mpc52xx.h>
> +
> +#include "mscan.h"
> +
> +

Remove one line, please.

> +#define DRV_NAME "mpc5xxx_can"
> +
> +static struct of_device_id mpc52xx_cdm_ids[] __devinitdata = {
> +	{ .compatible = "fsl,mpc5200-cdm", },
> +	{ .compatible = "fsl,mpc5200b-cdm", },
> +	{}
> +};
> +
> +/*
> + * Get the frequency of the external oscillator clock connected
> + * to the SYS_XTAL_IN pin, or return 0 if it cannot be determined.
> + */
> +static unsigned int  __devinit mpc52xx_can_xtal_freq(struct of_device *of)
> +{
> +	struct mpc52xx_cdm  __iomem *cdm;
> +	struct device_node *np_cdm;
> +	unsigned int freq;
> +	u32 val;
> +
> +	freq = mpc5xxx_get_bus_frequency(of->node);
> +	if (!freq)
> +		return 0;
> +
> +	/*
> +	 * Determine SYS_XTAL_IN frequency from the clock domain settings
> +	 */
> +	np_cdm = of_find_matching_node(NULL, mpc52xx_cdm_ids);
> +	if (!np_cdm) {
> +		dev_err(&of->dev, "can't get clock node!\n");
> +		return 0;
> +	}
> +	cdm = of_iomap(np_cdm, 0);
> +	of_node_put(np_cdm);
> +
> +	if (in_8(&cdm->ipb_clk_sel) & 0x1)
> +		freq *= 2;
> +	val  = in_be32(&cdm->rstcfg);
> +	if (val & (1 << 5))
> +		freq *= 8;
> +	else
> +		freq *= 4;
> +	if (val & (1 << 6))
> +		freq /= 12;
> +	else
> +		freq /= 16;
> +
> +	iounmap(cdm);
> +
> +	return freq;
> +}
> +
> +/*
> + * Get frequency of the MSCAN clock source
> + *
> + * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock (IP_CLK)
> + * can be selected. According to the MPC5200 user's manual, the oscillator
> + * clock is the better choice as it has less jitter but due to a hardware
> + * bug, it can not be selected for the old MPC5200 Rev. A chips.
> + */
> +
> +static unsigned int  __devinit mpc52xx_can_clock_freq(struct of_device *of,
> +						      int clock_src)
> +{
> +	unsigned int pvr;
> +
> +	pvr = mfspr(SPRN_PVR);
> +
> +	if (clock_src == MSCAN_CLKSRC_BUS || pvr == 0x80822011)
> +		return mpc5xxx_get_bus_frequency(of->node);
> +
> +	return mpc52xx_can_xtal_freq(of);
> +}
> +
> +static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
> +				       const struct of_device_id *id)
> +{
> +	struct device_node *np = ofdev->node;
> +	struct net_device *dev;
> +	struct mscan_priv *priv;
> +	void __iomem *base;
> +	const char *clk_src;
> +	int err, irq, clock_src;
> +
> +	base = of_iomap(ofdev->node, 0);
> +	if (!base) {
> +		dev_err(&ofdev->dev, "couldn't ioremap\n");
> +		err = -ENOMEM;
> +		goto exit_release_mem;
> +	}
> +
> +	irq = irq_of_parse_and_map(np, 0);
> +	if (!irq) {
> +		dev_err(&ofdev->dev, "no irq found\n");
> +		err = -ENODEV;
> +		goto exit_unmap_mem;
> +	}
> +
> +	dev = alloc_mscandev();
> +	if (!dev) {
> +		err = -ENOMEM;
> +		goto exit_dispose_irq;
> +	}
> +
> +	priv = netdev_priv(dev);
> +	priv->reg_base = base;
> +	dev->irq = irq;
> +
> +	/*
> +	 * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock
> +	 * (IP_CLK) can be selected as MSCAN clock source. According to
> +	 * the MPC5200 user's manual, the oscillator clock is the better
> +	 * choice as it has less jitter. For this reason, it is selected
> +	 * by default.
> +	 */
> +	clk_src = of_get_property(np, "fsl,mscan-clk-src", NULL);
> +	if (clk_src && strcmp(clk_src, "ip") == 0)
> +		clock_src = MSCAN_CLKSRC_BUS;
> +	else
> +		clock_src = MSCAN_CLKSRC_XTAL;
> +	priv->can.clock.freq = mpc52xx_can_clock_freq(ofdev, clock_src);
> +	if (!priv->can.clock.freq) {
> +		dev_err(&ofdev->dev, "couldn't get MSCAN clock frequency\n");
> +		err = -ENODEV;
> +		goto exit_free_mscan;
> +	}
> +
> +	SET_NETDEV_DEV(dev, &ofdev->dev);
> +
> +	err = register_mscandev(dev, clock_src);
> +	if (err) {
> +		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
> +			DRV_NAME, err);
> +		goto exit_free_mscan;
> +	}
> +
> +	dev_set_drvdata(&ofdev->dev, dev);
> +
> +	dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
> +		 priv->reg_base, dev->irq, priv->can.clock.freq);
> +
> +	return 0;
> +
> +exit_free_mscan:
> +	free_candev(dev);
> +exit_dispose_irq:
> +	irq_dispose_mapping(irq);
> +exit_unmap_mem:
> +	iounmap(base);
> +exit_release_mem:
> +	return err;
> +}
> +
> +static int __devexit mpc5xxx_can_remove(struct of_device *ofdev)
> +{
> +	struct net_device *dev = dev_get_drvdata(&ofdev->dev);
> +	struct mscan_priv *priv = netdev_priv(dev);
> +
> +	dev_set_drvdata(&ofdev->dev, NULL);
> +
> +	unregister_mscandev(dev);
> +	iounmap(priv->reg_base);
> +	irq_dispose_mapping(dev->irq);
> +	free_candev(dev);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static struct mscan_regs saved_regs;
> +static int mpc5xxx_can_suspend(struct of_device *ofdev, pm_message_t state)
> +{
> +	struct net_device *dev = dev_get_drvdata(&ofdev->dev);
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +
> +	_memcpy_fromio(&saved_regs, regs, sizeof(*regs));
> +
> +	return 0;
> +}
> +
> +static int mpc5xxx_can_resume(struct of_device *ofdev)
> +{
> +	struct net_device *dev = dev_get_drvdata(&ofdev->dev);
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +
> +	regs->canctl0 |= MSCAN_INITRQ;
> +	while ((regs->canctl1 & MSCAN_INITAK) == 0)
> +		udelay(10);
> +
> +	regs->canctl1 = saved_regs.canctl1;
> +	regs->canbtr0 = saved_regs.canbtr0;
> +	regs->canbtr1 = saved_regs.canbtr1;
> +	regs->canidac = saved_regs.canidac;
> +
> +	/* restore masks, buffers etc. */
> +	_memcpy_toio(&regs->canidar1_0, (void *)&saved_regs.canidar1_0,
> +		     sizeof(*regs) - offsetof(struct mscan_regs, canidar1_0));
> +
> +	regs->canctl0 &= ~MSCAN_INITRQ;
> +	regs->cantbsel = saved_regs.cantbsel;
> +	regs->canrier = saved_regs.canrier;
> +	regs->cantier = saved_regs.cantier;
> +	regs->canctl0 = saved_regs.canctl0;
> +
> +	return 0;
> +}
> +#endif

I wonder if suspend/resume is working. Does the software shutdown the
device before suspending? Did you or anybody else have a chance to test
suspend/resume?

> +static struct of_device_id __devinitdata mpc5xxx_can_table[] = {
> +	{.compatible = "fsl,mpc5200-mscan"},
> +	{.compatible = "fsl,mpc5200b-mscan"},
> +	{},
> +};
> +
> +static struct of_platform_driver mpc5xxx_can_driver = {
> +	.owner = THIS_MODULE,
> +	.name = "mpc5xxx_can",
> +	.probe = mpc5xxx_can_probe,
> +	.remove = __devexit_p(mpc5xxx_can_remove),
> +#ifdef CONFIG_PM
> +	.suspend = mpc5xxx_can_suspend,
> +	.resume = mpc5xxx_can_resume,
> +#endif
> +	.match_table = mpc5xxx_can_table,
> +};
> +
> +static int __init mpc5xxx_can_init(void)
> +{
> +	return of_register_platform_driver(&mpc5xxx_can_driver);
> +}
> +module_init(mpc5xxx_can_init);
> +
> +static void __exit mpc5xxx_can_exit(void)
> +{
> +	return of_unregister_platform_driver(&mpc5xxx_can_driver);
> +};
> +module_exit(mpc5xxx_can_exit);
> +
> +MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
> +MODULE_DESCRIPTION("Freescale MPC5200 CAN driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
> new file mode 100644
> index 0000000..49542ca
> --- /dev/null
> +++ b/drivers/net/can/mscan/mscan.c
> @@ -0,0 +1,699 @@
> +/*
> + * CAN bus driver for the alone generic (as possible as) MSCAN controller.
> + *
> + * Copyright (C) 2005-2006 Andrey Volkov <avolkov@varma-el.com>,
> + *                         Varma Electronics Oy
> + * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
> + * Copytight (C) 2008-2009 Pengutronix <kernel@pengutronix.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the version 2 of the GNU General Public License
> + * as published by the Free Software Foundation
> + *
> + * 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/kernel.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/netdevice.h>
> +#include <linux/if_arp.h>
> +#include <linux/if_ether.h>
> +#include <linux/list.h>
> +#include <linux/can.h>
> +#include <linux/can/dev.h>
> +#include <linux/can/error.h>
> +#include <linux/io.h>
> +
> +#include "mscan.h"
> +
> +#define MSCAN_NORMAL_MODE	0
> +#define MSCAN_SLEEP_MODE	MSCAN_SLPRQ
> +#define MSCAN_INIT_MODE		(MSCAN_INITRQ | MSCAN_SLPRQ)
> +#define MSCAN_POWEROFF_MODE	(MSCAN_CSWAI | MSCAN_SLPRQ)
> +#define MSCAN_SET_MODE_RETRIES	255
> +#define MSCAN_ECHO_SKB_MAX	3
> +
> +#define BTR0_BRP_MASK		0x3f
> +#define BTR0_SJW_SHIFT		6
> +#define BTR0_SJW_MASK		(0x3 << BTR0_SJW_SHIFT)
> +
> +#define BTR1_TSEG1_MASK 	0xf
> +#define BTR1_TSEG2_SHIFT	4
> +#define BTR1_TSEG2_MASK 	(0x7 << BTR1_TSEG2_SHIFT)
> +#define BTR1_SAM_SHIFT  	7
> +
> +#define BTR0_SET_BRP(brp)	(((brp) - 1) & BTR0_BRP_MASK)
> +#define BTR0_SET_SJW(sjw)	((((sjw) - 1) << BTR0_SJW_SHIFT) & \
> +				 BTR0_SJW_MASK)
> +
> +#define BTR1_SET_TSEG1(tseg1)	(((tseg1) - 1) &  BTR1_TSEG1_MASK)
> +#define BTR1_SET_TSEG2(tseg2)	((((tseg2) - 1) << BTR1_TSEG2_SHIFT) & \
> +				 BTR1_TSEG2_MASK)
> +#define BTR1_SET_SAM(sam)	((sam) ? 1 << BTR1_SAM_SHIFT : 0)

These definitions should probably be moved to mscan.h.

> +static struct can_bittiming_const mscan_bittiming_const = {
> +	.name = "mscan",
> +	.tseg1_min = 4,
> +	.tseg1_max = 16,
> +	.tseg2_min = 2,
> +	.tseg2_max = 8,
> +	.sjw_max = 4,
> +	.brp_min = 1,
> +	.brp_max = 64,
> +	.brp_inc = 1,
> +};
> +
> +struct mscan_state {
> +	u8 mode;
> +	u8 canrier;
> +	u8 cantier;
> +};
> +
> +#define F_RX_PROGRESS	0
> +#define F_TX_PROGRESS	1
> +#define F_TX_WAIT_ALL	2

Ditto.

> +static enum can_state state_map[] = {
> +	CAN_STATE_ERROR_ACTIVE,
> +	CAN_STATE_ERROR_WARNING,
> +	CAN_STATE_ERROR_PASSIVE,
> +	CAN_STATE_BUS_OFF
> +};
> +
> +static int mscan_set_mode(struct net_device *dev, u8 mode)
> +{
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +	int ret = 0;
> +	int i;
> +	u8 canctl1;
> +
> +	if (mode != MSCAN_NORMAL_MODE) {
> +

Please remove the empty line above.

> +		if (priv->tx_active) {
> +			/* Abort transfers before going to sleep */#
> +			out_8(&regs->cantarq, priv->tx_active);
> +			/* Suppress TX done interrupts */
> +			out_8(&regs->cantier, 0);
> +		}
> +
> +		canctl1 = in_8(&regs->canctl1);
> +		if ((mode & MSCAN_SLPRQ) && (canctl1 & MSCAN_SLPAK) == 0) {
> +			out_8(&regs->canctl0,
> +			      in_8(&regs->canctl0) | MSCAN_SLPRQ);

We better use setbits8(&regs->canctl0, MSCAN_SLPRQ);

> +			for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
> +				if (in_8(&regs->canctl1) & MSCAN_SLPAK)
> +					break;
> +				udelay(100);
> +			}
> +			/*
> +			 * The mscan controller will fail to enter sleep mode,
> +			 * while there are irregular activities on bus, like
> +			 * somebody keeps retransmitting. This behavior is
> +			 * undocumented and seems to differ between mscan built
> +			 * in mpc5200b and mpc5200. We proceed in that case,
> +			 * since otherwise the slprq will be kept set and the
> +			 * controller will get stuck. NOTE: INITRQ or CSWAI
> +			 * will abort all active transmit actions, if still
> +			 * any, at once.
> +			 */
> +			if (i >= MSCAN_SET_MODE_RETRIES)
> +				dev_dbg(dev->dev.parent,
> +					"device failed to enter sleep mode. "
> +					"We proceed anyhow.\n");
> +			else
> +				priv->can.state = CAN_STATE_SLEEPING;
> +		}
> +
> +		if ((mode & MSCAN_INITRQ) && (canctl1 & MSCAN_INITAK) == 0) {

	if ((mode & MSCAN_INITRQ) && !(canctl1 & MSCAN_INITAK)) ?

> +			out_8(&regs->canctl0,
> +			      in_8(&regs->canctl0) | MSCAN_INITRQ);

setbits8?

> +			for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
> +				if (in_8(&regs->canctl1) & MSCAN_INITAK)
> +					break;
> +			}
> +			if (i >= MSCAN_SET_MODE_RETRIES)
> +				ret = -ENODEV;
> +		}
> +		if (!ret)
> +			priv->can.state = CAN_STATE_STOPPED;
> +
> +		if (mode & MSCAN_CSWAI)
> +			out_8(&regs->canctl0,
> +			      in_8(&regs->canctl0) | MSCAN_CSWAI);

setbits8?

> +
> +	} else {
> +		canctl1 = in_8(&regs->canctl1);
> +		if (canctl1 & (MSCAN_SLPAK | MSCAN_INITAK)) {
> +			out_8(&regs->canctl0, in_8(&regs->canctl0) &
> +			      ~(MSCAN_SLPRQ | MSCAN_INITRQ));

clrbits8?

> +			for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
> +				canctl1 = in_8(&regs->canctl1);
> +				if (!(canctl1 & (MSCAN_INITAK | MSCAN_SLPAK)))
> +					break;
> +			}
> +			if (i >= MSCAN_SET_MODE_RETRIES)
> +				ret = -ENODEV;
> +			else
> +				priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +		}
> +	}
> +	return ret;
> +}
> +
> +static int mscan_start(struct net_device *dev)
> +{
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +	u8 canrflg;
> +	int err;
> +
> +	out_8(&regs->canrier, 0);
> +
> +	INIT_LIST_HEAD(&priv->tx_head);
> +	priv->prev_buf_id = 0;
> +	priv->cur_pri = 0;
> +	priv->tx_active = 0;
> +	priv->shadow_canrier = 0;
> +	priv->flags = 0;
> +
> +	err = mscan_set_mode(dev, MSCAN_NORMAL_MODE);
> +	if (err)
> +		return err;
> +
> +	canrflg = in_8(&regs->canrflg);
> +	priv->shadow_statflg = canrflg & MSCAN_STAT_MSK;
> +	priv->can.state = state_map[max(MSCAN_STATE_RX(canrflg),
> +				    MSCAN_STATE_TX(canrflg))];
> +	out_8(&regs->cantier, 0);
> +
> +	/* Enable receive interrupts. */
> +	out_8(&regs->canrier, MSCAN_OVRIE | MSCAN_RXFIE | MSCAN_CSCIE |
> +	      MSCAN_RSTATE1 | MSCAN_RSTATE0 | MSCAN_TSTATE1 | MSCAN_TSTATE0);
> +
> +	return 0;
> +}
> +
> +static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +	struct can_frame *frame = (struct can_frame *)skb->data;
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +	int i, rtr, buf_id;
> +	u32 can_id;
> +
> +	if (frame->can_dlc > 8)
> +		return -EINVAL;
> +
> +	out_8(&regs->cantier, 0);
> +
> +	i = ~priv->tx_active & MSCAN_TXE;
> +	buf_id = ffs(i) - 1;
> +	switch (hweight8(i)) {
> +	case 0:
> +		netif_stop_queue(dev);
> +		dev_err(dev->dev.parent, "Tx Ring full when queue awake!\n");
> +		return NETDEV_TX_BUSY;
> +	case 1:
> +		/*
> +		 * if buf_id < 3, then current frame will be send out of order,
> +		 * since buffer with lower id have higher priority (hell..)
> +		 */
> +		netif_stop_queue(dev);
> +	case 2:
> +		if (buf_id < priv->prev_buf_id) {
> +			priv->cur_pri++;
> +			if (priv->cur_pri == 0xff) {
> +				set_bit(F_TX_WAIT_ALL, &priv->flags);
> +				netif_stop_queue(dev);
> +			}
> +		}
> +		set_bit(F_TX_PROGRESS, &priv->flags);
> +		break;
> +	}
> +	priv->prev_buf_id = buf_id;
> +	out_8(&regs->cantbsel, i);
> +
> +	rtr = frame->can_id & CAN_RTR_FLAG;
> +
> +	if (frame->can_id & CAN_EFF_FLAG) {
> +		can_id = (frame->can_id & CAN_EFF_MASK) << 1;
> +		if (rtr)
> +			can_id |= 1;

Would be nice to have some definitions for this bit and other bits and
shifts as well (in general).

> +		out_be16(&regs->tx.idr3_2, can_id);
> +
> +		can_id >>= 16;
> +		can_id = (can_id & 0x7) | ((can_id << 2) & 0xffe0) | (3 << 3);

Ditto

> +	} else {
> +		can_id = (frame->can_id & CAN_SFF_MASK) << 5;
> +		if (rtr)
> +			can_id |= 1 << 4;
> +	}
> +	out_be16(&regs->tx.idr1_0, can_id);
> +
> +	if (!rtr) {
> +		void __iomem *data = &regs->tx.dsr1_0;
> +		u16 *payload = (u16 *) frame->data;

Please add one empty line and remove the space before frame.

> +		/* It is safe to write into dsr[dlc+1] */
> +		for (i = 0; i < (frame->can_dlc + 1) / 2; i++) {
> +			out_be16(data, *payload++);
> +			data += 2 + _MSCAN_RESERVED_DSR_SIZE;
> +		}
> +	}
> +
> +	out_8(&regs->tx.dlr, frame->can_dlc);
> +	out_8(&regs->tx.tbpr, priv->cur_pri);
> +
> +	/* Start transmission. */
> +	out_8(&regs->cantflg, 1 << buf_id);
> +
> +	if (!test_bit(F_TX_PROGRESS, &priv->flags))
> +		dev->trans_start = jiffies;
> +
> +	list_add_tail(&priv->tx_queue[buf_id].list, &priv->tx_head);
> +
> +	can_put_echo_skb(skb, dev, buf_id);
> +
> +	/* Enable interrupt. */
> +	priv->tx_active |= 1 << buf_id;
> +	out_8(&regs->cantier, priv->tx_active);
> +
> +	return NETDEV_TX_OK;
> +}
> +
> +/* This function returns the old state to see where we came from */
> +static enum can_state check_set_state(struct net_device *dev, u8 canrflg)
> +{
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	enum can_state state, old_state = priv->can.state;
> +
> +	if (canrflg & MSCAN_CSCIF && old_state <= CAN_STATE_BUS_OFF) {
> +		state = state_map[max(MSCAN_STATE_RX(canrflg),
> +				      MSCAN_STATE_TX(canrflg))];
> +		priv->can.state = state;
> +	}
> +	return old_state;
> +}
> +
> +static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame)
> +{
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +	u32 can_id;
> +	int i;
> +
> +	can_id = in_be16(&regs->rx.idr1_0);
> +	if (can_id & (1 << 3)) {
> +		frame->can_id = CAN_EFF_FLAG;
> +		can_id = ((can_id << 16) | in_be16(&regs->rx.idr3_2));
> +		can_id = ((can_id & 0xffe00000) |
> +			  ((can_id & 0x7ffff) << 2)) >> 2;
> +	} else {
> +		can_id >>= 4;
> +		frame->can_id = 0;
> +	}
> +
> +	frame->can_id |= can_id >> 1;
> +	if (can_id & 1)
> +		frame->can_id |= CAN_RTR_FLAG;
> +	frame->can_dlc = in_8(&regs->rx.dlr) & 0xf;
> +
> +	if (!(frame->can_id & CAN_RTR_FLAG)) {
> +		void __iomem *data = &regs->rx.dsr1_0;
> +		u16 *payload = (u16 *) frame->data;

Please add one empty line and remove the space before frame.

> +		for (i = 0; i < (frame->can_dlc + 1) / 2; i++) {
> +			*payload++ = in_be16(data);
> +			data += 2 + _MSCAN_RESERVED_DSR_SIZE;
> +		}
> +	}
> +
> +	out_8(&regs->canrflg, MSCAN_RXF);
> +}
> +
> +static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame,
> +				u8 canrflg)
> +{
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +	struct net_device_stats *stats = &dev->stats;
> +	enum can_state old_state;
> +
> +	dev_dbg(dev->dev.parent, "error interrupt (canrflg=%#x)\n", canrflg);
> +	frame->can_id = CAN_ERR_FLAG;
> +
> +	if (canrflg & MSCAN_OVRIF) {
> +		frame->can_id |= CAN_ERR_CRTL;
> +		frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
> +		stats->rx_over_errors++;
> +		stats->rx_errors++;
> +	} else
> +		frame->data[1] = 0;

Add {} here as well.

> +
> +	old_state = check_set_state(dev, canrflg);
> +	/* State changed */
> +	if (old_state != priv->can.state) {
> +		switch (priv->can.state) {
> +		case CAN_STATE_ERROR_WARNING:
> +			frame->can_id |= CAN_ERR_CRTL;
> +			priv->can.can_stats.error_warning++;
> +			if ((priv->shadow_statflg & MSCAN_RSTAT_MSK) <
> +			    (canrflg & MSCAN_RSTAT_MSK))
> +				frame->data[1] |= CAN_ERR_CRTL_RX_WARNING;
> +

Remove this line please.

> +			if ((priv->shadow_statflg & MSCAN_TSTAT_MSK) <
> +			    (canrflg & MSCAN_TSTAT_MSK))
> +				frame->data[1] |= CAN_ERR_CRTL_TX_WARNING;
> +			break;
> +		case CAN_STATE_ERROR_PASSIVE:
> +			frame->can_id |= CAN_ERR_CRTL;
> +			priv->can.can_stats.error_passive++;
> +			frame->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
> +			break;
> +		case CAN_STATE_BUS_OFF:
> +			frame->can_id |= CAN_ERR_BUSOFF;
> +			/*
> +			 * The MSCAN on the MPC5200 does recover from bus-off
> +			 * automatically. To avoid that we stop the chip doing
> +			 * a light-weight stop (we are in irq-context).
> +			 */
> +			out_8(&regs->cantier, 0);
> +			out_8(&regs->canrier, 0);
> +			out_8(&regs->canctl0, in_8(&regs->canctl0) |
> +				MSCAN_SLPRQ | MSCAN_INITRQ);
> +			can_bus_off(dev);
> +			break;
> +		default:
> +			break;
> +		}
> +	}
> +	priv->shadow_statflg = canrflg & MSCAN_STAT_MSK;
> +	frame->can_dlc = CAN_ERR_DLC;
> +	out_8(&regs->canrflg, MSCAN_ERR_IF);
> +}
> +
> +static int mscan_rx_poll(struct napi_struct *napi, int quota)
> +{
> +	struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);
> +	struct net_device *dev = napi->dev;
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +	struct net_device_stats *stats = &dev->stats;
> +	int npackets = 0;
> +	int ret = 1;
> +	struct sk_buff *skb;
> +	struct can_frame *frame;
> +	u8 canrflg;
> +
> +	while (npackets < quota && ((canrflg = in_8(&regs->canrflg)) &
> +				    (MSCAN_RXF | MSCAN_ERR_IF))) {

To avoid the expression inside "while" I woud suggest:

	while (npackets < quota) {
		canrflg = in_8(&regs->canrflg);
		if (!(canrflg & (MSCAN_RXF | MSCAN_ERR_IF)))
			break;

> +
> +		skb = alloc_can_skb(dev, &frame);
> +		if (!skb) {
> +			if (printk_ratelimit())
> +				dev_notice(dev->dev.parent, "packet dropped\n");
> +			stats->rx_dropped++;
> +			out_8(&regs->canrflg, canrflg);
> +			continue;
> +		}
> +
> +		if (canrflg & MSCAN_RXF)
> +			mscan_get_rx_frame(dev, frame);
> +		 else if (canrflg & MSCAN_ERR_IF)

Remove space in front of "else".

> +			mscan_get_err_frame(dev, frame, canrflg);
> +
> +		stats->rx_packets++;
> +		stats->rx_bytes += frame->can_dlc;
> +		npackets++;
> +		netif_receive_skb(skb);
> +	}
> +
> +	if (!(in_8(&regs->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) {
> +		napi_complete(&priv->napi);
> +		clear_bit(F_RX_PROGRESS, &priv->flags);
> +		if (priv->can.state < CAN_STATE_BUS_OFF)
> +			out_8(&regs->canrier, priv->shadow_canrier);
> +		ret = 0;
> +	}
> +	return ret;
> +}
> +
> +static irqreturn_t mscan_isr(int irq, void *dev_id)
> +{
> +	struct net_device *dev = (struct net_device *)dev_id;
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +	struct net_device_stats *stats = &dev->stats;
> +	u8 cantier, cantflg, canrflg;
> +	irqreturn_t ret = IRQ_NONE;
> +
> +	cantier = in_8(&regs->cantier) & MSCAN_TXE;
> +	cantflg = in_8(&regs->cantflg) & cantier;
> +
> +	if (cantier && cantflg) {
> +

Please remove empty line above.

> +		struct list_head *tmp, *pos;
> +
> +		list_for_each_safe(pos, tmp, &priv->tx_head) {
> +			struct tx_queue_entry *entry =
> +			    list_entry(pos, struct tx_queue_entry, list);
> +			u8 mask = entry->mask;
> +
> +			if (!(cantflg & mask))
> +				continue;
> +
> +			out_8(&regs->cantbsel, mask);
> +			stats->tx_bytes += in_8(&regs->tx.dlr);
> +			stats->tx_packets++;
> +			can_get_echo_skb(dev, entry->id);
> +			priv->tx_active &= ~mask;
> +			list_del(pos);
> +		}
> +
> +		if (list_empty(&priv->tx_head)) {
> +			clear_bit(F_TX_WAIT_ALL, &priv->flags);
> +			clear_bit(F_TX_PROGRESS, &priv->flags);
> +			priv->cur_pri = 0;
> +		} else
> +			dev->trans_start = jiffies;

Add {} here as well.

> +
> +		if (!test_bit(F_TX_WAIT_ALL, &priv->flags))
> +			netif_wake_queue(dev);
> +
> +		out_8(&regs->cantier, priv->tx_active);
> +		ret = IRQ_HANDLED;
> +	}
> +
> +	canrflg = in_8(&regs->canrflg);
> +	if ((canrflg & ~MSCAN_STAT_MSK) &&
> +	    !test_and_set_bit(F_RX_PROGRESS, &priv->flags)) {
> +		if (canrflg & ~MSCAN_STAT_MSK) {
> +			priv->shadow_canrier = in_8(&regs->canrier);
> +			out_8(&regs->canrier, 0);
> +			napi_schedule(&priv->napi);
> +			ret = IRQ_HANDLED;
> +		} else
> +			clear_bit(F_RX_PROGRESS, &priv->flags);

Add {} here as well.

> +	}
> +	return ret;
> +}
> +
> +static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
> +{
> +

Please remove empty line above.

> +	struct mscan_priv *priv = netdev_priv(dev);
> +	int ret = 0;
> +
> +	if (!priv->open_time)
> +		return -EINVAL;
> +
> +	switch (mode) {
> +	case CAN_MODE_SLEEP:
> +	case CAN_MODE_STOP:
> +		netif_stop_queue(dev);
> +		mscan_set_mode(dev,
> +			       (mode ==
> +				CAN_MODE_STOP) ? MSCAN_INIT_MODE :
> +			       MSCAN_SLEEP_MODE);
> +		break;

We should remove the block above. There is no way to request these modes.

> +	case CAN_MODE_START:
> +		if (priv->can.state <= CAN_STATE_BUS_OFF)
> +			mscan_set_mode(dev, MSCAN_INIT_MODE);
> +		ret = mscan_start(dev);
> +		if (ret)
> +			break;
> +		if (netif_queue_stopped(dev))
> +			netif_wake_queue(dev);
> +		break;
> +
> +	default:
> +		ret = -EOPNOTSUPP;
> +		break;
> +	}
> +	return ret;
> +}
> +
> +static int mscan_do_set_bittiming(struct net_device *dev)
> +{
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +	struct can_bittiming *bt = &priv->can.bittiming;
> +	u8 btr0, btr1;
> +
> +	btr0 = BTR0_SET_BRP(bt->brp) | BTR0_SET_SJW(bt->sjw);
> +	btr1 = (BTR1_SET_TSEG1(bt->prop_seg + bt->phase_seg1) |
> +		BTR1_SET_TSEG2(bt->phase_seg2) |
> +		BTR1_SET_SAM(priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES));
> +
> +	dev_info(dev->dev.parent, "setting BTR0=0x%02x BTR1=0x%02x\n",
> +		btr0, btr1);
> +
> +	out_8(&regs->canbtr0, btr0);
> +	out_8(&regs->canbtr1, btr1);
> +
> +	return 0;
> +}
> +
> +static int mscan_open(struct net_device *dev)
> +{
> +	int ret;
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +
> +	/* common open */
> +	ret = open_candev(dev);
> +	if (ret)
> +		return ret;
> +
> +	napi_enable(&priv->napi);
> +
> +	ret = request_irq(dev->irq, mscan_isr, 0, dev->name, dev);
> +	if (ret < 0) {
> +		napi_disable(&priv->napi);
> +		printk(KERN_ERR "%s - failed to attach interrupt\n",
> +		       dev->name);
> +		return ret;
> +	}
> +
> +	priv->open_time = jiffies;
> +
> +	out_8(&regs->canctl1, in_8(&regs->canctl1) & ~MSCAN_LISTEN);

clrbits8?

> +
> +	ret = mscan_start(dev);
> +	if (ret)
> +		return ret;
> +
> +	netif_start_queue(dev);

The cleanup of this function is not OK. We need

  exit_free_irq:
	priv->open_time = 0; (Could be done later as well).
	free_irq()
  exit_napi_disable:
	napi_disable();
  	close_candev();

> +
> +	return 0;
> +}
> +
> +static int mscan_close(struct net_device *dev)
> +{
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +
> +	netif_stop_queue(dev);
> +	napi_disable(&priv->napi);
> +
> +	out_8(&regs->cantier, 0);
> +	out_8(&regs->canrier, 0);
> +	mscan_set_mode(dev, MSCAN_INIT_MODE);
> +	close_candev(dev);
> +	free_irq(dev->irq, dev);
> +	priv->open_time = 0;
> +
> +	return 0;
> +}
> +
> +static const struct net_device_ops mscan_netdev_ops = {
> +       .ndo_open               = mscan_open,
> +       .ndo_stop               = mscan_close,
> +       .ndo_start_xmit         = mscan_start_xmit,
> +};
> +
> +int register_mscandev(struct net_device *dev, int clock_src)
> +{
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +	u8 ctl1;
> +
> +	ctl1 = in_8(&regs->canctl1);
> +	if (clock_src)
> +		ctl1 |= MSCAN_CLKSRC;
> +	else
> +		ctl1 &= ~MSCAN_CLKSRC;
> +
> +	ctl1 |= MSCAN_CANE;
> +	out_8(&regs->canctl1, ctl1);
> +	udelay(100);
> +
> +	/* acceptance mask/acceptance code (accept everything) */
> +	out_be16(&regs->canidar1_0, 0);
> +	out_be16(&regs->canidar3_2, 0);
> +	out_be16(&regs->canidar5_4, 0);
> +	out_be16(&regs->canidar7_6, 0);
> +
> +	out_be16(&regs->canidmr1_0, 0xffff);
> +	out_be16(&regs->canidmr3_2, 0xffff);
> +	out_be16(&regs->canidmr5_4, 0xffff);
> +	out_be16(&regs->canidmr7_6, 0xffff);
> +	/* Two 32 bit Acceptance Filters */
> +	out_8(&regs->canidac, MSCAN_AF_32BIT);
> +
> +	mscan_set_mode(dev, MSCAN_INIT_MODE);
> +
> +	return register_candev(dev);
> +}
> +EXPORT_SYMBOL_GPL(register_mscandev);

There is no need to export this and all other functions below.

> +
> +void unregister_mscandev(struct net_device *dev)
> +{
> +	struct mscan_priv *priv = netdev_priv(dev);
> +	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +	mscan_set_mode(dev, MSCAN_INIT_MODE);
> +	out_8(&regs->canctl1, in_8(&regs->canctl1) & ~MSCAN_CANE);

clrbits8?

> +	unregister_candev(dev);
> +}
> +EXPORT_SYMBOL_GPL(unregister_mscandev);

See above.

> +
> +struct net_device *alloc_mscandev(void)
> +{
> +	struct net_device *dev;
> +	struct mscan_priv *priv;
> +	int i;
> +
> +	dev = alloc_candev(sizeof(struct mscan_priv), MSCAN_ECHO_SKB_MAX);
> +	if (!dev)
> +		return NULL;
> +	priv = netdev_priv(dev);
> +
> +	dev->netdev_ops = &mscan_netdev_ops;
> +
> +	dev->flags |= IFF_ECHO;	/* we support local echo */
> +
> +	netif_napi_add(dev, &priv->napi, mscan_rx_poll, 8);
> +
> +	priv->can.bittiming_const = &mscan_bittiming_const;
> +	priv->can.do_set_bittiming = mscan_do_set_bittiming;
> +	priv->can.do_set_mode = mscan_do_set_mode;
> +
> +	for (i = 0; i < TX_QUEUE_SIZE; i++) {
> +		priv->tx_queue[i].id = i;
> +		priv->tx_queue[i].mask = 1 << i;
> +	}
> +
> +	return dev;
> +}
> +EXPORT_SYMBOL_GPL(alloc_mscandev);

See above.

> +MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("CAN port driver for a MSCAN based chips");

As this is not a standalone module, the definitions above make little sense.

> diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
> new file mode 100644
> index 0000000..57820f5
> --- /dev/null
> +++ b/drivers/net/can/mscan/mscan.h
> @@ -0,0 +1,262 @@
> +/*
> + * Definitions of consts/structs to drive the Freescale MSCAN.
> + *
> + * Copyright (C) 2005-2006 Andrey Volkov <avolkov@varma-el.com>,
> + *                         Varma Electronics Oy
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the version 2 of the GNU General Public License
> + * as published by the Free Software Foundation
> + *
> + * 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
> + */
> +
> +#ifndef __MSCAN_H__
> +#define __MSCAN_H__
> +
> +#include <linux/types.h>
> +
> +/* MSCAN control register 0 (CANCTL0) bits */
> +#define MSCAN_RXFRM		0x80
> +#define MSCAN_RXACT		0x40
> +#define MSCAN_CSWAI		0x20
> +#define MSCAN_SYNCH		0x10
> +#define MSCAN_TIME		0x08
> +#define MSCAN_WUPE		0x04
> +#define MSCAN_SLPRQ		0x02
> +#define MSCAN_INITRQ		0x01
> +
> +/* MSCAN control register 1 (CANCTL1) bits */
> +#define MSCAN_CANE		0x80
> +#define MSCAN_CLKSRC		0x40
> +#define MSCAN_LOOPB		0x20
> +#define MSCAN_LISTEN		0x10
> +#define MSCAN_WUPM		0x04
> +#define MSCAN_SLPAK		0x02
> +#define MSCAN_INITAK		0x01
> +
> +/* Use the MPC5200 MSCAN variant? */
> +#ifdef CONFIG_PPC
> +#define MSCAN_FOR_MPC5200
> +#endif
> +
> +#ifdef MSCAN_FOR_MPC5200
> +#define MSCAN_CLKSRC_BUS	0
> +#define MSCAN_CLKSRC_XTAL	MSCAN_CLKSRC
> +#else
> +#define MSCAN_CLKSRC_BUS	MSCAN_CLKSRC
> +#define MSCAN_CLKSRC_XTAL	0
> +#endif
> +
> +/* MSCAN receiver flag register (CANRFLG) bits */
> +#define MSCAN_WUPIF		0x80
> +#define MSCAN_CSCIF		0x40
> +#define MSCAN_RSTAT1		0x20
> +#define MSCAN_RSTAT0		0x10
> +#define MSCAN_TSTAT1		0x08
> +#define MSCAN_TSTAT0		0x04
> +#define MSCAN_OVRIF		0x02
> +#define MSCAN_RXF		0x01
> +#define MSCAN_ERR_IF 		(MSCAN_OVRIF | MSCAN_CSCIF)
> +#define MSCAN_RSTAT_MSK		(MSCAN_RSTAT1 | MSCAN_RSTAT0)
> +#define MSCAN_TSTAT_MSK		(MSCAN_TSTAT1 | MSCAN_TSTAT0)
> +#define MSCAN_STAT_MSK		(MSCAN_RSTAT_MSK | MSCAN_TSTAT_MSK)
> +
> +#define MSCAN_STATE_BUS_OFF	(MSCAN_RSTAT1 | MSCAN_RSTAT0 | \
> +				 MSCAN_TSTAT1 | MSCAN_TSTAT0)
> +#define MSCAN_STATE_TX(canrflg)	(((canrflg)&MSCAN_TSTAT_MSK)>>2)
> +#define MSCAN_STATE_RX(canrflg)	(((canrflg)&MSCAN_RSTAT_MSK)>>4)
> +#define MSCAN_STATE_ACTIVE	0
> +#define MSCAN_STATE_WARNING	1
> +#define MSCAN_STATE_PASSIVE	2
> +#define MSCAN_STATE_BUSOFF	3
> +
> +/* MSCAN receiver interrupt enable register (CANRIER) bits */
> +#define MSCAN_WUPIE		0x80
> +#define MSCAN_CSCIE		0x40
> +#define MSCAN_RSTATE1		0x20
> +#define MSCAN_RSTATE0		0x10
> +#define MSCAN_TSTATE1		0x08
> +#define MSCAN_TSTATE0		0x04
> +#define MSCAN_OVRIE		0x02
> +#define MSCAN_RXFIE		0x01
> +
> +/* MSCAN transmitter flag register (CANTFLG) bits */
> +#define MSCAN_TXE2		0x04
> +#define MSCAN_TXE1		0x02
> +#define MSCAN_TXE0		0x01
> +#define MSCAN_TXE		(MSCAN_TXE2 | MSCAN_TXE1 | MSCAN_TXE0)
> +
> +/* MSCAN transmitter interrupt enable register (CANTIER) bits */
> +#define MSCAN_TXIE2		0x04
> +#define MSCAN_TXIE1		0x02
> +#define MSCAN_TXIE0		0x01
> +#define MSCAN_TXIE		(MSCAN_TXIE2 | MSCAN_TXIE1 | MSCAN_TXIE0)
> +
> +/* MSCAN transmitter message abort request (CANTARQ) bits */
> +#define MSCAN_ABTRQ2		0x04
> +#define MSCAN_ABTRQ1		0x02
> +#define MSCAN_ABTRQ0		0x01
> +
> +/* MSCAN transmitter message abort ack (CANTAAK) bits */
> +#define MSCAN_ABTAK2		0x04
> +#define MSCAN_ABTAK1		0x02
> +#define MSCAN_ABTAK0		0x01
> +
> +/* MSCAN transmit buffer selection (CANTBSEL) bits */
> +#define MSCAN_TX2		0x04
> +#define MSCAN_TX1		0x02
> +#define MSCAN_TX0		0x01
> +
> +/* MSCAN ID acceptance control register (CANIDAC) bits */
> +#define MSCAN_IDAM1		0x20
> +#define MSCAN_IDAM0		0x10
> +#define MSCAN_IDHIT2		0x04
> +#define MSCAN_IDHIT1		0x02
> +#define MSCAN_IDHIT0		0x01
> +
> +#define MSCAN_AF_32BIT		0x00
> +#define MSCAN_AF_16BIT		MSCAN_IDAM0
> +#define MSCAN_AF_8BIT		MSCAN_IDAM1
> +#define MSCAN_AF_CLOSED		(MSCAN_IDAM0|MSCAN_IDAM1)
> +#define MSCAN_AF_MASK		(~(MSCAN_IDAM0|MSCAN_IDAM1))
> +
> +/* MSCAN Miscellaneous Register (CANMISC) bits */
> +#define MSCAN_BOHOLD		0x01
> +
> +#ifdef MSCAN_FOR_MPC5200
> +#define _MSCAN_RESERVED_(n, num) u8 _res##n[num]
> +#define _MSCAN_RESERVED_DSR_SIZE	2
> +#else
> +#define _MSCAN_RESERVED_(n, num)
> +#define _MSCAN_RESERVED_DSR_SIZE	0
> +#endif
> +
> +/* Structure of the hardware registers */
> +struct mscan_regs {
> +	/* (see doc S12MSCANV3/D)		  MPC5200    MSCAN */
> +	u8 canctl0;				/* + 0x00     0x00 */
> +	u8 canctl1;				/* + 0x01     0x01 */
> +	_MSCAN_RESERVED_(1, 2);			/* + 0x02          */
> +	u8 canbtr0;				/* + 0x04     0x02 */
> +	u8 canbtr1;				/* + 0x05     0x03 */
> +	_MSCAN_RESERVED_(2, 2);			/* + 0x06          */
> +	u8 canrflg;				/* + 0x08     0x04 */
> +	u8 canrier;				/* + 0x09     0x05 */
> +	_MSCAN_RESERVED_(3, 2);			/* + 0x0a          */
> +	u8 cantflg;				/* + 0x0c     0x06 */
> +	u8 cantier;				/* + 0x0d     0x07 */
> +	_MSCAN_RESERVED_(4, 2);			/* + 0x0e          */
> +	u8 cantarq;				/* + 0x10     0x08 */
> +	u8 cantaak;				/* + 0x11     0x09 */
> +	_MSCAN_RESERVED_(5, 2);			/* + 0x12          */
> +	u8 cantbsel;				/* + 0x14     0x0a */
> +	u8 canidac;				/* + 0x15     0x0b */
> +	u8 reserved;				/* + 0x16     0x0c */
> +	_MSCAN_RESERVED_(6, 5);			/* + 0x17          */
> +#ifndef MSCAN_FOR_MPC5200
> +	u8 canmisc;				/*            0x0d */
> +#endif
> +	u8 canrxerr;				/* + 0x1c     0x0e */
> +	u8 cantxerr;				/* + 0x1d     0x0f */
> +	_MSCAN_RESERVED_(7, 2);			/* + 0x1e          */
> +	u16 canidar1_0;				/* + 0x20     0x10 */
> +	_MSCAN_RESERVED_(8, 2);			/* + 0x22          */
> +	u16 canidar3_2;				/* + 0x24     0x12 */
> +	_MSCAN_RESERVED_(9, 2);			/* + 0x26          */
> +	u16 canidmr1_0;				/* + 0x28     0x14 */
> +	_MSCAN_RESERVED_(10, 2);		/* + 0x2a          */
> +	u16 canidmr3_2;				/* + 0x2c     0x16 */
> +	_MSCAN_RESERVED_(11, 2);		/* + 0x2e          */
> +	u16 canidar5_4;				/* + 0x30     0x18 */
> +	_MSCAN_RESERVED_(12, 2);		/* + 0x32          */
> +	u16 canidar7_6;				/* + 0x34     0x1a */
> +	_MSCAN_RESERVED_(13, 2);		/* + 0x36          */
> +	u16 canidmr5_4;				/* + 0x38     0x1c */
> +	_MSCAN_RESERVED_(14, 2);		/* + 0x3a          */
> +	u16 canidmr7_6;				/* + 0x3c     0x1e */
> +	_MSCAN_RESERVED_(15, 2);		/* + 0x3e          */
> +	struct {
> +		u16 idr1_0;			/* + 0x40     0x20 */
> +		 _MSCAN_RESERVED_(16, 2);	/* + 0x42          */
> +		u16 idr3_2;			/* + 0x44     0x22 */
> +		 _MSCAN_RESERVED_(17, 2);	/* + 0x46          */
> +		u16 dsr1_0;			/* + 0x48     0x24 */
> +		 _MSCAN_RESERVED_(18, 2);	/* + 0x4a          */
> +		u16 dsr3_2;			/* + 0x4c     0x26 */
> +		 _MSCAN_RESERVED_(19, 2);	/* + 0x4e          */
> +		u16 dsr5_4;			/* + 0x50     0x28 */
> +		 _MSCAN_RESERVED_(20, 2);	/* + 0x52          */
> +		u16 dsr7_6;			/* + 0x54     0x2a */
> +		 _MSCAN_RESERVED_(21, 2);	/* + 0x56          */
> +		u8 dlr;				/* + 0x58     0x2c */
> +		 u8:8;				/* + 0x59     0x2d */
> +		 _MSCAN_RESERVED_(22, 2);	/* + 0x5a          */
> +		u16 time;			/* + 0x5c     0x2e */
> +	} rx;
> +	 _MSCAN_RESERVED_(23, 2);		/* + 0x5e          */
> +	struct {
> +		u16 idr1_0;			/* + 0x60     0x30 */
> +		 _MSCAN_RESERVED_(24, 2);	/* + 0x62          */
> +		u16 idr3_2;			/* + 0x64     0x32 */
> +		 _MSCAN_RESERVED_(25, 2);	/* + 0x66          */
> +		u16 dsr1_0;			/* + 0x68     0x34 */
> +		 _MSCAN_RESERVED_(26, 2);	/* + 0x6a          */
> +		u16 dsr3_2;			/* + 0x6c     0x36 */
> +		 _MSCAN_RESERVED_(27, 2);	/* + 0x6e          */
> +		u16 dsr5_4;			/* + 0x70     0x38 */
> +		 _MSCAN_RESERVED_(28, 2);	/* + 0x72          */
> +		u16 dsr7_6;			/* + 0x74     0x3a */
> +		 _MSCAN_RESERVED_(29, 2);	/* + 0x76          */
> +		u8 dlr;				/* + 0x78     0x3c */
> +		u8 tbpr;			/* + 0x79     0x3d */
> +		 _MSCAN_RESERVED_(30, 2);	/* + 0x7a          */
> +		u16 time;			/* + 0x7c     0x3e */
> +	} tx;
> +	 _MSCAN_RESERVED_(31, 2);		/* + 0x7e          */
> +} __attribute__ ((packed));
> +
> +#undef _MSCAN_RESERVED_
> +#define MSCAN_REGION 	sizeof(struct mscan)
> +
> +#define TX_QUEUE_SIZE	3
> +
> +struct tx_queue_entry {
> +	struct list_head list;
> +	u8 mask;
> +	u8 id;
> +};
> +
> +struct mscan_priv {
> +	struct can_priv can;	/* must be the first member */
> +	long open_time;
> +	unsigned long flags;
> +	void __iomem *reg_base;	/* ioremap'ed address to registers */
> +	u8 shadow_statflg;
> +	u8 shadow_canrier;
> +	u8 cur_pri;
> +	u8 prev_buf_id;
> +	u8 tx_active;
> +
> +	struct list_head tx_head;
> +	struct tx_queue_entry tx_queue[TX_QUEUE_SIZE];
> +	struct napi_struct napi;
> +};
> +
> +struct net_device *alloc_mscandev(void);

Either add "extern" above or remove it below.

> +/*
> + * clock_src:
> + *	1 = The MSCAN clock source is the onchip Bus Clock.
> + *	0 = The MSCAN clock source is the chip Oscillator Clock.
> + */
> +extern int register_mscandev(struct net_device *dev, int clock_src);
> +extern void unregister_mscandev(struct net_device *dev);
> +
> +#endif /* __MSCAN_H__ */

Wolfgang.

^ permalink raw reply

* Re: [PATCH] net/can: add driver for mscan family & mpc52xx_mscan
From: Wolfram Sang @ 2009-11-16 10:12 UTC (permalink / raw)
  To: Wolfgang Grandegger; +Cc: socketcan-core, netdev, David Miller, linuxppc-dev
In-Reply-To: <4AFFEC2C.6000106@grandegger.com>

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

David,

> >> Taken from socketcan-svn, fixed remaining todos, cleaned up, tested with a
> >> phyCORE-MPC5200B-IO and a custom board.
> >>
> >> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
> > 
> > Applied.
> 
> Unfortunately too early. I will send my review tomorrow. Sorry for the
> delay.

So, I'd assume that I now have to send an incremental patch instead of a V2?

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

^ permalink raw reply

* Re: [PATCH] net/can: add driver for mscan family & mpc52xx_mscan
From: David Miller @ 2009-11-16 10:21 UTC (permalink / raw)
  To: w.sang; +Cc: socketcan-core, netdev, linuxppc-dev
In-Reply-To: <20091116101205.GA30609@pengutronix.de>

From: Wolfram Sang <w.sang@pengutronix.de>
Date: Mon, 16 Nov 2009 11:12:05 +0100

>> >> Taken from socketcan-svn, fixed remaining todos, cleaned up, tested with a
>> >> phyCORE-MPC5200B-IO and a custom board.
>> >>
>> >> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
>> > 
>> > Applied.
>> 
>> Unfortunately too early. I will send my review tomorrow. Sorry for the
>> delay.
> 
> So, I'd assume that I now have to send an incremental patch instead of a V2?

Yes.

^ permalink raw reply

* Re: [PATCH] net/can: add driver for mscan family & mpc52xx_mscan
From: Wolfram Sang @ 2009-11-16 10:24 UTC (permalink / raw)
  To: Wolfgang Grandegger; +Cc: netdev, David Miller, socketcan-core, linuxppc-dev
In-Reply-To: <4B0110D5.6010405@grandegger.com>

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

Hi Wolfgang,

On Mon, Nov 16, 2009 at 09:44:05AM +0100, Wolfgang Grandegger wrote:
> Hi Wolfram,
> 
> thanks for pushing this driver to mainline. I think you should also add
> a CC to the Devicetree-discuss ML.

thank you very much for your review! I agree with nearly all of your points and will
send an update today. The only thing I have doubts about is removing those lines:

> +MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("CAN port driver for a MSCAN based chips");

I looked around in the kernel sources and found that they are often present in
generic modules, even if they can't be used without a wrapper (examples are all
files in drivers/i2c/algos or drivers/net/wireless/iwlwifi/iwl-core.c). As I'm
also a bit anxious to fiddle with other people's authorship, I'd prefer to keep
them.

Finally, I'll also try to test suspend/resume, but I have to find out if it is
supported on that board in general.

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

^ permalink raw reply

* Re: [v9 PATCH 0/9]: cpuidle: Cleanup cpuidle/ Introduce cpuidle to POWER.
From: Arun R Bharadwaj @ 2009-11-16 10:36 UTC (permalink / raw)
  To: Peter Zijlstra, Benjamin Herrenschmidt, Ingo Molnar,
	Vaidyanathan Srinivasan, Dipankar Sarma, Balbir Singh, Andi Kleen,
	Arun Bharadwaj
  Cc: linux-arch, linux-acpi, linuxppc-dev, linux-kernel
In-Reply-To: <20091016093850.GB27350@linux.vnet.ibm.com>

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-10-16 15:08:50]:

> Hi,
> 
> This patchset introduces cpuidle infrastructure to POWER, prototyping
> for pSeries, and also does a major refactoring of current x86 idle
> power management and a cleanup of cpuidle infrastructure.
> 
> This patch series has been in discussion for quite a while now and
> below are the links to the previous discussions.
> 
> Hopefully, this is ready to be included in the -tip tree.
> 
> v8 --> http://lkml.org/lkml/2009/10/8/82
> v7 --> http://lkml.org/lkml/2009/10/6/278
> v6 --> http://lkml.org/lkml/2009/9/22/180
> v5 --> http://lkml.org/lkml/2009/9/22/26
> v4 --> http://lkml.org/lkml/2009/9/1/133
> v3 --> http://lkml.org/lkml/2009/8/27/124
> v2 --> http://lkml.org/lkml/2009/8/26/233
> v1 --> http://lkml.org/lkml/2009/8/19/150
> 
> 
> Changes in this version:
> ----------------------------------------
>         *Added documentation for the new design regarding registration
>         of idle routines in Documentation/cpuidle/core.txt
> 
>         *Platforms which do not want the code bloat of cpuidle can
>         disable CONFIG_CPU_IDLE. Alternate definition of
>         cpuidle_idle_call is provided which would call the appropriate
>         idle routine provided by the arch without the overhead of
>         registration and governors.
>         (Thanks to Andi for raising this isuue)
> 
>         *I had missed a cpuidle_kick_cpus() in
>         cpuidle_pause_and_lock() which is called from the hotplug
>         path. So added that and tested this patchset by subjecting it
>         to cpuhotplug torture.
>         (Thanks to Balbir for noticing this)
> 
> 

Hi Peter,

Did you get time to look at this series?
Please let me know if we need any changes to this version to get it
merged.

thanks
> --arun
> 

^ permalink raw reply

* Re: [PATCH] macintosh: Explicitly set llseek to no_llseek in ans-lcd
From: Christoph Hellwig @ 2009-11-16 10:54 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Arnd Bergmann, Jonathan Corbet, Frederic Weisbecker, LKML,
	linuxppc-dev, John Kacur, Thomas Gleixner, Ingo Molnar, Alan Cox
In-Reply-To: <200911021651.53331.arnd@arndb.de>

On Mon, Nov 02, 2009 at 04:51:52PM +0100, Arnd Bergmann wrote:
> I looked at what places in the code manipulate file->f_pos directly
> and found that almost all the uses in driver code are broken because
> they don't take any locks. Most of them are in driver specific
> lseek operations. Others are in read/write methods and are even
> more broken because the change gets immediately overwritten by
> vfs_read/vfs_write when the driver method returns.
> 
> IMHO, we should complete the pushdown into all ioctl methods
> that John and Thomas have started working on, fixing the lseek
> methods in those files we touch.
> 
> When that is done, all interaction between default_llseek and
> driver locking has to be with explicit calls to lock_kernel
> in those drivers, so we can reasonably well script the search
> for drivers needing the BKL in llseek: everyhing that
>  a) defines file_operations without an llseek function,
>  b) touches f_pos somewhere, and
>  c) calls lock_kernel() somewhere
> That should only be a small number and when they are fixed,
> we can remove default_llseek and instead call generic_file_llseek
> for any file operation without a separate llseek method.

As mentioned before making generic_file_llseek the new default is
probably a bad idea.  The majority of our file_operations instances
don't actually support seeking, so no_llseek should become the new
default if you spend some effort on converting things.  Anything that
wants to allow seeking will have to set a llseek method.  This also
mirrors what we do for other file operations.  None of the major ones
has a non-trivial default, it's either silently succeeding for a
selected few like open or release or returning an error for operatings
that actually do something like read and write.

^ permalink raw reply

* Re: [PATCH] macintosh: Explicitly set llseek to no_llseek in ans-lcd
From: Arnd Bergmann @ 2009-11-16 12:09 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Arnd Bergmann, Jonathan Corbet, Frederic Weisbecker, LKML,
	linuxppc-dev, John Kacur, Thomas Gleixner, Ingo Molnar, Alan Cox
In-Reply-To: <20091116105427.GA17411@lst.de>

On Monday 16 November 2009, Christoph Hellwig wrote:
> As mentioned before making generic_file_llseek the new default is
> probably a bad idea.  The majority of our file_operations instances
> don't actually support seeking, so no_llseek should become the new
> default if you spend some effort on converting things.  Anything that
> wants to allow seeking will have to set a llseek method.  This also
> mirrors what we do for other file operations.  None of the major ones
> has a non-trivial default, it's either silently succeeding for a
> selected few like open or release or returning an error for operatings
> that actually do something like read and write.

Ok, good point.

Do you think we should also prevent pread/pwrite for devices without
an llseek operation, like nonseekable_open does? I guess that would
be consistent.

Then there is the point that (I forgot who) brought up that changing
code to do no_llseek is actually an ABI change. Even if the file
position is never used anywhere, some random user application might
expect a chardev not to return an error when its llseek method is
called, resulting in regressions.

	Arnd <><

^ permalink raw reply

* Re: [PATCH] net/can: add driver for mscan family & mpc52xx_mscan
From: Wolfgang Grandegger @ 2009-11-16 13:08 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: netdev, David Miller, socketcan-core, linuxppc-dev
In-Reply-To: <20091116102414.GB30609@pengutronix.de>

Hi Wolfram,

Wolfram Sang wrote:
> Hi Wolfgang,
> 
> On Mon, Nov 16, 2009 at 09:44:05AM +0100, Wolfgang Grandegger wrote:
>> Hi Wolfram,
>>
>> thanks for pushing this driver to mainline. I think you should also add
>> a CC to the Devicetree-discuss ML.
> 
> thank you very much for your review! I agree with nearly all of your points and will
> send an update today. The only thing I have doubts about is removing those lines:

Thanks, quite a bit of work.

>> +MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_DESCRIPTION("CAN port driver for a MSCAN based chips");
> 
> I looked around in the kernel sources and found that they are often present in
> generic modules, even if they can't be used without a wrapper (examples are all
> files in drivers/i2c/algos or drivers/net/wireless/iwlwifi/iwl-core.c). As I'm
> also a bit anxious to fiddle with other people's authorship, I'd prefer to keep
> them.

They do not harm, fine for me.

> Finally, I'll also try to test suspend/resume, but I have to find out if it is
> supported on that board in general.

Maybe somebody else already uses suspend/resume on a MPC5200 board with
Socket-CAN and could provide some feedback.

Wolfgang.

^ permalink raw reply

* [PATCH 0/4] mpc8349emitx: add bindings for GPIO, I2C and leds
From: Dmitry Eremin-Solenikov @ 2009-11-16 13:58 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev

Hello,

Please apply the following patches:

Dmitry Eremin-Solenikov (4):
      mpc8349emitx: add gpio controller declarations
      mpc8349emitx: populate I2C busses
      mpc8349emitx: add OF descriptions of LocalBus devices
      mpc8349emitx: add leds-gpio binding

 arch/powerpc/boot/dts/mpc8349emitx.dts |   82 +++++++++++++++++++++++++++++++-
 1 files changed, 81 insertions(+), 1 deletions(-)

^ permalink raw reply

* [PATCH 1/4] mpc8349emitx: add gpio controller declarations
From: Dmitry Eremin-Solenikov @ 2009-11-16 13:58 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <1258379934-32352-1-git-send-email-dbaryshkov@gmail.com>

mpc8349 bears two GPIO controllers. Enable support for them.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/powerpc/boot/dts/mpc8349emitx.dts |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index feeeb7f..16872c9 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -63,6 +63,24 @@
 			reg = <0x200 0x100>;
 		};
 
+		gpio1: gpio-controller@c00 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8349-gpio";
+			reg = <0xc00 0x100>;
+			interrupts = <74 0x8>;
+			interrupt-parent = <&ipic>;
+			gpio-controller;
+		};
+
+		gpio2: gpio-controller@d00 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8349-gpio";
+			reg = <0xd00 0x100>;
+			interrupts = <75 0x8>;
+			interrupt-parent = <&ipic>;
+			gpio-controller;
+		};
+
 		i2c@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-- 
1.6.5

^ permalink raw reply related

* [PATCH 3/4] mpc8349emitx: add OF descriptions of LocalBus devices
From: Dmitry Eremin-Solenikov @ 2009-11-16 13:58 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <1258379934-32352-1-git-send-email-dbaryshkov@gmail.com>

Describe all LocalBus chipselects on MPC8349E-MITX board. Also add flash
bindings.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/powerpc/boot/dts/mpc8349emitx.dts |   21 ++++++++++++++++++++-
 1 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 0fb78b2..097950c 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -374,7 +374,26 @@
 		compatible = "fsl,mpc8349e-localbus",
 			     "fsl,pq2pro-localbus";
 		reg = <0xe0005000 0xd8>;
-		ranges = <0x3 0x0 0xf0000000 0x210>;
+		ranges = <0x0 0x0 0xfe000000 0x1000000	/* flash */
+			  0x1 0x0 0xf8000000 0x20000	/* VSC 7385 */
+			  0x2 0x0 0xf9000000 0x200000	/* exp slot */
+			  0x3 0x0 0xf0000000 0x210>;	/* CF slot */
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0x0      0x0 0x800000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		flash@0,1 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x800000 0x800000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
 
 		pata@3,0 {
 			compatible = "fsl,mpc8349emitx-pata", "ata-generic";
-- 
1.6.5

^ permalink raw reply related

* [PATCH 2/4] mpc8349emitx: populate I2C busses
From: Dmitry Eremin-Solenikov @ 2009-11-16 13:58 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <1258379934-32352-1-git-send-email-dbaryshkov@gmail.com>

Add OF descriptions of EEPROM, two GPIO extenders and SPD hanging on I2C
on this board.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/powerpc/boot/dts/mpc8349emitx.dts |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 16872c9..0fb78b2 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -90,6 +90,12 @@
 			interrupts = <14 0x8>;
 			interrupt-parent = <&ipic>;
 			dfsrr;
+
+			eeprom: at24@50 {
+				compatible = "st-micro,24c256";
+				reg = <0x50>;
+			};
+
 		};
 
 		i2c@3100 {
@@ -109,6 +115,25 @@
 				interrupt-parent = <&ipic>;
 			};
 
+			pcf1: iexp@38 {
+				#gpio-cells = <2>;
+				compatible = "ti,pcf8574a";
+				reg = <0x38>;
+				gpio-controller;
+			};
+
+			pcf2: iexp@39 {
+				#gpio-cells = <2>;
+				compatible = "ti,pcf8574a";
+				reg = <0x39>;
+				gpio-controller;
+			};
+
+			spd: at24@51 {
+				compatible = "at24,spd";
+				reg = <0x51>;
+			};
+
 			mcu_pio: mcu@a {
 				#gpio-cells = <2>;
 				compatible = "fsl,mc9s08qg8-mpc8349emitx",
-- 
1.6.5

^ permalink raw reply related

* [PATCH 4/4] mpc8349emitx: add leds-gpio binding
From: Dmitry Eremin-Solenikov @ 2009-11-16 13:58 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <1258379934-32352-1-git-send-email-dbaryshkov@gmail.com>

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/powerpc/boot/dts/mpc8349emitx.dts |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 097950c..fb58a7c 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -318,6 +318,24 @@
 			reg = <0x700 0x100>;
 			device_type = "ipic";
 		};
+
+		gpio-leds {
+			compatible = "gpio-leds";
+
+			green {
+				label = "Green";
+				gpios = <&pcf1 0 1>;
+				linux,default-trigger = "heartbeat";
+			};
+
+			yellow {
+				label = "Yellow";
+				gpios = <&pcf1 1 1>;
+				/* linux,default-trigger = "heartbeat"; */
+				default-state = "on";
+			};
+		};
+
 	};
 
 	pci0: pci@e0008500 {
-- 
1.6.5

^ permalink raw reply related


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