LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Cell xmon helpers
From: Michael Ellerman @ 2006-10-12 12:03 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev, cbe-oss-dev

The following two patches add three commands to xmon for stopping,
restarting and dumping info about spus from xmon.

For the folks on linuxppc-dev, these patches depend on another patch
which isn't in the powerpc tree yet AFAIK, you can get it here:
http://kernel.org/pub/linux/kernel/people/arnd/patches/2.6.17-arnd8/broken-out/spu-add-attributes.diff

cheers

^ permalink raw reply

* PPChameleonEVB Newbie question
From: Adrian @ 2006-10-12 11:47 UTC (permalink / raw)
  To: linuxppc-embedded

Thanks Wolfgang.

I have now got the target compiling modules, kernel and everything.

For the record, I found it very difficult and time consuming.

To get to this stage I had to :-

Install Slack 8.1 kernel 2.4.18
Install ELDK version 4
as per docs add /usr/local/eldk/usr/bin:/usr/local/eldk/bin to PATH

set and export ARCH=ppc, CROSS_COMPILE=ppc_4xx-

make mrproper

make PPChameleon_defconfig

edit arch/ppc/platforms/4xx/Kconfig and add

'select WANT_EARLY_SERIAL'

to PPChameleonEVB definition

make menuconfig

make
then copy kernel to /tftpboot dir.

Board then booted ok provided the ELDK instructions about NFS shares were 
followed.

Under Slack 9 + 10.1 the kernel cross-compile barfed with 'clobber list' 
errors.

The dev host would cross-compile the modules, but wouldn't install them 
(INSTALL_MOD_PATH set).

After that i wanted to build the Kernel and modules on the target to make 
sure it was all ok, so :-

Installed Perl 5.6.4 with etc/Digest/MD5 copied from Perl 5.8.2 tree
(make modules_install wouldn't work without perl, and it isn't supplied 
AFAICS)
cd /usr/src/linux/include

ln -s asm-ppc asm

make mrproper
make PPChameleon_defconfig

edit arch/ppc/platforms/4xx/Kconfig and add

'select WANT_EARLY_SERIAL'

to PPChameleonEVB definition

make menuconfig

make
make modules
make modules_install

On the target it is (naturally) slow and you have to set up some NFS shared 
swap if you don't have much ram (i have 32mb and the kernel compile ran out 
of memory).

Out of the box i couldn't get ELDK 3.1.1 working at all, and the 
linux-2.4.20-pelk- thing wouldn't compile under either.

The main hurdle was needing to retro-grade the dev host.

Anyway. It is working happily now. Thanks for your help.

Adrian Atkins
IT Live Limited

tel: 0161 408 3327
fax: 08702 360 443
skype: adrianitlive
ES mob: (0034) 606806236 

^ permalink raw reply

* Re: [PATCH 1/4] powerpc: consolidate feature fixup code
From: Benjamin Herrenschmidt @ 2006-10-12 10:48 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev list
In-Reply-To: <1160646965.16101.4.camel@localhost.localdomain>


> >  void __init setup_system(void)
> >  {
> > +	extern unsigned int __start___ftr_fixup, __stop___ftr_fixup;
> > +	extern unsigned int __start___fw_ftr_fixup, __stop___fw_ftr_fixup;
> 
> 
> Every extern in a C file ... god kills a kitten! :)

Well... it's a bit special in this case.. just a reference to a section,
I'd rather keep it close to the only call site...

Ben.

^ permalink raw reply

* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: Peter Korsgaard @ 2006-10-12 10:34 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <609d5c8e0610101349w64cdd4ecjc5359ad8d1f5d635@mail.gmail.com>

>>>>> "David" == David Bolcsfoldi <dbolcsfoldi@gmail.com> writes:

Hi David,

David> here's a set of patches that adds support for Xilinx UART lite
David> devices. It has been tested on an ML403-FX using xapp902
David> (ml403_ppc_plb_temac) using a 2.6.18 kernel and a BusyBox
David> userspace.

I guess you didn't know, but there already exists a uartlite driver!
It unfortunately didn't made it into 2.6.19-rc1 because Russell
stopped maintaining serial stuff, but it's in -mm.

It also has an official lanana.org assigned set of device nodes.

I didn't look at your patch yet, but I think it would be more useful
to add any features missing to my driver than writing yet another
driver (I think we're up to 3 now).

-- 
Bye, Peter Korsgaard

^ permalink raw reply

* Re: Handling machine check exception
From: Matt Sealey @ 2006-10-12 10:34 UTC (permalink / raw)
  To: ganesh subramonian; +Cc: linuxppc-dev
In-Reply-To: <20061012045943.9389.qmail@web52403.mail.yahoo.com>

The G2 core definitely has a DAR register (SPR 19).

Look on the Freescale site for G2CORERM.pdf - this is
your reference manual, not the one specifically for the
8247.

-- 
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations

ganesh subramonian wrote:
> Hi,
> 
> I am trying to modify the machinecheck exception
> handler so that checks caused by data access to a
> particular address range can be ignored. In mpc866
> there is a register called DAR(Data Address Register)
> which gives the address[access to] which caused the
> exception. However this is not mentioned in the
> MPC8247 manual. Is there some equivalent register for
> 8247. (It seemed to me that the DAR should be a core
> register and hence should be there on 8247 also. but
> if i try to read i really dont get the address causing
> the error).
> 
> Or is there some way i can specify that access to a
> particular range of address should not cause a machine
> check?? Please help.
> 
> thanks
> ganesh
> 
> __________________________________________________
> Do You Yahoo!?
> Tired of spam?  Yahoo! Mail has the best spam protection around 
> http://mail.yahoo.com 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* SystemACE in a multiprocessor system
From: Alireza Sadri @ 2006-10-12 10:13 UTC (permalink / raw)
  To: linuxppc-embedded

Hi,

My question is about using only one SystemACE in a
board containing several Virtex4 chips all in the JTAG
chain.

How are kernels run on these processors, as only one
of these FPGAs are connected to this CompactFlash
directly.

Regards,
Ali R. Sadri,
Sarv-net Inc.
www.sarv-net.com

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

^ permalink raw reply

* unsubscribe
From: Usha Rani Konudula @ 2006-10-12  9:56 UTC (permalink / raw)
  To: linuxppc-dev list

unsubscribe

^ permalink raw reply

* Re: [PATCH 1/4] powerpc: consolidate feature fixup code
From: Michael Ellerman @ 2006-10-12  9:56 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list
In-Reply-To: <1160641793.4792.133.camel@localhost.localdomain>

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

On Thu, 2006-10-12 at 18:29 +1000, Benjamin Herrenschmidt wrote:
> There are currently two versions of the functions for applying the
> feature fixups, one for CPU features and one for firmware features. In
> addition, they are both in assembly.
> 
> This patch replaces them with a single C function. The call site is
> slightly moved on ppc64 as well to be called from C instead of from
> assembly, though it's a very small move, and thus shouldn't cause any
> problem (called at the start of setup_system() instead of just before
> calling it).

Nice to see it written in C :)

> Index: linux-cell/arch/powerpc/kernel/setup.h
> ===================================================================
> --- linux-cell.orig/arch/powerpc/kernel/setup.h	2006-10-12 14:24:10.000000000 +1000
> +++ linux-cell/arch/powerpc/kernel/setup.h	2006-10-12 17:46:02.000000000 +1000
> @@ -1,9 +1,12 @@
>  #ifndef _POWERPC_KERNEL_SETUP_H
>  #define _POWERPC_KERNEL_SETUP_H
>  
> -void check_for_initrd(void);
> -void do_init_bootmem(void);
> -void setup_panic(void);
> +extern void check_for_initrd(void);
> +extern void do_init_bootmem(void);
> +extern void setup_panic(void);
> +extern void do_feature_fixups(unsigned long offset, unsigned long value,
> +			      void *fixup_start, void *fixup_end);
> +
>  extern int do_early_xmon;
>  
>  #endif /* _POWERPC_KERNEL_SETUP_H */
> Index: linux-cell/arch/powerpc/kernel/setup_32.c
> ===================================================================
> --- linux-cell.orig/arch/powerpc/kernel/setup_32.c	2006-10-12 14:24:10.000000000 +1000
> +++ linux-cell/arch/powerpc/kernel/setup_32.c	2006-10-12 17:46:24.000000000 +1000
> @@ -90,6 +90,7 @@ int ucache_bsize;
>   */
>  unsigned long __init early_init(unsigned long dt_ptr)
>  {
> +	extern unsigned int __start___ftr_fixup, __stop___ftr_fixup;

> Index: linux-cell/arch/powerpc/kernel/setup_64.c
> ===================================================================
> --- linux-cell.orig/arch/powerpc/kernel/setup_64.c	2006-10-12 14:24:10.000000000 +1000
> +++ linux-cell/arch/powerpc/kernel/setup_64.c	2006-10-12 17:46:18.000000000 +1000
> @@ -346,8 +346,19 @@ static void __init initialize_cache_info
>   */
>  void __init setup_system(void)
>  {
> +	extern unsigned int __start___ftr_fixup, __stop___ftr_fixup;
> +	extern unsigned int __start___fw_ftr_fixup, __stop___fw_ftr_fixup;


Every extern in a C file ... god kills a kitten! :)

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

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

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

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

^ permalink raw reply

* [PATCH 4/4] powerpc: Cell timebase workaround
From: Benjamin Herrenschmidt @ 2006-10-12  8:30 UTC (permalink / raw)
  To: linuxppc-dev list

The Cell CPU timebase has an errata. When reading the entire 64 bits of
the timebase with one mftb instruction, there is a handful of cycles
window during which one might read a value with the low order 32 bits
already reset to 0x00000000 but the high order bits not yet incremeted
by one. Simply reading the timebase a second time if the low order bits
are 0 is enough (the second read will always miss that window).

Note that there is still a potential issue if the process gets
interrupted between the 2 reads for long enough that the second reads
pricely hits that same window on the next 32 bits wrap. However, this is
so extremely unlikely to happen that we choose not to do anything
against it (the 32 bits wrap happens every few seconds or so, in fact
every few minutes on IBM cell blades).

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

This is the "old" patch adapted to apply on top of the previous changes.
I'll post tomorrow a new version of the patch using a different
technique for the workaround

Index: linux-cell/arch/powerpc/kernel/vdso64/gettimeofday.S
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/vdso64/gettimeofday.S	2006-10-12 18:08:40.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/vdso64/gettimeofday.S	2006-10-12 18:18:15.000000000 +1000
@@ -11,6 +11,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
+
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 #include <asm/vdso.h>
@@ -229,8 +230,13 @@ V_FUNCTION_BEGIN(__do_get_xsec)
 	xor	r0,r8,r8		/* create dependency */
 	add	r3,r3,r0
 
-	/* Get TB & offset it */
-	mftb	r7
+	/* Get TB & offset it. We use the MFTB macro which will generate
+	 * workaround code for Cell. The macro will generate the ELF bits
+	 * for the CPU feature fixup though those aren't actually applied
+	 * on the vDSO, which means that the workaround will always be
+	 * executed if CONFIG_PPC_CELL is set.
+	 */
+	MFTB(r7)
 	ld	r9,CFG_TB_ORIG_STAMP(r3)
 	subf	r7,r9,r7
 
Index: linux-cell/include/asm-powerpc/cputable.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/cputable.h	2006-10-12 18:17:44.000000000 +1000
+++ linux-cell/include/asm-powerpc/cputable.h	2006-10-12 18:18:15.000000000 +1000
@@ -144,6 +144,7 @@ extern void do_cpu_ftr_fixups(unsigned l
 #define CPU_FTR_CI_LARGE_PAGE		LONG_ASM_CONST(0x0000100000000000)
 #define CPU_FTR_PAUSE_ZERO		LONG_ASM_CONST(0x0000200000000000)
 #define CPU_FTR_PURR			LONG_ASM_CONST(0x0000400000000000)
+#define CPU_FTR_CELL_TB_BUG		LONG_ASM_CONST(0x0000800000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -332,7 +333,7 @@ extern void do_cpu_ftr_fixups(unsigned l
 #define CPU_FTRS_CELL	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
-	    CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE)
+	    CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
 #define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
Index: linux-cell/include/asm-powerpc/ppc_asm.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/ppc_asm.h	2006-10-12 18:08:40.000000000 +1000
+++ linux-cell/include/asm-powerpc/ppc_asm.h	2006-10-12 18:18:15.000000000 +1000
@@ -29,10 +29,10 @@
 BEGIN_FTR_SECTION;							\
 	mfspr	ra,SPRN_PURR;		/* get processor util. reg */	\
 END_FTR_SECTION_IFSET(CPU_FTR_PURR);					\
-BEGIN_FTR_SECTION;							\
-	mftb	ra;			/* or get TB if no PURR */	\
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR);					\
-	ld	rb,PACA_STARTPURR(r13);				\
+BEGIN_FTR_SECTION_NESTED(96);						\
+	MFTB(ra);			/* or get TB if no PURR */	\
+END_FTR_SECTION_NESTED(CPU_FTR_PURR, 0, 96);				\
+	ld	rb,PACA_STARTPURR(r13);					\
 	std	ra,PACA_STARTPURR(r13);					\
 	subf	rb,rb,ra;		/* subtract start value */	\
 	ld	ra,PACA_USER_TIME(r13);					\
@@ -44,9 +44,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_PURR);				
 BEGIN_FTR_SECTION;							\
 	mfspr	ra,SPRN_PURR;		/* get processor util. reg */	\
 END_FTR_SECTION_IFSET(CPU_FTR_PURR);					\
-BEGIN_FTR_SECTION;							\
-	mftb	ra;			/* or get TB if no PURR */	\
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR);					\
+BEGIN_FTR_SECTION_NESTED(96);						\
+	MFTB(ra);			/* or get TB if no PURR */	\
+END_FTR_SECTION_NESTED(CPU_FTR_PURR, 0, 96);				\
 	ld	rb,PACA_STARTPURR(r13);				\
 	std	ra,PACA_STARTPURR(r13);					\
 	subf	rb,rb,ra;		/* subtract start value */	\
@@ -274,6 +274,18 @@ END_FTR_SECTION_IFSET(CPU_FTR_601)
 #define ISYNC_601
 #endif
 
+#ifdef CONFIG_PPC_CELL
+#define MFTB(dest)			\
+	mftb  dest;			\
+BEGIN_FTR_SECTION;			\
+	cmpwi dest,0;			\
+	bne+  90f;			\
+	mftb  dest;			\
+90:					\
+END_FTR_SECTION_IFSET(CPU_FTR_CELL_TB_BUG)
+#else
+#define MFTB(dest)			mftb dest
+#endif
 
 #ifndef CONFIG_SMP
 #define TLBSYNC
Index: linux-cell/include/asm-powerpc/reg.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/reg.h	2006-10-12 18:17:44.000000000 +1000
+++ linux-cell/include/asm-powerpc/reg.h	2006-10-12 18:19:05.000000000 +1000
@@ -617,9 +617,28 @@
 			asm volatile("mfspr %0," __stringify(rn) \
 				: "=r" (rval)); rval;})
 #define mtspr(rn, v)	asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v))
-
+#ifdef CONFIG_PPC_CELL
+#define mftb()		({unsigned long rval;				\
+			asm volatile(					\
+				"	mftb %0;\n"			\
+				"97:	cmpwi %0,0;\n"			\
+				"	bne+ 99f;\n"			\
+				"	mftb %0;\n"			\
+				"99:\n"					\
+				".section __ftr_fixup,\"a\"\n"		\
+				".align 3\n"				\
+				"98:\n"					\
+				"	.llong %1\n"			\
+				"	.llong %1\n"			\
+				"	.llong 97b-98b\n"		\
+				"	.llong 99b-98b\n"		\
+				".previous"				\
+			: "=r" (rval) : "i" (CPU_FTR_CELL_TB_BUG)); rval;})
+#else
 #define mftb()		({unsigned long rval;	\
 			asm volatile("mftb %0" : "=r" (rval)); rval;})
+#endif
+
 #define mftbl()		({unsigned long rval;	\
 			asm volatile("mftbl %0" : "=r" (rval)); rval;})
 
Index: linux-cell/include/asm-powerpc/time.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/time.h	2006-10-12 18:08:40.000000000 +1000
+++ linux-cell/include/asm-powerpc/time.h	2006-10-12 18:18:15.000000000 +1000
@@ -85,26 +85,28 @@ struct div_result {
 /* On ppc64 this gets us the whole timebase; on ppc32 just the lower half */
 static inline unsigned long get_tbl(void)
 {
-	unsigned long tbl;
-
 #if defined(CONFIG_403GCX)
+	unsigned long tbl;
 	asm volatile("mfspr %0, 0x3dd" : "=r" (tbl));
+	return tbl;
+#elif defined(CONFIG_PPC32)
+	return mftbl();
 #else
-	asm volatile("mftb %0" : "=r" (tbl));
+	return mftb();
 #endif
-	return tbl;
 }
 
 static inline unsigned int get_tbu(void)
 {
+#ifdef CONFIG_403GCX
 	unsigned int tbu;
-
-#if defined(CONFIG_403GCX)
 	asm volatile("mfspr %0, 0x3dc" : "=r" (tbu));
+	return tbu;
+#elif defined(CONFIG_PPC32)
+	return mftbu();
 #else
-	asm volatile("mftbu %0" : "=r" (tbu));
+	return mftb();
 #endif
-	return tbu;
 }
 
 static inline unsigned int get_rtcl(void)
Index: linux-cell/include/asm-powerpc/timex.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/timex.h	2006-10-12 18:17:44.000000000 +1000
+++ linux-cell/include/asm-powerpc/timex.h	2006-10-12 18:18:15.000000000 +1000
@@ -8,6 +8,7 @@
  */
 
 #include <asm/cputable.h>
+#include <asm/reg.h>
 
 #define CLOCK_TICK_RATE	1024000 /* Underlying HZ */
 
@@ -15,13 +16,11 @@ typedef unsigned long cycles_t;
 
 static inline cycles_t get_cycles(void)
 {
-	cycles_t ret;
-
 #ifdef __powerpc64__
-
-	__asm__ __volatile__("mftb %0" : "=r" (ret) : );
-
+	return mftb();
 #else
+	cycles_t ret;
+
 	/*
 	 * For the "cycle" counter we use the timebase lower half.
 	 * Currently only used on SMP.
@@ -41,9 +40,8 @@ static inline cycles_t get_cycles(void)
 		"	.long 99b-98b\n"
 		".previous"
 		: "=r" (ret) : "i" (CPU_FTR_601));
-#endif
-
 	return ret;
+#endif
 }
 
 #endif	/* __KERNEL__ */

^ permalink raw reply

* [PATCH 3/4] powerpc: Support feature fixups in vdso's
From: Benjamin Herrenschmidt @ 2006-10-12  8:30 UTC (permalink / raw)
  To: linuxppc-dev list

This patch is the "meat" of the series. It reworks the feature fixup
mecanism so vdso's can be fixed up. The main issue was that the
construct:

	.long	label  (or .llong on 64 bits)

will not work in the case of a shared library like the vdso. It will
generate an empty placeholder in the fixup table along with a reloc,
which is not something we can deal with in the vdso.

The idea here (thanks Alan Modra !) is to instead use something like:

1:
	.long	label - 1b

That is, the feature fixup tables no longer contain addresses of bits of
code to patch, but offsets of such code from the fixup table entry
itself. That is properly resolved by ld when building the .so's. I've
modified the fixup mecanism generically to use that method for the rest
of the kernel as well.

Another trick is that the 32 bits vDSO included in the 64 bits kernel
need to have a table in the 64 bits format. However, gas does not
support 32 bits code with a statement of the form:

	.llong	label - 1b  (Or even just .llong label)

That is, it cannot emit the right fixup/relocation for the linker to use
to assign a 32 bits address to an .llong field. Thus, in the specific
case of the 32 bits vdso built as part of the 64 bits kernel, we are
using a modified macro that generates:

	.long	0xffffffff
	.llong	label - 1b

Note that is assumes that the value is negative which is enforced by
the .lds (those offsets are always negative as the .text is always
before the fixup table and gas doesn't support emiting the reloc the
other way around).

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

Index: linux-cell/arch/powerpc/kernel/vdso.c
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/vdso.c	2006-10-12 18:08:40.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/vdso.c	2006-10-12 18:17:44.000000000 +1000
@@ -36,6 +36,8 @@
 #include <asm/vdso.h>
 #include <asm/vdso_datapage.h>
 
+#include "setup.h"
+
 #undef DEBUG
 
 #ifdef DEBUG
@@ -586,6 +588,43 @@ static __init int vdso_fixup_datapage(st
 	return 0;
 }
 
+
+static __init int vdso_fixup_features(struct lib32_elfinfo *v32,
+				      struct lib64_elfinfo *v64)
+{
+	void *start32;
+	unsigned long size32, offset32;
+
+#ifdef CONFIG_PPC64
+	void *start64;
+	unsigned long size64, offset64;
+
+	start64 = find_section64(v64->hdr, "__ftr_fixup", &size64);
+	if (start64)
+		do_feature_fixups(cur_cpu_spec->cpu_features,
+				  start64, start64 + size64);
+
+	start64 = find_section64(v64->hdr, "__fw_ftr_fixup", &size64);
+	if (start64)
+		do_feature_fixups(powerpc_firmware_features,
+				  start64, start64 + size64);
+#endif /* CONFIG_PPC64 */
+
+	start32 = find_section32(v32->hdr, "__ftr_fixup", &size32);
+	if (start32)
+		do_feature_fixups(cur_cpu_spec->cpu_features,
+				  start32, start32 + size32);
+
+#ifdef CONFIG_PPC64
+	start32 = find_section32(v32->hdr, "__fw_ftr_fixup", &size32);
+	if (start32)
+		do_feature_fixups(powerpc_firmware_features,
+				  start32, start32 + size32);
+#endif /* CONFIG_PPC64 */
+
+	return 0;
+}
+
 static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32,
 				       struct lib64_elfinfo *v64)
 {
@@ -634,6 +673,9 @@ static __init int vdso_setup(void)
 	if (vdso_fixup_datapage(&v32, &v64))
 		return -1;
 
+	if (vdso_fixup_features(&v32, &v64))
+		return -1;
+
 	if (vdso_fixup_alt_funcs(&v32, &v64))
 		return -1;
 
@@ -714,6 +756,7 @@ void __init vdso_init(void)
 	 * Setup the syscall map in the vDOS
 	 */
 	vdso_setup_syscall_map();
+
 	/*
 	 * Initialize the vDSO images in memory, that is do necessary
 	 * fixups of vDSO symbols, locate trampolines, etc...
Index: linux-cell/arch/powerpc/kernel/vdso32/vdso32.lds.S
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/vdso32/vdso32.lds.S	2006-10-12 18:08:40.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/vdso32/vdso32.lds.S	2006-10-12 18:17:44.000000000 +1000
@@ -32,6 +32,18 @@ SECTIONS
   PROVIDE (_etext = .);
   PROVIDE (etext = .);
 
+  . = ALIGN(8);
+  __ftr_fixup : {
+    *(__ftr_fixup)
+  }
+
+#ifdef CONFIG_PPC64
+  . = ALIGN(8);
+  __fw_ftr_fixup : {
+    *(__fw_ftr_fixup)
+  }
+#endif
+
   /* Other stuff is appended to the text segment: */
   .rodata		: { *(.rodata .rodata.* .gnu.linkonce.r.*) }
   .rodata1		: { *(.rodata1) }
Index: linux-cell/arch/powerpc/kernel/vdso64/vdso64.lds.S
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/vdso64/vdso64.lds.S	2006-10-12 18:08:40.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/vdso64/vdso64.lds.S	2006-10-12 18:17:44.000000000 +1000
@@ -31,6 +31,16 @@ SECTIONS
   PROVIDE (_etext = .);
   PROVIDE (etext = .);
 
+  . = ALIGN(8);
+  __ftr_fixup : {
+    *(__ftr_fixup)
+  }
+
+  . = ALIGN(8);
+  __fw_ftr_fixup : {
+    *(__fw_ftr_fixup)
+  }
+
   /* Other stuff is appended to the text segment: */
   .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
   .rodata1        : { *(.rodata1) }
Index: linux-cell/arch/powerpc/kernel/setup-common.c
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/setup-common.c	2006-10-12 18:17:37.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/setup-common.c	2006-10-12 18:17:44.000000000 +1000
@@ -521,27 +521,29 @@ void __init setup_panic(void)
 	atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block);
 }
 
-void do_feature_fixups(unsigned long offset, unsigned long value,
-		       void *fixup_start, void *fixup_end)
+void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
 {
 	struct fixup_entry {
 		unsigned long	mask;
 		unsigned long	value;
-		unsigned int	*start;
-		unsigned int	*end;
+		long		start_off;
+		long		end_off;
 	} *fcur, *fend;
 
 	fcur = fixup_start;
 	fend = fixup_end;
 
+	printk("fixup using section %p -> %p, value: 0x%lx\n",
+	       fixup_start, fixup_end, value);
+
 	for (; fcur < fend; fcur++) {
 		unsigned int *pcur, *pend;
 
 		if ((value & fcur->mask) == fcur->value)
 			continue;
 
-		pcur = fcur->start - offset;
-		pend = fcur->end - offset;
+		pcur = ((unsigned int *)fcur) + (fcur->start_off / 4);
+		pend = ((unsigned int *)fcur) + (fcur->end_off / 4);
 		for (; pcur < pend; pcur++) {
 			*pcur = 0x60000000u;
 			asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync"
Index: linux-cell/arch/powerpc/kernel/setup.h
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/setup.h	2006-10-12 18:17:37.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/setup.h	2006-10-12 18:17:44.000000000 +1000
@@ -4,8 +4,8 @@
 extern void check_for_initrd(void);
 extern void do_init_bootmem(void);
 extern void setup_panic(void);
-extern void do_feature_fixups(unsigned long offset, unsigned long value,
-			      void *fixup_start, void *fixup_end);
+extern void do_feature_fixups(unsigned long value, void *fixup_start,
+			      void *fixup_end);
 
 extern int do_early_xmon;
 
Index: linux-cell/arch/powerpc/kernel/setup_32.c
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/setup_32.c	2006-10-12 18:17:37.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/setup_32.c	2006-10-12 18:17:44.000000000 +1000
@@ -103,7 +103,7 @@ unsigned long __init early_init(unsigned
 	 */
 	identify_cpu(offset, 0);
 
-	do_feature_fixups(offset, cur_cpu_spec->cpu_features,
+	do_feature_fixups(cur_cpu_spec->cpu_features,
 			  &__start___ftr_fixup, &__stop___ftr_fixup);
 
 	return KERNELBASE + offset;
Index: linux-cell/arch/powerpc/kernel/setup_64.c
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/setup_64.c	2006-10-12 18:17:37.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/setup_64.c	2006-10-12 18:17:44.000000000 +1000
@@ -354,9 +354,9 @@ void __init setup_system(void)
 	/* Apply the CPUs-specific and firmware specific fixups to kernel
 	 * text (nop out sections not relevant to this CPU or this firmware)
 	 */
-	do_feature_fixups(0, cur_cpu_spec->cpu_features,
+	do_feature_fixups(cur_cpu_spec->cpu_features,
 			  &__start___ftr_fixup, &__stop___ftr_fixup);
-	do_feature_fixups(0, powerpc_firmware_features,
+	do_feature_fixups(powerpc_firmware_features,
 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
 
 	/*
Index: linux-cell/include/asm-powerpc/asm-compat.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/asm-compat.h	2006-10-12 18:08:40.000000000 +1000
+++ linux-cell/include/asm-powerpc/asm-compat.h	2006-10-12 18:17:44.000000000 +1000
@@ -14,6 +14,58 @@
 #  define ASM_CONST(x)		__ASM_CONST(x)
 #endif
 
+
+/*
+ * Feature section common macros
+ *
+ * Note that the entries now contain offsets between the table entry
+ * and the code rather than absolute code pointers in order to be
+ * useable with the vdso shared library. There is also an assumption
+ * that values will be negative, that is, the fixup table has to be
+ * located after the code it fixes up.
+ */
+#ifdef CONFIG_PPC64
+#ifdef __powerpc64__
+/* 64 bits kernel, 64 bits code */
+#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect)	\
+99:							\
+	.section sect,"a";				\
+	.align 3;					\
+98:						       	\
+	.llong msk;					\
+	.llong val;					\
+	.llong label##b-98b;				\
+	.llong 99b-98b;		 			\
+	.previous
+#else /* __powerpc64__ */
+/* 64 bits kernel, 32 bits code (ie. vdso32) */
+#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect)	\
+99:							\
+	.section sect,"a";				\
+	.align 3;					\
+98:						       	\
+	.llong msk;					\
+	.llong val;					\
+	.long 0xffffffff;      				\
+	.long label##b-98b;				\
+	.long 0xffffffff;	       			\
+	.long 99b-98b;		 			\
+	.previous
+#endif /* !__powerpc64__ */
+#else /* CONFIG_PPC64 */
+/* 32 bits kernel, 32 bits code */
+#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect)	\
+99:						       	\
+	.section sect,"a";			       	\
+	.align 2;				       	\
+98:						       	\
+	.long msk;				       	\
+	.long val;				       	\
+	.long label##b-98b;			       	\
+	.long 99b-98b;				       	\
+	.previous
+#endif /* !CONFIG_PPC64 */
+
 #ifdef __powerpc64__
 
 /* operations for longs and pointers */
Index: linux-cell/include/asm-powerpc/cputable.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/cputable.h	2006-10-12 18:17:37.000000000 +1000
+++ linux-cell/include/asm-powerpc/cputable.h	2006-10-12 18:17:44.000000000 +1000
@@ -432,32 +432,11 @@ static inline int cpu_has_feature(unsign
 #ifdef __ASSEMBLY__
 
 #define BEGIN_FTR_SECTION_NESTED(label)	label:
-#define BEGIN_FTR_SECTION		BEGIN_FTR_SECTION_NESTED(98)
-
-#ifndef __powerpc64__
-#define END_FTR_SECTION_NESTED(msk, val, label) \
-99:						\
-	.section __ftr_fixup,"a";		\
-	.align 2;				\
-	.long msk;				\
-	.long val;				\
-	.long label##b;				\
-	.long 99b;				\
-	.previous
-#else /* __powerpc64__ */
+#define BEGIN_FTR_SECTION		BEGIN_FTR_SECTION_NESTED(97)
 #define END_FTR_SECTION_NESTED(msk, val, label) \
-99:						\
-	.section __ftr_fixup,"a";		\
-	.align 3;				\
-	.llong msk;				\
-	.llong val;				\
-	.llong label##b;				\
-	.llong 99b;	 			\
-	.previous
-#endif /* __powerpc64__ */
-
+	MAKE_FTR_SECTION_ENTRY(msk, val, label, __ftr_fixup)
 #define END_FTR_SECTION(msk, val)		\
-	END_FTR_SECTION_NESTED(msk, val, 98)
+	END_FTR_SECTION_NESTED(msk, val, 97)
 
 #define END_FTR_SECTION_IFSET(msk)	END_FTR_SECTION((msk), (msk))
 #define END_FTR_SECTION_IFCLR(msk)	END_FTR_SECTION((msk), 0)
Index: linux-cell/include/asm-powerpc/firmware.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/firmware.h	2006-10-12 18:08:40.000000000 +1000
+++ linux-cell/include/asm-powerpc/firmware.h	2006-10-12 18:17:44.000000000 +1000
@@ -98,17 +98,12 @@ extern int fwnmi_active;
 
 #else /* __ASSEMBLY__ */
 
-#define BEGIN_FW_FTR_SECTION		96:
-
+#define BEGIN_FW_FTR_SECTION_NESTED(label)	label:
+#define BEGIN_FW_FTR_SECTION			BEGIN_FW_FTR_SECTION_NESTED(97)
+#define END_FW_FTR_SECTION_NESTED(msk, val, label) \
+	MAKE_FTR_SECTION_ENTRY(msk, val, label, __fw_ftr_fixup)
 #define END_FW_FTR_SECTION(msk, val)		\
-97:						\
-	.section __fw_ftr_fixup,"a";		\
-	.align 3;				\
-	.llong msk;				\
-	.llong val;				\
-	.llong 96b;				\
-	.llong 97b;				\
-	.previous
+	END_FW_FTR_SECTION_NESTED(msk, val, 97)
 
 #define END_FW_FTR_SECTION_IFSET(msk)	END_FW_FTR_SECTION((msk), (msk))
 #define END_FW_FTR_SECTION_IFCLR(msk)	END_FW_FTR_SECTION((msk), 0)
Index: linux-cell/include/asm-powerpc/timex.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/timex.h	2006-10-12 18:08:40.000000000 +1000
+++ linux-cell/include/asm-powerpc/timex.h	2006-10-12 18:17:44.000000000 +1000
@@ -30,13 +30,15 @@ static inline cycles_t get_cycles(void)
 	ret = 0;
 
 	__asm__ __volatile__(
-		"98:	mftb %0\n"
+		"97:	mftb %0\n"
 		"99:\n"
 		".section __ftr_fixup,\"a\"\n"
+		".align 2\n"
+		"98:\n"
 		"	.long %1\n"
 		"	.long 0\n"
-		"	.long 98b\n"
-		"	.long 99b\n"
+		"	.long 97b-98b\n"
+		"	.long 99b-98b\n"
 		".previous"
 		: "=r" (ret) : "i" (CPU_FTR_601));
 #endif

^ permalink raw reply

* [PATCH 2/4] powerpc: support nested cpu features
From: Benjamin Herrenschmidt @ 2006-10-12  8:29 UTC (permalink / raw)
  To: linuxppc-dev list

This patch adds some macros that can be used with an explicit label in
order to nest cpu features. This should be used very careful but is
necessary for the upcoming cell TB fixup.

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

Index: linux-cell/include/asm-powerpc/cputable.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/cputable.h	2006-10-11 13:20:08.000000000 +1000
+++ linux-cell/include/asm-powerpc/cputable.h	2006-10-11 13:20:26.000000000 +1000
@@ -431,30 +432,34 @@ static inline int cpu_has_feature(unsign
 
 #ifdef __ASSEMBLY__
 
-#define BEGIN_FTR_SECTION		98:
+#define BEGIN_FTR_SECTION_NESTED(label)	label:
+#define BEGIN_FTR_SECTION		BEGIN_FTR_SECTION_NESTED(98)
 
 #ifndef __powerpc64__
-#define END_FTR_SECTION(msk, val)		\
+#define END_FTR_SECTION_NESTED(msk, val, label) \
 99:						\
 	.section __ftr_fixup,"a";		\
 	.align 2;				\
 	.long msk;				\
 	.long val;				\
-	.long 98b;				\
+	.long label##b;				\
 	.long 99b;				\
 	.previous
 #else /* __powerpc64__ */
-#define END_FTR_SECTION(msk, val)		\
+#define END_FTR_SECTION_NESTED(msk, val, label) \
 99:						\
 	.section __ftr_fixup,"a";		\
 	.align 3;				\
 	.llong msk;				\
 	.llong val;				\
-	.llong 98b;				\
+	.llong label##b;				\
 	.llong 99b;	 			\
 	.previous
 #endif /* __powerpc64__ */
 
+#define END_FTR_SECTION(msk, val)		\
+	END_FTR_SECTION_NESTED(msk, val, 98)
+
 #define END_FTR_SECTION_IFSET(msk)	END_FTR_SECTION((msk), (msk))
 #define END_FTR_SECTION_IFCLR(msk)	END_FTR_SECTION((msk), 0)
 #endif /* __ASSEMBLY__ */

^ permalink raw reply

* [PATCH 1/4] powerpc: consolidate feature fixup code
From: Benjamin Herrenschmidt @ 2006-10-12  8:29 UTC (permalink / raw)
  To: linuxppc-dev list

There are currently two versions of the functions for applying the
feature fixups, one for CPU features and one for firmware features. In
addition, they are both in assembly.

This patch replaces them with a single C function. The call site is
slightly moved on ppc64 as well to be called from C instead of from
assembly, though it's a very small move, and thus shouldn't cause any
problem (called at the start of setup_system() instead of just before
calling it).

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


Index: linux-cell/arch/powerpc/kernel/head_64.S
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/head_64.S	2006-10-12 14:24:10.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/head_64.S	2006-10-12 14:24:54.000000000 +1000
@@ -2000,13 +2000,6 @@ _STATIC(start_here_common)
 	li	r0,0
 	stdu	r0,-STACK_FRAME_OVERHEAD(r1)
 
-	/* Apply the CPUs-specific fixups (nop out sections not relevant
-	 * to this CPU
-	 */
-	li	r3,0
-	bl	.do_cpu_ftr_fixups
-	bl	.do_fw_ftr_fixups
-
 	/* ptr to current */
 	LOAD_REG_IMMEDIATE(r4, init_task)
 	std	r4,PACACURRENT(r13)
Index: linux-cell/arch/powerpc/kernel/misc_64.S
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/misc_64.S	2006-10-12 14:24:10.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/misc_64.S	2006-10-12 14:24:54.000000000 +1000
@@ -277,99 +277,6 @@ _GLOBAL(identify_cpu)
 	mr	r3,r5
 	bctr
 
-/*
- * do_cpu_ftr_fixups - goes through the list of CPU feature fixups
- * and writes nop's over sections of code that don't apply for this cpu.
- * r3 = data offset (not changed)
- */
-_GLOBAL(do_cpu_ftr_fixups)
-	/* Get CPU 0 features */
-	LOAD_REG_IMMEDIATE(r6,cur_cpu_spec)
-	sub	r6,r6,r3
-	ld	r4,0(r6)
-	sub	r4,r4,r3
-	ld	r4,CPU_SPEC_FEATURES(r4)
-	/* Get the fixup table */
-	LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup)
-	sub	r6,r6,r3
-	LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup)
-	sub	r7,r7,r3
-	/* Do the fixup */
-1:	cmpld	r6,r7
-	bgelr
-	addi	r6,r6,32
-	ld	r8,-32(r6)	/* mask */
-	and	r8,r8,r4
-	ld	r9,-24(r6)	/* value */
-	cmpld	r8,r9
-	beq	1b
-	ld	r8,-16(r6)	/* section begin */
-	ld	r9,-8(r6)	/* section end */
-	subf.	r9,r8,r9
-	beq	1b
-	/* write nops over the section of code */
-	/* todo: if large section, add a branch at the start of it */
-	srwi	r9,r9,2
-	mtctr	r9
-	sub	r8,r8,r3
-	lis	r0,0x60000000@h	/* nop */
-3:	stw	r0,0(r8)
-	andi.	r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
-	beq	2f
-	dcbst	0,r8		/* suboptimal, but simpler */
-	sync
-	icbi	0,r8
-2:	addi	r8,r8,4
-	bdnz	3b
-	sync			/* additional sync needed on g4 */
-	isync
-	b	1b
-
-/*
- * do_fw_ftr_fixups - goes through the list of firmware feature fixups
- * and writes nop's over sections of code that don't apply for this firmware.
- * r3 = data offset (not changed)
- */
-_GLOBAL(do_fw_ftr_fixups)
-	/* Get firmware features */
-	LOAD_REG_IMMEDIATE(r6,powerpc_firmware_features)
-	sub	r6,r6,r3
-	ld	r4,0(r6)
-	/* Get the fixup table */
-	LOAD_REG_IMMEDIATE(r6,__start___fw_ftr_fixup)
-	sub	r6,r6,r3
-	LOAD_REG_IMMEDIATE(r7,__stop___fw_ftr_fixup)
-	sub	r7,r7,r3
-	/* Do the fixup */
-1:	cmpld	r6,r7
-	bgelr
-	addi	r6,r6,32
-	ld	r8,-32(r6)	/* mask */
-	and	r8,r8,r4
-	ld	r9,-24(r6)	/* value */
-	cmpld	r8,r9
-	beq	1b
-	ld	r8,-16(r6)	/* section begin */
-	ld	r9,-8(r6)	/* section end */
-	subf.	r9,r8,r9
-	beq	1b
-	/* write nops over the section of code */
-	/* todo: if large section, add a branch at the start of it */
-	srwi	r9,r9,2
-	mtctr	r9
-	sub	r8,r8,r3
-	lis	r0,0x60000000@h	/* nop */
-3:	stw	r0,0(r8)
-BEGIN_FTR_SECTION
-	dcbst	0,r8		/* suboptimal, but simpler */
-	sync
-	icbi	0,r8
-END_FTR_SECTION_IFSET(CPU_FTR_SPLIT_ID_CACHE)
-	addi	r8,r8,4
-	bdnz	3b
-	sync			/* additional sync needed on g4 */
-	isync
-	b	1b
 
 #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
 /*
Index: linux-cell/arch/powerpc/kernel/setup-common.c
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/setup-common.c	2006-10-12 14:24:10.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/setup-common.c	2006-10-12 17:46:02.000000000 +1000
@@ -520,3 +520,32 @@ void __init setup_panic(void)
 {
 	atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block);
 }
+
+void do_feature_fixups(unsigned long offset, unsigned long value,
+		       void *fixup_start, void *fixup_end)
+{
+	struct fixup_entry {
+		unsigned long	mask;
+		unsigned long	value;
+		unsigned int	*start;
+		unsigned int	*end;
+	} *fcur, *fend;
+
+	fcur = fixup_start;
+	fend = fixup_end;
+
+	for (; fcur < fend; fcur++) {
+		unsigned int *pcur, *pend;
+
+		if ((value & fcur->mask) == fcur->value)
+			continue;
+
+		pcur = fcur->start - offset;
+		pend = fcur->end - offset;
+		for (; pcur < pend; pcur++) {
+			*pcur = 0x60000000u;
+			asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync"
+			     : : "r" (pcur));
+		}
+	}
+}
Index: linux-cell/arch/powerpc/kernel/setup.h
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/setup.h	2006-10-12 14:24:10.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/setup.h	2006-10-12 17:46:02.000000000 +1000
@@ -1,9 +1,12 @@
 #ifndef _POWERPC_KERNEL_SETUP_H
 #define _POWERPC_KERNEL_SETUP_H
 
-void check_for_initrd(void);
-void do_init_bootmem(void);
-void setup_panic(void);
+extern void check_for_initrd(void);
+extern void do_init_bootmem(void);
+extern void setup_panic(void);
+extern void do_feature_fixups(unsigned long offset, unsigned long value,
+			      void *fixup_start, void *fixup_end);
+
 extern int do_early_xmon;
 
 #endif /* _POWERPC_KERNEL_SETUP_H */
Index: linux-cell/arch/powerpc/kernel/setup_32.c
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/setup_32.c	2006-10-12 14:24:10.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/setup_32.c	2006-10-12 17:46:24.000000000 +1000
@@ -90,6 +90,7 @@ int ucache_bsize;
  */
 unsigned long __init early_init(unsigned long dt_ptr)
 {
+	extern unsigned int __start___ftr_fixup, __stop___ftr_fixup;
 	unsigned long offset = reloc_offset();
 
 	/* First zero the BSS -- use memset_io, some platforms don't have
@@ -101,7 +102,9 @@ unsigned long __init early_init(unsigned
 	 * that depend on which cpu we have.
 	 */
 	identify_cpu(offset, 0);
-	do_cpu_ftr_fixups(offset);
+
+	do_feature_fixups(offset, cur_cpu_spec->cpu_features,
+			  &__start___ftr_fixup, &__stop___ftr_fixup);
 
 	return KERNELBASE + offset;
 }
Index: linux-cell/arch/powerpc/kernel/setup_64.c
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/setup_64.c	2006-10-12 14:24:10.000000000 +1000
+++ linux-cell/arch/powerpc/kernel/setup_64.c	2006-10-12 17:46:18.000000000 +1000
@@ -346,8 +346,19 @@ static void __init initialize_cache_info
  */
 void __init setup_system(void)
 {
+	extern unsigned int __start___ftr_fixup, __stop___ftr_fixup;
+	extern unsigned int __start___fw_ftr_fixup, __stop___fw_ftr_fixup;
+
 	DBG(" -> setup_system()\n");
 
+	/* Apply the CPUs-specific and firmware specific fixups to kernel
+	 * text (nop out sections not relevant to this CPU or this firmware)
+	 */
+	do_feature_fixups(0, cur_cpu_spec->cpu_features,
+			  &__start___ftr_fixup, &__stop___ftr_fixup);
+	do_feature_fixups(0, powerpc_firmware_features,
+			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
+
 	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
 	 */

^ permalink raw reply

* [PATCH 0/4] powerpc: feature fixup updates
From: Benjamin Herrenschmidt @ 2006-10-12  8:29 UTC (permalink / raw)
  To: linuxppc-dev list

The following patches are not to be merged yet as I haven't fully tested
them and I still want to do a few changes. I'm posting them for review
here.

They update the feature fixup mecanism to be nicer (C vs. asm), support
some level of nesting, and work with the vdso. This is needed for the
cell TB workaround which is the last patch of that serie

The remaining bits that need to be done before that queue can be merged,
in addition to testing, are:

 - add fixup of modules (should be easy. the __ftr_fixup and
__ftr_fw_fixup sections aren't fully filled at build time with modules,
there are relocs for them, so we need to be a bit careful there but it
should just work)

 - rework the cell workarounds to use a different method

^ permalink raw reply

* Handling machine check exception
From: ganesh subramonian @ 2006-10-12  4:59 UTC (permalink / raw)
  To: linuxppc-dev

Hi,

I am trying to modify the machinecheck exception
handler so that checks caused by data access to a
particular address range can be ignored. In mpc866
there is a register called DAR(Data Address Register)
which gives the address[access to] which caused the
exception. However this is not mentioned in the
MPC8247 manual. Is there some equivalent register for
8247. (It seemed to me that the DAR should be a core
register and hence should be there on 8247 also. but
if i try to read i really dont get the address causing
the error).

Or is there some way i can specify that access to a
particular range of address should not cause a machine
check?? Please help.

thanks
ganesh

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

^ permalink raw reply

* [PATCH 4/4] powerpc: Add simple memory allocator to bootwrapper
From: Mark A. Greer @ 2006-10-12  1:35 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20061012013223.GA9143@mag.az.mvista.com>

Provide primitive malloc, free, and realloc functions for bootwrapper.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---

 Makefile       |    2 
 simple_alloc.c |  147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 148 insertions(+), 1 deletion(-)
---

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index ef1bec4..895e537 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -41,7 +41,7 @@ zliblinuxheader := zlib.h zconf.h zutil.
 		$(addprefix $(obj)/,$(zlibheader))
 
 src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c ns16550.c \
-		serial.c div64.S util.S $(zlib)
+		serial.c simple_alloc.c div64.S util.S $(zlib)
 src-plat := of.c
 src-boot := crt0.S $(src-wlib) $(src-plat) empty.c
 
diff --git a/arch/powerpc/boot/simple_alloc.c b/arch/powerpc/boot/simple_alloc.c
new file mode 100644
index 0000000..478a381
--- /dev/null
+++ b/arch/powerpc/boot/simple_alloc.c
@@ -0,0 +1,147 @@
+/*
+ * Implement primitive realloc(3) functionality.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <stddef.h>
+#include "types.h"
+#include "page.h"
+#include "string.h"
+#include "ops.h"
+
+#define	ENTRY_BEEN_USED	0x01
+#define	ENTRY_IN_USE	0x02
+
+static struct alloc_info {
+	u32	flags;
+	u32	base;
+	u32	size;
+} *alloc_tbl;
+
+static u32 tbl_entries;
+static u32 alloc_min;
+static u32 space_left;
+
+/*
+ * First time an entry is used, its base and size are set.
+ * An entry can be freed and re-malloc'd but its base & size don't change.
+ * Should be smart enough for needs of bootwrapper.
+ */
+static void *simple_malloc(u32 size)
+{
+	u32 i;
+	struct alloc_info *p = alloc_tbl, *prevp = NULL;
+
+	if (size == 0)
+		goto err_out;
+
+	size = _ALIGN_UP(size, alloc_min);
+
+	for (i=0; i<tbl_entries; i++) {
+		if (!(p->flags & ENTRY_BEEN_USED)) { /* never been used */
+			if (size <= space_left) {
+				if (i > 0)
+					p->base = prevp->base + prevp->size;
+				p->size = size;
+				p->flags = ENTRY_BEEN_USED | ENTRY_IN_USE;
+				space_left -= size;
+				return (void *)p->base;
+			}
+			goto err_out; /* not enough space left */
+		}
+		/* reuse an entry keeping same base & size */
+		else if (!(p->flags & ENTRY_IN_USE) && (size <= p->size)) {
+			p->flags |= ENTRY_IN_USE;
+			return (void *)p->base;
+		}
+		prevp = p++;
+	}
+err_out:
+	return NULL;
+}
+
+static struct alloc_info *simple_find_entry(void *ptr)
+{
+	u32 i;
+	struct alloc_info *p = alloc_tbl;
+
+	for (i=0; i<tbl_entries; i++,p++) {
+		if (!(p->flags & ENTRY_BEEN_USED))
+			break;
+		if ((p->flags & ENTRY_IN_USE) && (p->base == (u32)ptr))
+			return p;
+	}
+	return NULL;
+}
+
+static void simple_free(void *ptr)
+{
+	struct alloc_info *p = simple_find_entry(ptr);
+
+	if (p != NULL)
+		p->flags &= ~ENTRY_IN_USE;
+}
+
+/*
+ * Change size of area pointed to by 'ptr' to 'size'.
+ * If 'ptr' is NULL, then its a malloc().  If 'size' is 0, then its a free().
+ * 'ptr' must be NULL or a value previously returned by simple_realloc().
+ */
+static void *simple_realloc(void *ptr, unsigned long size)
+{
+	struct alloc_info *p;
+	void *new;
+
+	if (size == 0) {
+		simple_free(ptr);
+		return NULL;
+	}
+
+	/* also malloc if ptr didn't come from simple_malloc/realloc */
+	if ((ptr == NULL) || ((p = simple_find_entry(ptr)) == NULL))
+		return simple_malloc(size);
+
+	if (size <= p->size) /* fits in current block */
+		return ptr;
+
+	new = simple_malloc(size);
+	memcpy(new, ptr, p->size);
+	simple_free(ptr);
+	return new;
+}
+
+/*
+ * Returns addr of first byte after heap so caller can see if it took
+ * too much space.  If so, change args & try again.
+ */
+void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
+		u32 max_allocs)
+{
+	u32 heap_base, tbl_size;
+
+	heap_size = _ALIGN_UP(heap_size, granularity);
+	alloc_min = granularity;
+	tbl_entries = max_allocs;
+
+	tbl_size = tbl_entries * sizeof(struct alloc_info);
+
+	alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8);
+	memset(alloc_tbl, 0, tbl_size);
+
+	heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min);
+
+	alloc_tbl[0].base = heap_base;
+	space_left = heap_size;
+
+	platform_ops.malloc = simple_malloc;
+	platform_ops.free = simple_free;
+	platform_ops.realloc = simple_realloc;
+
+	return (void *)(heap_base + heap_size);
+}

^ permalink raw reply related

* [PATCH 3/4] powerpc: Add non-OF serial console support
From: Mark A. Greer @ 2006-10-12  1:35 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20061012013223.GA9143@mag.az.mvista.com>

Add serial console support for non-OF systems.  There is a generic serial
console layer which calls a serial console driver.  Included is the serial
console driver for the ns16550 class of uarts.  Necessary support routines
are added as well.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---

 Makefile  |    4 -
 io.h      |   53 +++++++++++++++++++++++
 ns16550.c |   76 +++++++++++++++++++++++++++++++++
 serial.c  |  142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 util.S    |  101 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 374 insertions(+), 2 deletions(-)
---

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 8660cc5..ef1bec4 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -40,8 +40,8 @@ zliblinuxheader := zlib.h zconf.h zutil.
 $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
 		$(addprefix $(obj)/,$(zlibheader))
 
-src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c div64.S \
-		$(zlib)
+src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c ns16550.c \
+		serial.c div64.S util.S $(zlib)
 src-plat := of.c
 src-boot := crt0.S $(src-wlib) $(src-plat) empty.c
 
diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
new file mode 100644
index 0000000..32974ed
--- /dev/null
+++ b/arch/powerpc/boot/io.h
@@ -0,0 +1,53 @@
+#ifndef _IO_H
+#define __IO_H
+/*
+ * Low-level I/O routines.
+ *
+ * Copied from <file:include/asm-powerpc/io.h> (which has no copyright)
+ */
+static inline int in_8(const volatile unsigned char *addr)
+{
+	int ret;
+
+	__asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
+			     : "=r" (ret) : "m" (*addr));
+	return ret;
+}
+
+static inline void out_8(volatile unsigned char *addr, int val)
+{
+	__asm__ __volatile__("stb%U0%X0 %1,%0; sync"
+			     : "=m" (*addr) : "r" (val));
+}
+
+static inline unsigned in_le32(const volatile unsigned *addr)
+{
+	unsigned ret;
+
+	__asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
+			     : "=r" (ret) : "r" (addr), "m" (*addr));
+	return ret;
+}
+
+static inline unsigned in_be32(const volatile unsigned *addr)
+{
+	unsigned ret;
+
+	__asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
+			     : "=r" (ret) : "m" (*addr));
+	return ret;
+}
+
+static inline void out_le32(volatile unsigned *addr, int val)
+{
+	__asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
+			     : "r" (val), "r" (addr));
+}
+
+static inline void out_be32(volatile unsigned *addr, int val)
+{
+	__asm__ __volatile__("stw%U0%X0 %1,%0; sync"
+			     : "=m" (*addr) : "r" (val));
+}
+
+#endif /* _IO_H */
diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
new file mode 100644
index 0000000..e066942
--- /dev/null
+++ b/arch/powerpc/boot/ns16550.c
@@ -0,0 +1,76 @@
+/*
+ * 16550 serial console support.
+ *
+ * Original copied from <file:arch/ppc/boot/common/ns16550.c>
+ * (which had no copyright)
+ * Modifications: 2006 (c) MontaVista Software, Inc.
+ *
+ * Modified by: Mark A. Greer <mgreer@mvista.com>
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+#include "ops.h"
+
+#define UART_DLL	0	/* Out: Divisor Latch Low */
+#define UART_DLM	1	/* Out: Divisor Latch High */
+#define UART_FCR	2	/* Out: FIFO Control Register */
+#define UART_LCR	3	/* Out: Line Control Register */
+#define UART_MCR	4	/* Out: Modem Control Register */
+#define UART_LSR	5	/* In:  Line Status Register */
+#define UART_LSR_THRE	0x20	/* Transmit-hold-register empty */
+#define UART_LSR_DR	0x01	/* Receiver data ready */
+#define UART_MSR	6	/* In:  Modem Status Register */
+#define UART_SCR	7	/* I/O: Scratch Register */
+
+static unsigned char *reg_base;
+static u8 reg_shift;
+
+static int ns16550_open(void)
+{
+	out_8(reg_base + (UART_FCR << reg_shift), 0x06);
+	return 0;
+}
+
+static void ns16550_putc(unsigned char c)
+{
+	while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_THRE) == 0);
+	out_8(reg_base, c);
+}
+
+static unsigned char ns16550_getc(void)
+{
+	while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) == 0);
+	return in_8(reg_base);
+}
+
+static u8 ns16550_tstc(void)
+{
+	return ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) != 0);
+}
+
+int ns16550_console_init(void *devp, struct serial_console_data *scdp)
+{
+	u32 reg[2];
+	int n;
+
+	n = getprop(devp, "virtual-reg", &reg, sizeof(reg)) / 4;
+	if (n < 1)
+		return -1;
+	reg_base = (unsigned char *)((n == 1) ? reg[0] : reg[0] | reg[1]);
+
+	if (getprop(devp, "reg_shift", &reg_shift, sizeof(reg_shift))
+			!= sizeof(reg_shift))
+		reg_shift = 0;
+
+	scdp->open = ns16550_open;
+	scdp->putc = ns16550_putc;
+	scdp->getc = ns16550_getc;
+	scdp->tstc = ns16550_tstc;
+	scdp->close = NULL;
+
+	return 0;
+}
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
new file mode 100644
index 0000000..e8de4cf
--- /dev/null
+++ b/arch/powerpc/boot/serial.c
@@ -0,0 +1,142 @@
+/*
+ * Generic serial console support
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Code in serial_edit_cmdline() copied from <file:arch/ppc/boot/simple/misc.c>
+ * and was written by Matt Porter <mporter@kernel.crashing.org>.
+ *
+ * 2001,2006 (c) MontaVista Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+#include "ops.h"
+
+extern void udelay(long delay);
+
+static int serial_open(void)
+{
+	struct serial_console_data *scdp = console_ops.data;
+	return scdp->open();
+}
+
+static void serial_write(char *buf, int len)
+{
+	struct serial_console_data *scdp = console_ops.data;
+
+	while (*buf != '\0')
+		scdp->putc(*buf++);
+}
+
+static void serial_edit_cmdline(char *buf, int len)
+{
+	int timer = 0, count;
+	char ch, *cp;
+	struct serial_console_data *scdp = console_ops.data;
+
+	cp = buf;
+	count = strlen(buf);
+	cp = &buf[count];
+	count++;
+
+	while (timer++ < 5*1000) {
+		if (scdp->tstc()) {
+			while (((ch = scdp->getc()) != '\n') && (ch != '\r')) {
+				/* Test for backspace/delete */
+				if ((ch == '\b') || (ch == '\177')) {
+					if (cp != buf) {
+						cp--;
+						count--;
+						printf("\b \b");
+					}
+				/* Test for ^x/^u (and wipe the line) */
+				} else if ((ch == '\030') || (ch == '\025')) {
+					while (cp != buf) {
+						cp--;
+						count--;
+						printf("\b \b");
+					}
+				} else if (count < len) {
+						*cp++ = ch;
+						count++;
+						scdp->putc(ch);
+				}
+			}
+			break;  /* Exit 'timer' loop */
+		}
+		udelay(1000);  /* 1 msec */
+	}
+	*cp = 0;
+}
+
+static void serial_close(void)
+{
+	struct serial_console_data *scdp = console_ops.data;
+
+	if (scdp->close)
+		scdp->close();
+}
+
+static void *serial_get_stdout_devp(void)
+{
+	void *devp;
+	char devtype[MAX_PROP_LEN];
+	char path[MAX_PATH_LEN];
+
+	devp = finddevice("/chosen");
+	if (devp == NULL)
+		goto err_out;
+
+	if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) {
+		devp = finddevice(path);
+		if (devp == NULL)
+			goto err_out;
+
+		if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0)
+				&& !strcmp(devtype, "serial"))
+			return devp;
+	}
+err_out:
+	return NULL;
+}
+
+static struct serial_console_data serial_cd;
+
+/* Node's "compatible" property determines which serial driver to use */
+int serial_console_init(void)
+{
+	void *devp;
+	int rc = -1;
+	char compat[MAX_PROP_LEN];
+
+	devp = serial_get_stdout_devp();
+	if (devp == NULL)
+		goto err_out;
+
+	if (getprop(devp, "compatible", compat, sizeof(compat)) < 0)
+		goto err_out;
+
+	if (!strcmp(compat, "ns16550"))
+		rc = ns16550_console_init(devp, &serial_cd);
+
+	/* Add other serial console driver calls here */
+
+	if (!rc) {
+		console_ops.open = serial_open;
+		console_ops.write = serial_write;
+		console_ops.edit_cmdline = serial_edit_cmdline;
+		console_ops.close = serial_close;
+		console_ops.data = &serial_cd;
+
+		return 0;
+	}
+err_out:
+	return -1;
+}
diff --git a/arch/powerpc/boot/util.S b/arch/powerpc/boot/util.S
new file mode 100644
index 0000000..b8e1c23
--- /dev/null
+++ b/arch/powerpc/boot/util.S
@@ -0,0 +1,101 @@
+/*
+ * Copied from <file:arch/powerpc/kernel/misc_32.S>
+ *
+ * This file contains miscellaneous low-level functions.
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * kexec bits:
+ * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#include "ppc_asm.h"
+
+#define SPRN_PVR        0x11F   /* Processor Version Register */
+
+	.text
+/*
+ * complement mask on the msr then "or" some values on.
+ *     _nmask_and_or_msr(nmask, value_to_or)
+ */
+	.globl _nmask_and_or_msr
+_nmask_and_or_msr:
+	mfmsr	r0		/* Get current msr */
+	andc	r0,r0,r3	/* And off the bits set in r3 (first parm) */
+	or	r0,r0,r4	/* Or on the bits in r4 (second parm) */
+	SYNC			/* Some chip revs have problems here... */
+	mtmsr	r0		/* Update machine state */
+	isync
+	blr			/* Done */
+
+/* udelay (on non-601 processors) needs to know the period of the
+ * timebase in nanoseconds.  This used to be hardcoded to be 60ns
+ * (period of 66MHz/4).  Now a variable is used that is initialized to
+ * 60 for backward compatibility, but it can be overridden as necessary
+ * with code something like this:
+ *    extern unsigned long timebase_period_ns;
+ *    timebase_period_ns = 1000000000 / bd->bi_tbfreq;
+ */
+	.data
+	.globl timebase_period_ns
+timebase_period_ns:
+	.long	60
+
+	.text
+/*
+ * Delay for a number of microseconds
+ */
+	.globl	udelay
+udelay:
+	mfspr	r4,SPRN_PVR
+	srwi	r4,r4,16
+	cmpwi	0,r4,1		/* 601 ? */
+	bne	.udelay_not_601
+00:	li	r0,86	/* Instructions / microsecond? */
+	mtctr	r0
+10:	addi	r0,r0,0 /* NOP */
+	bdnz	10b
+	subic.	r3,r3,1
+	bne	00b
+	blr
+
+.udelay_not_601:
+	mulli	r4,r3,1000	/* nanoseconds */
+	/*  Change r4 to be the number of ticks using:
+	 *	(nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
+	 *  timebase_period_ns defaults to 60 (16.6MHz) */
+	mflr	r5
+	bl	0f
+0:	mflr	r6
+	mtlr	r5
+	lis	r5,0b@ha
+	addi	r5,r5,0b@l
+	subf	r5,r5,r6	/* In case we're relocated */
+	addis	r5,r5,timebase_period_ns@ha
+	lwz	r5,timebase_period_ns@l(r5)
+	add	r4,r4,r5
+	addi	r4,r4,-1
+	divw	r4,r4,r5	/* BUS ticks */
+1:	mftbu	r5
+	mftb	r6
+	mftbu	r7
+	cmpw	0,r5,r7
+	bne	1b		/* Get [synced] base time */
+	addc	r9,r6,r4	/* Compute end time */
+	addze	r8,r5
+2:	mftbu	r5
+	cmpw	0,r5,r8
+	blt	2b
+	bgt	3f
+	mftb	r6
+	cmpw	0,r6,r9
+	blt	2b
+3:	blr

^ permalink raw reply related

* [PATCH 2/4] powerpc: Add flatdevtree source
From: Mark A. Greer @ 2006-10-12  1:34 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20061012013223.GA9143@mag.az.mvista.com>

Add the latest version of the flatdevtree code and corresponding glue.

A phandle table now tracks values returned by ft_find_device().
The value returned by ft_find_device() is a phandle which is really
an index into the phandle table.  The phandle table contains the address
of the corresponding node.  When the flat dt is edited/moved, the node
pointers in the phandle table are updated accordingly so no phandles kept
by the caller become stale.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---

 Makefile           |    3 
 flatdevtree.c      |  876 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 flatdevtree.h      |   62 +++
 flatdevtree_env.h  |   47 ++
 flatdevtree_misc.c |   56 +++
 5 files changed, 1042 insertions(+), 2 deletions(-)
---

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 37ddfca..8660cc5 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -40,7 +40,8 @@ zliblinuxheader := zlib.h zconf.h zutil.
 $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
 		$(addprefix $(obj)/,$(zlibheader))
 
-src-wlib := string.S stdio.c main.c div64.S $(zlib)
+src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c div64.S \
+		$(zlib)
 src-plat := of.c
 src-boot := crt0.S $(src-wlib) $(src-plat) empty.c
 
diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c
new file mode 100644
index 0000000..0d24f50
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree.c
@@ -0,0 +1,876 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright Pantelis Antoniou 2006
+ * Copyright (C) IBM Corporation 2006
+ *
+ * Authors: Pantelis Antoniou <pantelis@embeddedalley.com>
+ *	    Hollis Blanchard <hollisb@us.ibm.com>
+ *	    Mark A. Greer <mgreer@mvista.com>
+ *	    Paul Mackerras <paulus@samba.org>
+ */
+
+#include <string.h>
+#include <stddef.h>
+#include "flatdevtree.h"
+#include "flatdevtree_env.h"
+
+#define _ALIGN(x, al)	(((x) + (al) - 1) & ~((al) - 1))
+
+/* Routines for keeping node ptrs returned by ft_find_device current */
+/* First entry not used b/c it would return 0 and be taken as NULL/error */
+static void *ft_node_add(struct ft_cxt *cxt, char *node)
+{
+	unsigned int i;
+
+	for (i = 1; i < cxt->nodes_used; i++)	/* already there? */
+		if (cxt->node_tbl[i] == node)
+			return (void *)i;
+
+	if (cxt->nodes_used < cxt->node_max) {
+		cxt->node_tbl[cxt->nodes_used] = node;
+		return (void *)cxt->nodes_used++;
+	}
+
+	return NULL;
+}
+
+static char *ft_node_ph2node(struct ft_cxt *cxt, const void *phandle)
+{
+	unsigned int i = (unsigned int)phandle;
+
+	if (i < cxt->nodes_used)
+		return cxt->node_tbl[i];
+	return NULL;
+}
+
+static void ft_node_update_before(struct ft_cxt *cxt, char *addr, int shift)
+{
+	unsigned int i;
+
+	if (shift == 0)
+		return;
+
+	for (i = 1; i < cxt->nodes_used; i++)
+		if (cxt->node_tbl[i] < addr)
+			cxt->node_tbl[i] += shift;
+}
+
+static void ft_node_update_after(struct ft_cxt *cxt, char *addr, int shift)
+{
+	unsigned int i;
+
+	if (shift == 0)
+		return;
+
+	for (i = 1; i < cxt->nodes_used; i++)
+		if (cxt->node_tbl[i] >= addr)
+			cxt->node_tbl[i] += shift;
+}
+
+/* Struct used to return info from ft_next() */
+struct ft_atom {
+	u32 tag;
+	const char *name;
+	void *data;
+	u32 size;
+};
+
+/* Set ptrs to current one's info; return addr of next one */
+static char *ft_next(struct ft_cxt *cxt, char *p, struct ft_atom *ret)
+{
+	u32 sz;
+
+	if (p >= cxt->rgn[FT_STRUCT].start + cxt->rgn[FT_STRUCT].size)
+		return NULL;
+
+	ret->tag = be32_to_cpu(*(u32 *) p);
+	p += 4;
+
+	switch (ret->tag) {	/* Tag */
+	case OF_DT_BEGIN_NODE:
+		ret->name = p;
+		ret->data = (void *)(p - 4);	/* start of node */
+		p += _ALIGN(strlen(p) + 1, 4);
+		break;
+	case OF_DT_PROP:
+		ret->size = sz = be32_to_cpu(*(u32 *) p);
+		ret->name = cxt->str_anchor + be32_to_cpu(*(u32 *) (p + 4));
+		ret->data = (void *)(p + 8);
+		p += 8 + _ALIGN(sz, 4);
+		break;
+	case OF_DT_END_NODE:
+	case OF_DT_NOP:
+		break;
+	case OF_DT_END:
+	default:
+		p = NULL;
+		break;
+	}
+
+	return p;
+}
+
+#define HDR_SIZE	_ALIGN(sizeof(struct boot_param_header), 8)
+#define EXPAND_INCR	1024	/* alloc this much extra when expanding */
+
+/* See if the regions are in the standard order and non-overlapping */
+static int ft_ordered(struct ft_cxt *cxt)
+{
+	char *p = (char *)cxt->bph + HDR_SIZE;
+	enum ft_rgn_id r;
+
+	for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
+		if (p > cxt->rgn[r].start)
+			return 0;
+		p = cxt->rgn[r].start + cxt->rgn[r].size;
+	}
+	return p <= (char *)cxt->bph + cxt->max_size;
+}
+
+/* Copy the tree to a newly-allocated region and put things in order */
+static int ft_reorder(struct ft_cxt *cxt, int nextra)
+{
+	unsigned long tot;
+	enum ft_rgn_id r;
+	char *p, *pend;
+	int stroff;
+
+	tot = HDR_SIZE + EXPAND_INCR;
+	for (r = FT_RSVMAP; r <= FT_STRINGS; ++r)
+		tot += cxt->rgn[r].size;
+	if (nextra > 0)
+		tot += nextra;
+	tot = _ALIGN(tot, 8);
+
+	if (!cxt->realloc)
+		return 0;
+	p = cxt->realloc(NULL, tot);
+	if (!p)
+		return 0;
+
+	memcpy(p, cxt->bph, sizeof(struct boot_param_header));
+	/* offsets get fixed up later */
+
+	cxt->bph = (struct boot_param_header *)p;
+	cxt->max_size = tot;
+	pend = p + tot;
+	p += HDR_SIZE;
+
+	memcpy(p, cxt->rgn[FT_RSVMAP].start, cxt->rgn[FT_RSVMAP].size);
+	cxt->rgn[FT_RSVMAP].start = p;
+	p += cxt->rgn[FT_RSVMAP].size;
+
+	memcpy(p, cxt->rgn[FT_STRUCT].start, cxt->rgn[FT_STRUCT].size);
+	ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
+			p - cxt->rgn[FT_STRUCT].start);
+	cxt->rgn[FT_STRUCT].start = p;
+
+	p = pend - cxt->rgn[FT_STRINGS].size;
+	memcpy(p, cxt->rgn[FT_STRINGS].start, cxt->rgn[FT_STRINGS].size);
+	stroff = cxt->str_anchor - cxt->rgn[FT_STRINGS].start;
+	cxt->rgn[FT_STRINGS].start = p;
+	cxt->str_anchor = p + stroff;
+
+	cxt->isordered = 1;
+	return 1;
+}
+
+static inline char *prev_end(struct ft_cxt *cxt, enum ft_rgn_id r)
+{
+	if (r > FT_RSVMAP)
+		return cxt->rgn[r - 1].start + cxt->rgn[r - 1].size;
+	return (char *)cxt->bph + HDR_SIZE;
+}
+
+static inline char *next_start(struct ft_cxt *cxt, enum ft_rgn_id r)
+{
+	if (r < FT_STRINGS)
+		return cxt->rgn[r + 1].start;
+	return (char *)cxt->bph + cxt->max_size;
+}
+
+/*
+ * See if we can expand region rgn by nextra bytes by using up
+ * free space after or before the region.
+ */
+static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
+		int nextra)
+{
+	char *p = *pp;
+	char *rgn_start, *rgn_end;
+
+	rgn_start = cxt->rgn[rgn].start;
+	rgn_end = rgn_start + cxt->rgn[rgn].size;
+	if (nextra <= 0 || rgn_end + nextra <= next_start(cxt, rgn)) {
+		/* move following stuff */
+		if (p < rgn_end) {
+			if (nextra < 0)
+				memmove(p, p - nextra, rgn_end - p + nextra);
+			else
+				memmove(p + nextra, p, rgn_end - p);
+			if (rgn == FT_STRUCT)
+				ft_node_update_after(cxt, p, nextra);
+		}
+		cxt->rgn[rgn].size += nextra;
+		if (rgn == FT_STRINGS)
+			/* assumes strings only added at beginning */
+			cxt->str_anchor += nextra;
+		return 1;
+	}
+	if (prev_end(cxt, rgn) <= rgn_start - nextra) {
+		/* move preceding stuff */
+		if (p > rgn_start) {
+			memmove(rgn_start - nextra, rgn_start, p - rgn_start);
+			if (rgn == FT_STRUCT)
+				ft_node_update_before(cxt, p, -nextra);
+		}
+		*p -= nextra;
+		cxt->rgn[rgn].start -= nextra;
+		cxt->rgn[rgn].size += nextra;
+		return 1;
+	}
+	return 0;
+}
+
+static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
+			 int nextra)
+{
+	unsigned long size, ssize, tot;
+	char *str, *next;
+	enum ft_rgn_id r;
+
+	if (!cxt->isordered && !ft_reorder(cxt, nextra))
+		return 0;
+	if (ft_shuffle(cxt, pp, rgn, nextra))
+		return 1;
+
+	/* See if there is space after the strings section */
+	ssize = cxt->rgn[FT_STRINGS].size;
+	if (cxt->rgn[FT_STRINGS].start + ssize
+			< (char *)cxt->bph + cxt->max_size) {
+		/* move strings up as far as possible */
+		str = (char *)cxt->bph + cxt->max_size - ssize;
+		cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
+		memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
+		cxt->rgn[FT_STRINGS].start = str;
+		/* enough space now? */
+		if (rgn >= FT_STRUCT && ft_shuffle(cxt, pp, rgn, nextra))
+			return 1;
+	}
+
+	/* how much total free space is there following this region? */
+	tot = 0;
+	for (r = rgn; r < FT_STRINGS; ++r) {
+		char *r_end = cxt->rgn[r].start + cxt->rgn[r].size;
+		tot += next_start(cxt, rgn) - r_end;
+	}
+
+	/* cast is to shut gcc up; we know nextra >= 0 */
+	if (tot < (unsigned int)nextra) {
+		/* have to reallocate */
+		char *newp, *oldp, *new_start;
+		int shift;
+
+		if (!cxt->realloc)
+			return 0;
+		size = _ALIGN(cxt->max_size + (nextra - tot) + EXPAND_INCR, 8);
+		newp = cxt->realloc(cxt->bph, size);
+		if (!newp)
+			return 0;
+		cxt->max_size = size;
+		oldp = (char *)cxt->bph;
+		shift = newp - oldp;
+
+		if (shift != 0) {	/* realloc can return same addr */
+			cxt->bph = (struct boot_param_header *)newp;
+			memmove(newp, oldp, sizeof(struct boot_param_header));
+			ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
+					shift);
+			for (r = FT_RSVMAP; r <= FT_STRUCT; ++r) {
+				new_start = cxt->rgn[r].start + shift;
+				memmove(new_start, cxt->rgn[r].start,
+					cxt->rgn[r].size);
+				cxt->rgn[r].start = new_start;
+			}
+			*pp += shift;
+		}
+
+		/* move strings up to the end */
+		str = newp + size - ssize;
+		cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
+		memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
+		cxt->rgn[FT_STRINGS].start = str;
+
+		if (ft_shuffle(cxt, pp, rgn, nextra))
+			return 1;
+	}
+
+	/* must be FT_RSVMAP and we need to move FT_STRUCT up */
+	if (rgn == FT_RSVMAP) {
+		next = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
+			+ nextra;
+		ssize = cxt->rgn[FT_STRUCT].size;
+		if (next + ssize >= cxt->rgn[FT_STRINGS].start)
+			return 0;	/* "can't happen" */
+		memmove(next, cxt->rgn[FT_STRUCT].start, ssize);
+		ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, nextra);
+		cxt->rgn[FT_STRUCT].start = next;
+
+		if (ft_shuffle(cxt, pp, rgn, nextra))
+			return 1;
+	}
+
+	return 0;		/* "can't happen" */
+}
+
+static void ft_put_word(struct ft_cxt *cxt, u32 v)
+{
+	*(u32 *) cxt->p = cpu_to_be32(v);
+	cxt->p += 4;
+}
+
+static void ft_put_bin(struct ft_cxt *cxt, const void *data, unsigned int sz)
+{
+	unsigned long sza = _ALIGN(sz, 4);
+
+	/* zero out the alignment gap if necessary */
+	if (sz < sza)
+		*(u32 *) (cxt->p + sza - 4) = 0;
+
+	/* copy in the data */
+	memcpy(cxt->p, data, sz);
+
+	cxt->p += sza;
+}
+
+int ft_begin_node(struct ft_cxt *cxt, const char *name)
+{
+	unsigned long nlen = strlen(name) + 1;
+	unsigned long len = 8 + _ALIGN(nlen, 4);
+
+	if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
+		return -1;
+	ft_put_word(cxt, OF_DT_BEGIN_NODE);
+	ft_put_bin(cxt, name, strlen(name) + 1);
+	return 0;
+}
+
+void ft_end_node(struct ft_cxt *cxt)
+{
+	ft_put_word(cxt, OF_DT_END_NODE);
+}
+
+void ft_nop(struct ft_cxt *cxt)
+{
+	if (ft_make_space(cxt, &cxt->p, FT_STRUCT, 4))
+		ft_put_word(cxt, OF_DT_NOP);
+}
+
+#define NO_STRING	0x7fffffff
+
+static int lookup_string(struct ft_cxt *cxt, const char *name)
+{
+	char *p, *end;
+
+	p = cxt->rgn[FT_STRINGS].start;
+	end = p + cxt->rgn[FT_STRINGS].size;
+	while (p < end) {
+		if (strcmp(p, (char *)name) == 0)
+			return p - cxt->str_anchor;
+		p += strlen(p) + 1;
+	}
+
+	return NO_STRING;
+}
+
+/* lookup string and insert if not found */
+static int map_string(struct ft_cxt *cxt, const char *name)
+{
+	int off;
+	char *p;
+
+	off = lookup_string(cxt, name);
+	if (off != NO_STRING)
+		return off;
+	p = cxt->rgn[FT_STRINGS].start;
+	if (!ft_make_space(cxt, &p, FT_STRINGS, strlen(name) + 1))
+		return NO_STRING;
+	strcpy(p, name);
+	return p - cxt->str_anchor;
+}
+
+int ft_prop(struct ft_cxt *cxt, const char *name, const void *data,
+		unsigned int sz)
+{
+	int off, len;
+
+	off = lookup_string(cxt, name);
+	if (off == NO_STRING)
+		return -1;
+
+	len = 12 + _ALIGN(sz, 4);
+	if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
+		return -1;
+
+	ft_put_word(cxt, OF_DT_PROP);
+	ft_put_word(cxt, sz);
+	ft_put_word(cxt, off);
+	ft_put_bin(cxt, data, sz);
+	return 0;
+}
+
+int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str)
+{
+	return ft_prop(cxt, name, str, strlen(str) + 1);
+}
+
+int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val)
+{
+	u32 v = cpu_to_be32((u32) val);
+
+	return ft_prop(cxt, name, &v, 4);
+}
+
+/* Calculate the size of the reserved map */
+static unsigned long rsvmap_size(struct ft_cxt *cxt)
+{
+	struct ft_reserve *res;
+
+	res = (struct ft_reserve *)cxt->rgn[FT_RSVMAP].start;
+	while (res->start || res->len)
+		++res;
+	return (char *)(res + 1) - cxt->rgn[FT_RSVMAP].start;
+}
+
+/* Calculate the size of the struct region by stepping through it */
+static unsigned long struct_size(struct ft_cxt *cxt)
+{
+	char *p = cxt->rgn[FT_STRUCT].start;
+	char *next;
+	struct ft_atom atom;
+
+	/* make check in ft_next happy */
+	if (cxt->rgn[FT_STRUCT].size == 0)
+		cxt->rgn[FT_STRUCT].size = 0xfffffffful - (unsigned long)p;
+
+	while ((next = ft_next(cxt, p, &atom)) != NULL)
+		p = next;
+	return p + 4 - cxt->rgn[FT_STRUCT].start;
+}
+
+/* add `adj' on to all string offset values in the struct area */
+static void adjust_string_offsets(struct ft_cxt *cxt, int adj)
+{
+	char *p = cxt->rgn[FT_STRUCT].start;
+	char *next;
+	struct ft_atom atom;
+	int off;
+
+	while ((next = ft_next(cxt, p, &atom)) != NULL) {
+		if (atom.tag == OF_DT_PROP) {
+			off = be32_to_cpu(*(u32 *) (p + 8));
+			*(u32 *) (p + 8) = cpu_to_be32(off + adj);
+		}
+		p = next;
+	}
+}
+
+/* start construction of the flat OF tree from scratch */
+void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+		void *(*realloc_fn) (void *, unsigned long))
+{
+	struct boot_param_header *bph = blob;
+	char *p;
+	struct ft_reserve *pres;
+
+	/* clear the cxt */
+	memset(cxt, 0, sizeof(*cxt));
+
+	cxt->bph = bph;
+	cxt->max_size = max_size;
+	cxt->realloc = realloc_fn;
+	cxt->isordered = 1;
+
+	/* zero everything in the header area */
+	memset(bph, 0, sizeof(*bph));
+
+	bph->magic = cpu_to_be32(OF_DT_HEADER);
+	bph->version = cpu_to_be32(0x10);
+	bph->last_comp_version = cpu_to_be32(0x10);
+
+	/* start pointers */
+	cxt->rgn[FT_RSVMAP].start = p = blob + HDR_SIZE;
+	cxt->rgn[FT_RSVMAP].size = sizeof(struct ft_reserve);
+	pres = (struct ft_reserve *)p;
+	cxt->rgn[FT_STRUCT].start = p += sizeof(struct ft_reserve);
+	cxt->rgn[FT_STRUCT].size = 4;
+	cxt->rgn[FT_STRINGS].start = blob + max_size;
+	cxt->rgn[FT_STRINGS].size = 0;
+
+	/* init rsvmap and struct */
+	pres->start = 0;
+	pres->len = 0;
+	*(u32 *) p = cpu_to_be32(OF_DT_END);
+
+	cxt->str_anchor = blob;
+}
+
+/* open up an existing blob to be examined or modified */
+int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+		unsigned int max_find_device,
+		void *(*realloc_fn) (void *, unsigned long))
+{
+	struct boot_param_header *bph = blob;
+
+	/* can't cope with version < 16 */
+	if (be32_to_cpu(bph->version) < 16)
+		return -1;
+
+	/* clear the cxt */
+	memset(cxt, 0, sizeof(*cxt));
+
+	/* alloc node_tbl to track node ptrs returned by ft_find_device */
+	++max_find_device;
+	cxt->node_tbl = realloc_fn(NULL, max_find_device * sizeof(char *));
+	if (!cxt->node_tbl)
+		return -1;
+	memset(cxt->node_tbl, 0, max_find_device * sizeof(char *));
+	cxt->node_max = max_find_device;
+	cxt->nodes_used = 1;	/* don't use idx 0 b/c looks like NULL */
+
+	cxt->bph = bph;
+	cxt->max_size = max_size;
+	cxt->realloc = realloc_fn;
+
+	cxt->rgn[FT_RSVMAP].start = blob + be32_to_cpu(bph->off_mem_rsvmap);
+	cxt->rgn[FT_RSVMAP].size = rsvmap_size(cxt);
+	cxt->rgn[FT_STRUCT].start = blob + be32_to_cpu(bph->off_dt_struct);
+	cxt->rgn[FT_STRUCT].size = struct_size(cxt);
+	cxt->rgn[FT_STRINGS].start = blob + be32_to_cpu(bph->off_dt_strings);
+	cxt->rgn[FT_STRINGS].size = be32_to_cpu(bph->dt_strings_size);
+	cxt->isordered = ft_ordered(cxt);
+
+	cxt->p = cxt->rgn[FT_STRUCT].start;
+	cxt->str_anchor = cxt->rgn[FT_STRINGS].start;
+
+	return 0;
+}
+
+/* add a reserver physical area to the rsvmap */
+int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
+{
+	char *p;
+	struct ft_reserve *pres;
+
+	p = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
+		- sizeof(struct ft_reserve);
+	if (!ft_make_space(cxt, &p, FT_RSVMAP, sizeof(struct ft_reserve)))
+		return -1;
+
+	pres = (struct ft_reserve *)p;
+	pres->start = cpu_to_be64(physaddr);
+	pres->len = cpu_to_be64(size);
+
+	return 0;
+}
+
+void ft_begin_tree(struct ft_cxt *cxt)
+{
+	cxt->p = cxt->rgn[FT_STRUCT].start;
+}
+
+void ft_end_tree(struct ft_cxt *cxt)
+{
+	struct boot_param_header *bph = cxt->bph;
+	char *p, *oldstr, *str, *endp;
+	unsigned long ssize;
+
+	if (!cxt->isordered)
+		return;		/* we haven't touched anything */
+
+	/* adjust string offsets */
+	oldstr = cxt->rgn[FT_STRINGS].start;
+	adjust_string_offsets(cxt, cxt->str_anchor - oldstr);
+
+	/* make strings end on 8-byte boundary */
+	ssize = cxt->rgn[FT_STRINGS].size;
+	endp = (char *)_ALIGN((unsigned long)cxt->rgn[FT_STRUCT].start
+			+ cxt->rgn[FT_STRUCT].size + ssize, 8);
+	str = endp - ssize;
+
+	/* move strings down to end of structs */
+	memmove(str, oldstr, ssize);
+	cxt->str_anchor = str;
+	cxt->rgn[FT_STRINGS].start = str;
+
+	/* fill in header fields */
+	p = (char *)bph;
+	bph->totalsize = cpu_to_be32(endp - p);
+	bph->off_mem_rsvmap = cpu_to_be32(cxt->rgn[FT_RSVMAP].start - p);
+	bph->off_dt_struct = cpu_to_be32(cxt->rgn[FT_STRUCT].start - p);
+	bph->off_dt_strings = cpu_to_be32(cxt->rgn[FT_STRINGS].start - p);
+	bph->dt_strings_size = cpu_to_be32(ssize);
+}
+
+void *ft_find_device(struct ft_cxt *cxt, const char *srch_path)
+{
+	char *node;
+
+	/* require absolute path */
+	if (srch_path[0] != '/')
+		return NULL;
+	node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path);
+	return ft_node_add(cxt, node);
+}
+
+void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path)
+{
+	struct ft_atom atom;
+	char *p;
+	const char *cp, *q;
+	int cl;
+	int depth = -1;
+	int dmatch = 0;
+	const char *path_comp[FT_MAX_DEPTH];
+
+	cp = srch_path;
+	cl = 0;
+	p = top;
+
+	while ((p = ft_next(cxt, p, &atom)) != NULL) {
+		switch (atom.tag) {
+		case OF_DT_BEGIN_NODE:
+			++depth;
+			if (depth != dmatch)
+				break;
+			cxt->genealogy[depth] = atom.data;
+			cxt->genealogy[depth + 1] = NULL;
+			if (depth && !(strncmp(atom.name, cp, cl) == 0
+					&& (atom.name[cl] == '/'
+						|| atom.name[cl] == '\0'
+						|| atom.name[cl] == '@')))
+				break;
+			path_comp[dmatch] = cp;
+			/* it matches so far, advance to next path component */
+			cp += cl;
+			/* skip slashes */
+			while (*cp == '/')
+				++cp;
+			/* we're done if this is the end of the string */
+			if (*cp == 0)
+				return atom.data;
+			/* look for end of this component */
+			q = strchr(cp, '/');
+			if (q)
+				cl = q - cp;
+			else
+				cl = strlen(cp);
+			++dmatch;
+			break;
+		case OF_DT_END_NODE:
+			if (depth == 0)
+				return NULL;
+			if (dmatch > depth) {
+				--dmatch;
+				cl = cp - path_comp[dmatch] - 1;
+				cp = path_comp[dmatch];
+				while (cl > 0 && cp[cl - 1] == '/')
+					--cl;
+			}
+			--depth;
+			break;
+		}
+	}
+	return NULL;
+}
+
+void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
+{
+	void *node;
+	int d;
+	struct ft_atom atom;
+	char *p;
+
+	node = ft_node_ph2node(cxt, phandle);
+	if (node == NULL)
+		return NULL;
+
+	for (d = 0; cxt->genealogy[d] != NULL; ++d)
+		if (cxt->genealogy[d] == node)
+			return cxt->genealogy[d > 0 ? d - 1 : 0];
+
+	/* have to do it the hard way... */
+	p = cxt->rgn[FT_STRUCT].start;
+	d = 0;
+	while ((p = ft_next(cxt, p, &atom)) != NULL) {
+		switch (atom.tag) {
+		case OF_DT_BEGIN_NODE:
+			cxt->genealogy[d] = atom.data;
+			if (node == atom.data) {
+				/* found it */
+				cxt->genealogy[d + 1] = NULL;
+				return d > 0 ? cxt->genealogy[d - 1] : node;
+			}
+			++d;
+			break;
+		case OF_DT_END_NODE:
+			--d;
+			break;
+		}
+	}
+	return NULL;
+}
+
+int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+		void *buf, const unsigned int buflen)
+{
+	struct ft_atom atom;
+	void *node;
+	char *p;
+	int depth;
+	unsigned int size;
+
+	node = ft_node_ph2node(cxt, phandle);
+	if (node == NULL)
+		return -1;
+
+	depth = 0;
+	p = (char *)node;
+
+	while ((p = ft_next(cxt, p, &atom)) != NULL) {
+		switch (atom.tag) {
+		case OF_DT_BEGIN_NODE:
+			++depth;
+			break;
+		case OF_DT_PROP:
+			if ((depth != 1) || strcmp(atom.name, propname))
+				break;
+			size = min(atom.size, buflen);
+			memcpy(buf, atom.data, size);
+			return atom.size;
+		case OF_DT_END_NODE:
+			if (--depth <= 0)
+				return -1;
+		}
+	}
+	return -1;
+}
+
+int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+		const void *buf, const unsigned int buflen)
+{
+	struct ft_atom atom;
+	void *node;
+	char *p, *next;
+	int nextra, depth;
+
+	node = ft_node_ph2node(cxt, phandle);
+	if (node == NULL)
+		return -1;
+
+	depth = 0;
+	p = node;
+
+	while ((next = ft_next(cxt, p, &atom)) != NULL) {
+		switch (atom.tag) {
+		case OF_DT_BEGIN_NODE:
+			++depth;
+			break;
+		case OF_DT_END_NODE:
+			if (--depth > 0)
+				break;
+			/* haven't found the property, insert here */
+			cxt->p = p;
+			return ft_prop(cxt, propname, buf, buflen);
+		case OF_DT_PROP:
+			if ((depth != 1) || strcmp(atom.name, propname))
+				break;
+			/* found an existing property, overwrite it */
+			nextra = _ALIGN(buflen, 4) - _ALIGN(atom.size, 4);
+			cxt->p = atom.data;
+			if (nextra && !ft_make_space(cxt, &cxt->p, FT_STRUCT,
+						nextra))
+				return -1;
+			*(u32 *) (cxt->p - 8) = cpu_to_be32(buflen);
+			ft_put_bin(cxt, buf, buflen);
+			return 0;
+		}
+		p = next;
+	}
+	return -1;
+}
+
+int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname)
+{
+	struct ft_atom atom;
+	void *node;
+	char *p, *next;
+	int size;
+
+	node = ft_node_ph2node(cxt, phandle);
+	if (node == NULL)
+		return -1;
+
+	p = node;
+	while ((next = ft_next(cxt, p, &atom)) != NULL) {
+		switch (atom.tag) {
+		case OF_DT_BEGIN_NODE:
+		case OF_DT_END_NODE:
+			return -1;
+		case OF_DT_PROP:
+			if (strcmp(atom.name, propname))
+				break;
+			/* found the property, remove it */
+			size = 12 + -_ALIGN(atom.size, 4);
+			cxt->p = p;
+			if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, -size))
+				return -1;
+			return 0;
+		}
+		p = next;
+	}
+	return -1;
+}
+
+void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path)
+{
+	struct ft_atom atom;
+	char *p, *next;
+	int depth = 0;
+
+	p = cxt->rgn[FT_STRUCT].start;
+	while ((next = ft_next(cxt, p, &atom)) != NULL) {
+		switch (atom.tag) {
+		case OF_DT_BEGIN_NODE:
+			++depth;
+			if (depth == 1 && strcmp(atom.name, path) == 0)
+				/* duplicate node path, return error */
+				return NULL;
+			break;
+		case OF_DT_END_NODE:
+			--depth;
+			if (depth > 0)
+				break;
+			/* end of node, insert here */
+			cxt->p = p;
+			ft_begin_node(cxt, path);
+			ft_end_node(cxt);
+			return p;
+		}
+		p = next;
+	}
+	return NULL;
+}
diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h
index 761c8dc..b9cd9f6 100644
--- a/arch/powerpc/boot/flatdevtree.h
+++ b/arch/powerpc/boot/flatdevtree.h
@@ -17,7 +17,7 @@
 #ifndef FLATDEVTREE_H
 #define FLATDEVTREE_H
 
-#include "types.h"
+#include "flatdevtree_env.h"
 
 /* Definitions used by the flattened device tree */
 #define OF_DT_HEADER            0xd00dfeed      /* marker */
@@ -43,4 +43,64 @@ struct boot_param_header {
 	u32 dt_strings_size;    /* size of the DT strings block */
 };
 
+struct ft_reserve {
+	u64 start;
+	u64 len;
+};
+
+struct ft_region {
+	char *start;
+	unsigned long size;
+};
+
+enum ft_rgn_id {
+	FT_RSVMAP,
+	FT_STRUCT,
+	FT_STRINGS,
+	FT_N_REGION
+};
+
+#define FT_MAX_DEPTH	50
+
+struct ft_cxt {
+	struct boot_param_header *bph;
+	int max_size;           /* maximum size of tree */
+	int isordered;		/* everything in standard order */
+	void *(*realloc)(void *, unsigned long);
+	char *str_anchor;
+	char *p;		/* current insertion point in structs */
+	struct ft_region rgn[FT_N_REGION];
+	void *genealogy[FT_MAX_DEPTH+1];
+	char **node_tbl;
+	unsigned int node_max;
+	unsigned int nodes_used;
+};
+
+int ft_begin_node(struct ft_cxt *cxt, const char *name);
+void ft_end_node(struct ft_cxt *cxt);
+
+void ft_begin_tree(struct ft_cxt *cxt);
+void ft_end_tree(struct ft_cxt *cxt);
+
+void ft_nop(struct ft_cxt *cxt);
+int ft_prop(struct ft_cxt *cxt, const char *name,
+	    const void *data, unsigned int sz);
+int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str);
+int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val);
+void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+	      void *(*realloc_fn)(void *, unsigned long));
+int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+		unsigned int max_find_device,
+		void *(*realloc_fn)(void *, unsigned long));
+int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size);
+
+void ft_dump_blob(const void *bphp);
+void ft_merge_blob(struct ft_cxt *cxt, void *blob);
+void *ft_find_device(struct ft_cxt *cxt, const char *srch_path);
+void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path);
+int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+		void *buf, const unsigned int buflen);
+int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+		const void *buf, const unsigned int buflen);
+
 #endif /* FLATDEVTREE_H */
diff --git a/arch/powerpc/boot/flatdevtree_env.h b/arch/powerpc/boot/flatdevtree_env.h
new file mode 100644
index 0000000..83bc1c7
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree_env.h
@@ -0,0 +1,47 @@
+/*
+ * This file adds the header file glue so that the shared files
+ * flatdevicetree.[ch] can compile and work in the powerpc bootwrapper.
+ *
+ * strncmp & strchr copied from <file:lib/strings.c>
+ * Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ * Maintained by: Mark A. Greer <mgreer@mvista.com>
+ */
+#ifndef _PPC_BOOT_FLATDEVTREE_ENV_H_
+#define _PPC_BOOT_FLATDEVTREE_ENV_H_
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "ops.h"
+
+#define be16_to_cpu(x)		(x)
+#define cpu_to_be16(x)		(x)
+#define be32_to_cpu(x)		(x)
+#define cpu_to_be32(x)		(x)
+#define be64_to_cpu(x)		(x)
+#define cpu_to_be64(x)		(x)
+
+static inline int strncmp(const char *cs, const char *ct, size_t count)
+{
+	signed char __res = 0;
+
+	while (count) {
+		if ((__res = *cs - *ct++) != 0 || !*cs++)
+			break;
+		count--;
+	}
+	return __res;
+}
+
+static inline char *strchr(const char *s, int c)
+{
+	for (; *s != (char)c; ++s)
+		if (*s == '\0')
+			return NULL;
+	return (char *)s;
+}
+
+#endif /* _PPC_BOOT_FLATDEVTREE_ENV_H_ */
diff --git a/arch/powerpc/boot/flatdevtree_misc.c b/arch/powerpc/boot/flatdevtree_misc.c
new file mode 100644
index 0000000..c7f9adb
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree_misc.c
@@ -0,0 +1,56 @@
+/*
+ * This file does the necessary interface mapping between the bootwrapper
+ * device tree operations and the interface provided by shared source
+ * files flatdevicetree.[ch].
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <stddef.h>
+#include "flatdevtree.h"
+#include "ops.h"
+
+static struct ft_cxt cxt;
+
+static void *ft_finddevice(const char *name)
+{
+	return ft_find_device(&cxt, name);
+}
+
+static int ft_getprop(const void *phandle, const char *propname, void *buf,
+		const int buflen)
+{
+	return ft_get_prop(&cxt, phandle, propname, buf, buflen);
+}
+
+static int ft_setprop(const void *phandle, const char *propname,
+		const void *buf, const int buflen)
+{
+	return ft_set_prop(&cxt, phandle, propname, buf, buflen);
+}
+
+static void ft_pack(void)
+{
+	ft_end_tree(&cxt);
+}
+
+static unsigned long ft_addr(void)
+{
+	return (unsigned long)cxt.bph;
+}
+
+int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device)
+{
+	dt_ops.finddevice = ft_finddevice;
+	dt_ops.getprop = ft_getprop;
+	dt_ops.setprop = ft_setprop;
+	dt_ops.ft_pack = ft_pack;
+	dt_ops.ft_addr = ft_addr;
+
+	return ft_open(&cxt, dt_blob, max_size, max_find_device,
+			platform_ops.realloc);
+}

^ permalink raw reply related

* [PATCH 1/4] powerpc: More bootwrapper reorg
From: Mark A. Greer @ 2006-10-12  1:33 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20061012013223.GA9143@mag.az.mvista.com>

More reorganization of the bootwrapper:
- Add dtb section to zImage
- ft_init now called by platform_init
- Pack a flat dt before calling kernel
- Remove size parameter from free
- printf only calls console_ops.write it its not NULL
- Some cleanup

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---

 main.c       |   27 ++++++---------------------
 of.c         |    8 +-------
 ops.h        |   25 ++++++++++++++-----------
 stdio.c      |    3 ++-
 wrapper      |    4 ++--
 zImage.lds.S |    5 +++++
 6 files changed, 30 insertions(+), 42 deletions(-)
---

diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index d719bb9..4184974 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -27,6 +27,8 @@ extern char _vmlinux_start[];
 extern char _vmlinux_end[];
 extern char _initrd_start[];
 extern char _initrd_end[];
+extern char _dtb_start[];
+extern char _dtb_end[];
 
 struct addr_range {
 	unsigned long addr;
@@ -250,10 +252,6 @@ #endif
 	flush_cache((void *)vmlinux.addr, vmlinux.size);
 }
 
-void __attribute__ ((weak)) ft_init(void *dt_blob)
-{
-}
-
 /* A buffer that may be edited by tools operating on a zImage binary so as to
  * edit the command line passed to vmlinux (by setting /chosen/bootargs).
  * The buffer is put in it's own section so that tools may locate it easier.
@@ -285,19 +283,12 @@ static void set_cmdline(char *buf)
 		setprop(devp, "bootargs", buf, strlen(buf) + 1);
 }
 
-/* Section where ft can be tacked on after zImage is built */
-union blobspace {
-	struct boot_param_header hdr;
-	char space[8*1024];
-} dt_blob __attribute__((__section__("__builtin_ft")));
-
 struct platform_ops platform_ops;
 struct dt_ops dt_ops;
 struct console_ops console_ops;
 
 void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
 {
-	int have_dt = 0;
 	kernel_entry_t kentry;
 	char cmdline[COMMAND_LINE_SIZE];
 
@@ -306,15 +297,7 @@ void start(unsigned long a1, unsigned lo
 	memset(&dt_ops, 0, sizeof(dt_ops));
 	memset(&console_ops, 0, sizeof(console_ops));
 
-	/* Override the dt_ops and device tree if there was an flat dev
-	 * tree attached to the zImage.
-	 */
-	if (dt_blob.hdr.magic == OF_DT_HEADER) {
-		have_dt = 1;
-		ft_init(&dt_blob);
-	}
-
-	if (platform_init(promptr))
+	if (platform_init(promptr, _dtb_start, _dtb_end))
 		exit();
 	if (console_ops.open && (console_ops.open() < 0))
 		exit();
@@ -342,8 +325,10 @@ void start(unsigned long a1, unsigned lo
 		console_ops.close();
 
 	kentry = (kernel_entry_t) vmlinux.addr;
-	if (have_dt)
+	if (_dtb_end > _dtb_start) {
+		dt_ops.ft_pack();
 		kentry(dt_ops.ft_addr(), 0, NULL);
+	}
 	else
 		/* XXX initrd addr/size should be passed in properties */
 		kentry(a1, a2, promptr);
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
index 3a71845..0182f38 100644
--- a/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -256,24 +256,18 @@ static void of_console_write(char *buf, 
 	call_prom("write", 3, 1, of_stdout_handle, buf, len);
 }
 
-int platform_init(void *promptr)
+int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end)
 {
-	platform_ops.fixups = NULL;
 	platform_ops.image_hdr = of_image_hdr;
 	platform_ops.malloc = of_try_claim;
-	platform_ops.free = NULL;
 	platform_ops.exit = of_exit;
 
 	dt_ops.finddevice = of_finddevice;
 	dt_ops.getprop = of_getprop;
 	dt_ops.setprop = of_setprop;
-	dt_ops.translate_addr = NULL;
 
 	console_ops.open = of_console_open;
 	console_ops.write = of_console_write;
-	console_ops.edit_cmdline = NULL;
-	console_ops.close = NULL;
-	console_ops.data = NULL;
 
 	prom = (int (*)(void *))promptr;
 	return 0;
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 135eb4b..59832fb 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -22,7 +22,8 @@ struct platform_ops {
 	void	(*fixups)(void);
 	void	(*image_hdr)(const void *);
 	void *	(*malloc)(u32 size);
-	void	(*free)(void *ptr, u32 size);
+	void	(*free)(void *ptr);
+	void *	(*realloc)(void *ptr, unsigned long size);
 	void	(*exit)(void);
 };
 extern struct platform_ops platform_ops;
@@ -30,12 +31,11 @@ extern struct platform_ops platform_ops;
 /* Device Tree operations */
 struct dt_ops {
 	void *	(*finddevice)(const char *name);
-	int	(*getprop)(const void *node, const char *name, void *buf,
+	int	(*getprop)(const void *phandle, const char *name, void *buf,
 			const int buflen);
-	int	(*setprop)(const void *node, const char *name,
+	int	(*setprop)(const void *phandle, const char *name,
 			const void *buf, const int buflen);
-	u64	(*translate_addr)(const char *path, const u32 *in_addr,
-			const u32 addr_len);
+	void	(*ft_pack)(void);
 	unsigned long (*ft_addr)(void);
 };
 extern struct dt_ops dt_ops;
@@ -59,10 +59,13 @@ struct serial_console_data {
 	void		(*close)(void);
 };
 
-extern int platform_init(void *promptr);
-extern void simple_alloc_init(void);
-extern void ft_init(void *dt_blob);
-extern int serial_console_init(void);
+int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end);
+int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
+int serial_console_init(void);
+int ns16550_console_init(void *devp, struct serial_console_data *scdp);
+void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
+		u32 max_allocs);
+
 
 static inline void *finddevice(const char *name)
 {
@@ -84,10 +87,10 @@ static inline void *malloc(u32 size)
 	return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
 }
 
-static inline void free(void *ptr, u32 size)
+static inline void free(void *ptr)
 {
 	if (platform_ops.free)
-		platform_ops.free(ptr, size);
+		platform_ops.free(ptr);
 }
 
 static inline void exit(void)
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index 6d5f638..0a9feeb 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -320,6 +320,7 @@ printf(const char *fmt, ...)
 	va_start(args, fmt);
 	n = vsprintf(sprint_buf, fmt, args);
 	va_end(args);
-	console_ops.write(sprint_buf, n);
+	if (console_ops.write)
+		console_ops.write(sprint_buf, n);
 	return n;
 }
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index eab7318..b5fb1fe 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -179,11 +179,11 @@ if [ -z "$cacheit" ]; then
 fi
 
 if [ -n "$initrd" ]; then
-    addsec $tmp "$initrd" initrd
+    addsec $tmp "$initrd" $isection
 fi
 
 if [ -n "$dtb" ]; then
-    addsec $tmp "$dtb" dtb
+    addsec $tmp "$dtb" .kernel:dtb
 fi
 
 if [ "$platform" != "miboot" ]; then
diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S
index 4b6bb3f..4be3c64 100644
--- a/arch/powerpc/boot/zImage.lds.S
+++ b/arch/powerpc/boot/zImage.lds.S
@@ -21,6 +21,11 @@ SECTIONS
     __got2_end = .;
   }
 
+  . = ALIGN(8);
+  _dtb_start = .;
+  .kernel:dtb : { *(.kernel:dtb) }
+  _dtb_end = .;
+
   . = ALIGN(4096);
   _vmlinux_start =  .;
   .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) }

^ permalink raw reply related

* [PATCH 0/4] powerpc: Next round of bootwrapper flat dt patches
From: Mark A. Greer @ 2006-10-12  1:32 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

I'm resumitting the entire patch series because I messed up the
threading and made some changes to simple_alloc.

Mark
---

Hi,

This patch series is a respin of--and complete replacement for--the
bootwrapper reorg patches that I sent out a while back.  I also included
the flatdevtree.c file which is the latest version that Paul sent plus
changes that I've made.

The patches apply to powerpc.git commit id:

	ba00003aa83a61b615542dd66f5af8fb4a7cee1d

Paul, it would really help the rest of us if you would apply these patches
quickly.  There are several people waiting for this work but there are so
many versions of so many patches that no one knows what to use.  Plus, it
would get more people testing/debugging the flatdevtree code.

Summary of changes:
===================

more reorg patch
----------------
- This patch includes Paul's changes to zImage.lds.S which define
  _dtb_start & _dtb_end and a related patch for the wrapper script.
- I changed main.c:start() a little so that the call to ft_init() is
  done in platform_init().  I did this because of an interface change
  to ft_init which now require some platform knowledge.
- I added a realloc() call to dt_ops so it can be passed to ft_open.

flatdevtree patch
-----------------
- I did not debug all of the flatdevtree.c code.  I only debugged
  ft_find_device, ft_get_prop, ft_set_prop and their supporting routines.
- I added a phandle table (insided the cxt) to track phandles returned by
  ft_find_device().  Now the value returned by ft_find_device() is a phandle
  which is nothing more than an index into the phandle table.  The phandle
  table contains the address of the corresponding node.  When the flat dt
  is edited/moved, the node pointers in the phandle table are updated
  accordingly so no phandles kept by the caller become stale.
- I tested shrinking, and expanding an existing property but did not test
  adding a new property.
- I'm not sure of the usefulness of the genealogy stuff but I left it there
  in case Paul has plans for it.  I did not test ft_get_parent (the only user
  of genealogy).

simple_realloc patch
--------------------
- The flatdevtree code needs a realloc now so that is implemented in here.
- As the name implies, it is a simple allocator which uses a table to track
  what's been allocated.  simple_alloc_init() let's the caller set where
  the heap is, its size, the granularity of its allocations, and how many
  entries the table has.
- Once a slot in the table is used, its base & size are set.  This allows
  the code to be much simpler.

non-OF serial console patch
---------------------------
- I decided not to look for a /cpus/<some cpu>/64-bit property and instead
  get either 1 or 2 "32-bit things" from the uart's 'virtual-reg' property.
  If there is 1, its 32-bits; if its 2, its 64-bits.

Mark

^ permalink raw reply

* Re: PPChameleonEVB Newbie question
From: Wolfgang Denk @ 2006-10-11 23:00 UTC (permalink / raw)
  To: Adrian; +Cc: linuxppc-embedded
In-Reply-To: <010001c6ed49$aa8ab390$3a0da8c0@adrianlaptop>

Dear Adrian,

in message <010001c6ed49$aa8ab390$3a0da8c0@adrianlaptop> you wrote:
> 
> I have a PPChameleonEVB board running a 405EP processor.

DAVE has a lot of pretty detailed application  notes.  Make  sure  to
read their docs.

> I have tried many things, and can now boot Linux 2.6.15 on the board using 
> an NFS share as both root fs and swap.

Swap over NFS? Grrghh... 

> When I try to compile & install the kernel modules on the board, i get an 
> message about perl and then it errors.

Why don't you just use the cross tools?

> 1) Kernel version/Linux distroof the i386 PC used for the cross-compiling.

Should not matter much.

> 2) ELDK version and if there are any patches needed.

For a 2.6 kernel tree you need ELDK 4.0.

> 2) Perl version (or how to stop the Kernel build using perl)

Use the cross tools. It's much faster anyway.


Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
He had quite a powerful intellect, but it  was  as  powerful  like  a
locomotive,  and  ran on rails and was therefore almost impossible to
steer.                          - Terry Pratchett, _Lords and Ladies_

^ permalink raw reply

* Re: [PATCH 21/21]: powerpc/cell spidernet DMA coalescing
From: Benjamin Herrenschmidt @ 2006-10-11 22:13 UTC (permalink / raw)
  To: Linas Vepstas
  Cc: akpm, jeff, Arnd Bergmann, netdev, James K Lewis, linux-kernel,
	linuxppc-dev
In-Reply-To: <20061011152016.GU4381@austin.ibm.com>


> I started writingthe patch thinking it will have some huge effect on
> performance, based on a false assumption on how i/o was done on this
> machine
> 
> *If* this were another pSeries system, then each call to 
> pci_map_single() chews up an actual hardware "translation 
> control entry" (TCE) that maps pci bus addresses into 
> system RAM addresses. These are somewhat limited resources,
> and so one shouldn't squander them.  Furthermore, I thouhght
> TCE's have TLB's associated with them (similar to how virtual
> memory page tables are backed by hardware page TLB's), of which 
> there are even less of. I was thinking that TLB thrashing would 
> have a big hit on performance. 
> 
> Turns out that there was no difference to performance at all, 
> and a quick look at "cell_map_single()" in arch/powerpc/platforms/cell
> made it clear why: there's no fancy i/o address mapping.
> 
> Thus, the patch has only mrginal benefit; I submit it only in the 
> name of "its the right thing to do anyway".

Well, there is no fancy iommu mapping ... yet.

It's been implemented and is coming after we put together some
workarounds for various other spider hardware issues that trigger when
using it (bogus prefetches and bogus pci ordering).

I think the hypervisor based platforms will be happy with that patch
too.

Ben.

^ permalink raw reply

* Re: Graphic issues (emulating VGA bios on IBM Maple)
From: Benjamin Herrenschmidt @ 2006-10-11 22:16 UTC (permalink / raw)
  To: jean-francois simon; +Cc: linuxppc-dev
In-Reply-To: <20061010203620.771.qmail@web27502.mail.ukl.yahoo.com>


> [C000000000BFFE60] [C0000000003CCC9C] .radeonfb_old_init+0x164/0x188

Try getting rid of the old radeonfb and see if that works.

Ben.

^ permalink raw reply

* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: David H. Lynch Jr. @ 2006-10-11 22:06 UTC (permalink / raw)
  To: David Bolcsfoldi; +Cc: linuxppc-embedded
In-Reply-To: <609d5c8e0610101349w64cdd4ecjc5359ad8d1f5d635@mail.gmail.com>

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


    also:

         your driver is strictly interrupt driven.
          I need polled for the Pico E12 - which my driver an early 
version was posted in January, supports.
          Somebody else needs DCR support.


David Bolcsfoldi wrote:
> Hi,
>
> here's a set of patches that adds support for Xilinx UART lite
> devices. It has been tested on an ML403-FX using xapp902
> (ml403_ppc_plb_temac) using a 2.6.18 kernel and a BusyBox userspace.
>
> This is my first patch for the Linux kernel, so please be gentle :-)
>
> David
> ------------------------------------------------------------------------
>
> diff -urN 2.6.18/arch/ppc/boot/simple/Makefile patched/arch/ppc/boot/simple/Makefile
> --- 2.6.18/arch/ppc/boot/simple/Makefile	2006-10-04 14:31:15.000000000 -0700
> +++ patched/arch/ppc/boot/simple/Makefile	2006-10-07 10:34:32.000000000 -0700
> @@ -205,6 +205,7 @@
>  endif
>  boot-$(CONFIG_SERIAL_MPC52xx_CONSOLE)	+= mpc52xx_tty.o
>  boot-$(CONFIG_SERIAL_MPSC_CONSOLE)	+= mv64x60_tty.o
> +boot-$(CONFIG_SERIAL_XUL_CONSOLE)	+= xuartlite_tty.o
>  
>  LIBS				:= $(common)/lib.a $(bootlib)/lib.a
>  ifeq ($(CONFIG_PPC_PREP),y)
> diff -urN 2.6.18/arch/ppc/boot/simple/misc.c patched/arch/ppc/boot/simple/misc.c
> --- 2.6.18/arch/ppc/boot/simple/misc.c	2006-10-04 14:31:15.000000000 -0700
> +++ patched/arch/ppc/boot/simple/misc.c	2006-10-07 10:27:34.000000000 -0700
> @@ -48,7 +48,8 @@
>  #if (defined(CONFIG_SERIAL_8250_CONSOLE) \
>  	|| defined(CONFIG_VGA_CONSOLE) \
>  	|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> -	|| defined(CONFIG_SERIAL_MPSC_CONSOLE)) \
> +	|| defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> +	|| defined(CONFIG_SERIAL_XUL_CONSOLE)) \
>  	&& !defined(CONFIG_GEMINI)
>  #define INTERACTIVE_CONSOLE	1
>  #endif
> diff -urN 2.6.18/arch/ppc/boot/simple/xuartlite_tty.c patched/arch/ppc/boot/simple/xuartlite_tty.c
> --- 2.6.18/arch/ppc/boot/simple/xuartlite_tty.c	1969-12-31 16:00:00.000000000 -0800
> +++ patched/arch/ppc/boot/simple/xuartlite_tty.c	2006-10-07 10:29:30.000000000 -0700
> @@ -0,0 +1,74 @@
> +/*
> + * Xilinx UART Lite support. 
> + * Right now it only works over UART0 and none other.
> + *
> + * Copyright (C) 2006 David Bolcsfoldi <dbolcsfoldi@gmail.com>
> + * 
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#include <asm/io.h>
> +#include <platforms/4xx/xparameters/xparameters.h>
> +
> +#define XUL_STATUS_REG_OFFSET           8   /* status register, read only */
> +#define XUL_SR_TX_FIFO_FULL             0x08    /* transmit FIFO full */
> +#define XUL_SR_RX_FIFO_VALID_DATA       0x01    /* data in receive FIFO */
> +#define XUL_RX_FIFO_OFFSET              0   /* receive FIFO, read only */
> +#define XUL_TX_FIFO_OFFSET              4   /* transmit FIFO, write only */
> +
> +static inline int is_xmit_full(unsigned int address)
> +{
> +	return ((in_be32((volatile unsigned *) (address + XUL_STATUS_REG_OFFSET)) & XUL_SR_TX_FIFO_FULL) == XUL_SR_TX_FIFO_FULL);
> +}
> +
> +static inline int is_recv_empty(unsigned int address)
> +{
> +	return ((in_be32((volatile unsigned *) (address + XUL_STATUS_REG_OFFSET)) & XUL_SR_RX_FIFO_VALID_DATA) != XUL_SR_RX_FIFO_VALID_DATA);
> +}
> +
> +unsigned long serial_init(int chan, void *ignored)
> +{
> +	switch (chan)  {
> +	#ifdef XPAR_XUL_UART_0_BASEADDR
> +		case 0:
> +			return XPAR_XUL_UART_0_BASEADDR;
> +	#endif
> +	#ifdef XPAR_XUL_UART_1_BASEADDR
> +		case 1:		
> +			return XPAR_XUL_UART_1_BASEADDR;
> +	#endif
> +	#ifdef XPAR_XUL_UART_2_BASEADDR
> +		case 2:
> +			return XPAR_XUL_UART_2_BASEADDR;
> +	#endif
> +	#ifdef XPAR_XUL_UART_3_BASEADDR
> +		case 3:
> +			return XPAR_XUL_UART_3_BASEADDR;
> +	#endif
> +		default:
> +			goto out;
> +	}
> +	
> +out:
> +	return -1;
> +}
> +
> +void serial_putc(unsigned long com_port, unsigned char c)
> +{
> +	while(is_xmit_full(XPAR_XUL_UART_0_BASEADDR));
> +	out_be32((volatile unsigned *) (XPAR_XUL_UART_0_BASEADDR + XUL_TX_FIFO_OFFSET), c);
> +}
> +
> +unsigned char serial_getc(unsigned long com_port)
> +{
> +	while(is_recv_empty(XPAR_XUL_UART_0_BASEADDR));
> +	return in_be32((volatile unsigned *) (XPAR_XUL_UART_0_BASEADDR + XUL_RX_FIFO_OFFSET));
> +}
> +
> +int serial_tstc(unsigned long com_port)
> +{
> +	return !(is_recv_empty(XPAR_XUL_UART_0_BASEADDR));
> +}
> +
>   
> ------------------------------------------------------------------------
>
> diff -urN 2.6.18/arch/ppc/boot/common/misc-common.c patched/arch/ppc/boot/common/misc-common.c
> --- 2.6.18/arch/ppc/boot/common/misc-common.c	2006-10-04 14:31:15.000000000 -0700
> +++ patched/arch/ppc/boot/common/misc-common.c	2006-10-07 10:33:28.000000000 -0700
> @@ -57,7 +57,8 @@
>  
>  #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
>  	|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> -	|| defined(CONFIG_SERIAL_MPSC_CONSOLE)
> +	|| defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> +	|| defined(CONFIG_SERIAL_XUL_CONSOLE)
>  extern unsigned long com_port;
>  
>  extern int serial_tstc(unsigned long com_port);
> @@ -80,7 +81,8 @@
>  {
>  #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
>  	|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> -	|| defined(CONFIG_SERIAL_MPSC_CONSOLE)
> +	|| defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> +	|| defined(CONFIG_SERIAL_XUL_CONSOLE)
>  	if(keyb_present)
>  		return (CRT_tstc() || serial_tstc(com_port));
>  	else
> @@ -95,7 +97,8 @@
>  	while (1) {
>  #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
>  	|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> -	|| defined(CONFIG_SERIAL_MPSC_CONSOLE)
> +	|| defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> +	|| defined(CONFIG_SERIAL_XUL_CONSOLE)
>  		if (serial_tstc(com_port))
>  			return (serial_getc(com_port));
>  #endif /* serial console */
> @@ -112,7 +115,8 @@
>  
>  #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
>  	|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> -	|| defined(CONFIG_SERIAL_MPSC_CONSOLE)
> +	|| defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> +	|| defined(CONFIG_SERIAL_XUL_CONSOLE)
>  	serial_putc(com_port, c);
>  	if ( c == '\n' )
>  		serial_putc(com_port, '\r');
> @@ -161,7 +165,8 @@
>  	while ( ( c = *s++ ) != '\0' ) {
>  #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
>  	|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> -	|| defined(CONFIG_SERIAL_MPSC_CONSOLE)
> +	|| defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> +	|| defined(CONFIG_SERIAL_XUL_CONSOLE)
>  	        serial_putc(com_port, c);
>  	        if ( c == '\n' ) serial_putc(com_port, '\r');
>  #endif /* serial console */
>   
> ------------------------------------------------------------------------
>
> --- 2.6.18/arch/ppc/platforms/4xx/virtex.c	2006-10-04 14:31:15.000000000 -0700
> +++ patched/arch/ppc/platforms/4xx/virtex.c	2006-10-07 11:21:18.000000000 -0700
> @@ -52,5 +52,10 @@
>  		.id		= 0,
>  		.dev.platform_data = serial_platform_data,
>  	},
> +
> +	[VIRTEX_XUL_UART] = {
> +		.name = "xul_uart",
> +		.id	  = 0,
> +	},
>  };
>  
>   
> ------------------------------------------------------------------------
>
> --- 2.6.18/arch/ppc/platforms/4xx/virtex.h	2006-10-04 14:31:15.000000000 -0700
> +++ patched/arch/ppc/platforms/4xx/virtex.h	2006-10-07 10:35:31.000000000 -0700
> @@ -27,7 +27,9 @@
>  /* Device type enumeration for platform bus definitions */
>  #ifndef __ASSEMBLY__
>  enum ppc_sys_devices {
> -	VIRTEX_UART, NUM_PPC_SYS_DEVS,
> +	VIRTEX_UART,
> +	VIRTEX_XUL_UART,
> +	NUM_PPC_SYS_DEVS,
>  };
>  #endif
>    
>   
> ------------------------------------------------------------------------
>
> diff -urN 2.6.18/drivers/serial/Kconfig patched/drivers/serial/Kconfig
> --- 2.6.18/drivers/serial/Kconfig	2006-10-04 14:31:18.000000000 -0700
> +++ patched/drivers/serial/Kconfig	2006-10-07 10:50:20.000000000 -0700
> @@ -959,4 +959,22 @@
>  	  If you have enabled the serial port on the Motorola IMX
>  	  CPU you can make it the console by answering Y to this option.
>  
> +config SERIAL_XUL
> +	tristate "Xilinx UART Lite serial support"
> +	depends on XILINX_ML403
> +	select SERIAL_CORE
> +	help
> +	  This driver supports the Xilinx UART Lite serial ports. If you would
> +	  like to use them, you must answer Y or M to this option. Note that
> +	  for use as console, it must be included in the kernel and not as a 
> +	  module.
> +
> +config SERIAL_XUL_CONSOLE
> +	bool "Console on a Xilinx UART Lite serial port"
> +	depends on SERIAL_XUL
> +	select SERIAL_CORE_CONSOLE
> +	help
> +	  Select this option if you'd like to use the UART Lite serial port
> +	  of the Xilinx ML403 board as a console.
> +
>  endmenu
> diff -urN 2.6.18/drivers/serial/Makefile patched/drivers/serial/Makefile
> --- 2.6.18/drivers/serial/Makefile	2006-10-04 14:31:18.000000000 -0700
> +++ patched/drivers/serial/Makefile	2006-10-07 10:51:02.000000000 -0700
> @@ -56,3 +56,4 @@
>  obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
>  obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
>  obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
> +obj-$(CONFIG_SERIAL_XUL) += xuartlite.o
> diff -urN 2.6.18/drivers/serial/xuartlite.c patched/drivers/serial/xuartlite.c
> --- 2.6.18/drivers/serial/xuartlite.c	1969-12-31 16:00:00.000000000 -0800
> +++ patched/drivers/serial/xuartlite.c	2006-10-10 11:08:08.000000000 -0700
> @@ -0,0 +1,723 @@
> +/*
> + * drivers/serial/xuartlite.c
> + *
> + * Driver for Xilinx UART Lite device.
> + *
> + * This driver has only been tested with the Xilinx ML403-FX board using the plb_temac
> + * reference design with on UART port.
> + * 
> + * This driver is loosely based off the mpc52xx_uart driver.
> + * 
> + * Copyright (C) 2006 David Bolcsfoldi <dbolcsfoldi@gmail.com>
> + * 
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#include <linux/config.h>
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/tty.h>
> +#include <linux/serial.h>
> +#include <linux/sysrq.h>
> +#include <linux/console.h>
> +
> +#include <asm/delay.h>
> +#include <asm/io.h>
> +#include <platforms/4xx/xparameters/xparameters.h>
> +
> +#if defined(CONFIG_SERIAL_XUL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
> +#define SUPPORT_SYSRQ
> +#endif
> +
> +#include <linux/serial_core.h>
> +
> +#define SERIAL_XUL_MAJOR	204
> +#define SERIAL_XUL_MINOR	187
> +
> +/*
> + * Keeps various tidbits about the serial port taken
> + * from xparameters.h
> + * */
> +
> +struct xul_uart_data {
> +	int baud;
> +	int parity;
> +	int bits;
> +	int flow;
> +	int uartclk;
> +	int irq;
> +	int mapbase;
> +	int size;
> +};
> +
> +static struct xul_uart_data xul_data[XPAR_XUARTLITE_NUM_INSTANCES] = {
> +	{ 
> +		.baud = XPAR_XUL_UART_0_BAUDRATE,
> +#if (XPAR_XUL_UART_0_USE_PARITY != 0)
> +		.parity = 'y',
> +#else
> +		.parity = 'n',
> +#endif /* XPAR_XUL_UART_0_USE_PARITY */
> +		.bits = XPAR_XUL_UART_0_DATA_BITS,		
> +		.flow = 'n',
> +		.uartclk = 100000000 / 16, /* PLB speed / 16 */
> +		.irq = XPAR_INTC_0_XUL_UART_0_VEC_ID,
> +		.mapbase = XPAR_XUL_UART_0_BASEADDR,
> +		.size = (XPAR_XUL_UART_0_HIGHADDR - XPAR_XUL_UART_0_BASEADDR) + 1
> +	}
> +
> +	/* Add next uart here */
> +};
> +
> +static const long ISR_PASS_LIMIT = 255;
> +static struct uart_port xul_uart_ports[XPAR_XUARTLITE_NUM_INSTANCES];
> +
> +#define XUL(port) ((unsigned int)((port)->membase))
> +
> +#define XUL_RX_FIFO_OFFSET              0   /* receive FIFO, read only */
> +#define XUL_TX_FIFO_OFFSET              4   /* transmit FIFO, write only */
> +#define XUL_STATUS_REG_OFFSET           8   /* status register, read only */
> +#define XUL_CONTROL_REG_OFFSET          12  /* control register, write only */
> +
> +#define XUL_CR_ENABLE_INTR              0x10    /* enable interrupt */
> +#define XUL_CR_FIFO_RX_RESET            0x02    /* reset receive FIFO */
> +#define XUL_CR_FIFO_TX_RESET            0x01    /* reset transmit FIFO */
> +
> +#define XUL_SR_PARITY_ERROR             0x80
> +#define XUL_SR_FRAMING_ERROR            0x40
> +#define XUL_SR_OVERRUN_ERROR            0x20
> +#define XUL_SR_TX_FIFO_FULL             0x08    /* transmit FIFO full */
> +#define XUL_SR_TX_FIFO_EMPTY            0x04    /* transmit FIFO empty */
> +#define XUL_SR_RX_FIFO_VALID_DATA       0x01    /* data in receive FIFO */
> +
> +/* Forward declaration of the interruption handling routine */
> +static irqreturn_t xul_uart_int(int irq,void *dev_id,struct pt_regs *regs);
> +
> +/* Simple macro to test if a port is console or not. This one is taken
> + * for serial_core.c and maybe should be moved to serial_core.h ? */
> +#ifdef CONFIG_SERIAL_CORE_CONSOLE
> +#define uart_console(port)	((port)->cons && (port)->cons->index == (port)->line)
> +#else
> +#define uart_console(port)	(0)
> +#endif
> +
> +/* ======================================================================== */
> +/* UART operations                                                          */
> +/* ======================================================================== */
> +
> +static int
> +xul_uart_int_tx_chars(struct uart_port *port);
> +
> +static inline int is_xmit_empty(struct uart_port *port)
> +{
> +	return ((in_be32((volatile unsigned *) (XUL(port) + XUL_STATUS_REG_OFFSET)) & XUL_SR_TX_FIFO_EMPTY) == XUL_SR_TX_FIFO_EMPTY);
> +}
> +
> +static inline int is_recv_empty(struct uart_port *port)
> +{
> +	return ((in_be32((volatile unsigned *) (XUL(port) + XUL_STATUS_REG_OFFSET)) & XUL_SR_RX_FIFO_VALID_DATA) != XUL_SR_RX_FIFO_VALID_DATA);
> +}
> +
> +static inline int is_xmit_full(struct uart_port *port)
> +{
> +	return ((in_be32((volatile unsigned *) (XUL(port) + XUL_STATUS_REG_OFFSET)) & XUL_SR_TX_FIFO_FULL) == XUL_SR_TX_FIFO_FULL);
> +}
> +
> +static inline void xmit_char(struct uart_port *port, char c)
> +{
> +	while(is_xmit_full(port));
> +	out_be32((volatile unsigned *) (XUL(port) + XUL_TX_FIFO_OFFSET), c); 
> +}
> +
> +static inline char recv_char(struct uart_port *port)
> +{
> +	while(is_recv_empty(port));
> +	return in_be32((volatile unsigned *) (XUL(port) + XUL_RX_FIFO_OFFSET));
> +}
> +
> +static unsigned int 
> +xul_uart_tx_empty(struct uart_port *port)
> +{
> +	return ((is_xmit_empty(port)) ? TIOCSER_TEMT : 0);
> +}
> +
> +static void 
> +xul_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
> +{
> +	/* Not implemented */
> +}
> +
> +static unsigned int 
> +xul_uart_get_mctrl(struct uart_port *port)
> +{
> +	return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
> +}
> +
> +static void 
> +xul_uart_stop_tx(struct uart_port *port)
> +{
> +	/* port->lock taken by caller */
> +}
> +
> +static void 
> +xul_uart_start_tx(struct uart_port *port)
> +{
> +	/* port->lock taken by caller */
> +	xul_uart_int_tx_chars(port);
> +}
> +
> +static void 
> +xul_uart_send_xchar(struct uart_port *port, char ch)
> +{
> +	unsigned long flags;
> +	
> +	spin_lock_irqsave(&port->lock, flags);
> +	
> +	port->x_char = ch;
> +	
> +	if (ch) {
> +		xmit_char(port, ch);
> +	}
> +	
> +	spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static void
> +xul_uart_stop_rx(struct uart_port *port)
> +{
> +	/* port->lock taken by caller */
> +}
> +
> +static void
> +xul_uart_enable_ms(struct uart_port *port)
> +{
> +	/* Not implemented */
> +}
> +
> +static void
> +xul_uart_break_ctl(struct uart_port *port, int ctl)
> +{
> +	/* Not implemented */
> +}
> +
> +static int
> +xul_uart_startup(struct uart_port *port)
> +{
> +	int ret;
> +	
> +	/* Request IRQ */
> +	ret = request_irq(port->irq, xul_uart_int,
> +		SA_INTERRUPT | SA_SAMPLE_RANDOM, "xul_uart", port);
> +	if (ret)
> +		return ret;
> +
> +	/* Reset/activate the port, clear and enable interrupts */
> +	out_be32((volatile unsigned *) (XUL(port) + XUL_CONTROL_REG_OFFSET), XUL_CR_FIFO_TX_RESET); /* Reset TX */
> +	out_be32((volatile unsigned *) (XUL(port) + XUL_CONTROL_REG_OFFSET), XUL_CR_FIFO_RX_RESET); /* Reset RX */
> +	out_be32((volatile unsigned *) (XUL(port) + XUL_CONTROL_REG_OFFSET), XUL_CR_ENABLE_INTR); /* Enable interrupt */
> +		
> +	return 0;
> +}
> +
> +static void
> +xul_uart_shutdown(struct uart_port *port)
> +{
> +	/* Shut down the port, interrupt and all */
> +
> +	/* Disable interrupt bu clearing control register */
> +	out_be32((volatile unsigned *) (XUL(port) + XUL_CONTROL_REG_OFFSET), 0);
> +
> +	out_be32((volatile unsigned *) (XUL(port) + XUL_CONTROL_REG_OFFSET), XUL_CR_FIFO_TX_RESET); /* Reset TX */
> +	out_be32((volatile unsigned *) (XUL(port) + XUL_CONTROL_REG_OFFSET), XUL_CR_FIFO_RX_RESET); /* Reset RX */
> +
> +	/* Release interrupt */
> +	free_irq(port->irq, port);
> +}
> +
> +static void 
> +xul_uart_set_termios(struct uart_port *port, struct termios *new,
> +                         struct termios *old)
> +{
> +	/* Nothing can be set, fixed at IP block generation */
> +}
> +
> +static const char *
> +xul_uart_type(struct uart_port *port)
> +{
> +	return port->type == PORT_XUL ? "ttyXUL" : NULL;
> +}
> +
> +static void
> +xul_uart_release_port(struct uart_port *port)
> +{
> +	if (port->flags & UPF_IOREMAP) {
> +		iounmap(port->membase);
> +		port->membase = NULL;
> +	}
> +	
> +	release_mem_region(port->mapbase, xul_data[port->line].size);
> +}
> +
> +static int
> +xul_uart_request_port(struct uart_port *port)
> +{
> +	int mem_region;
> +	
> +	if (port->flags & UPF_IOREMAP) {
> +		port->membase = ioremap(port->mapbase, xul_data[port->line].size);
> +	}
> +
> +	if (!port->membase) {
> +		return -EINVAL;
> +	}
> +	
> +	mem_region = request_mem_region(port->mapbase, xul_data[port->line].size, "xul_uart") != NULL ? 0 : -EBUSY;
> +	return 0;
> +}
> +
> +static void
> +xul_uart_config_port(struct uart_port *port, int flags)
> +{
> +	if ( (flags & UART_CONFIG_TYPE) &&
> +	     (xul_uart_request_port(port) == 0) )
> +	     	port->type = PORT_XUL;
> +}
> +
> +static int
> +xul_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
> +{
> +	if ( ser->type != PORT_UNKNOWN && ser->type != PORT_XUL ) {
> +		printk(KERN_WARNING "xul_uart_verify_port(1)\n");
> +		return -EINVAL;
> +	}
> +
> +	if ( (ser->irq != port->irq) ||
> +	     (ser->io_type != SERIAL_IO_MEM) ||
> +	     (ser->baud_base != port->uartclk)  || 
> +	     (ser->iomem_base != (void*)port->mapbase) ||
> +	     (ser->hub6 != 0 ) ) {
> +		printk(KERN_WARNING "xul_uart_verify_port(1)\n");
> +	}
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +
> +static struct uart_ops xul_uart_ops = {
> +	.tx_empty	= xul_uart_tx_empty,
> +	.set_mctrl	= xul_uart_set_mctrl,
> +	.get_mctrl	= xul_uart_get_mctrl,
> +	.stop_tx	= xul_uart_stop_tx,
> +	.start_tx	= xul_uart_start_tx,
> +	.send_xchar	= xul_uart_send_xchar,
> +	.stop_rx	= xul_uart_stop_rx,
> +	.enable_ms	= xul_uart_enable_ms,
> +	.break_ctl	= xul_uart_break_ctl,
> +	.startup	= xul_uart_startup,
> +	.shutdown	= xul_uart_shutdown,
> +	.set_termios	= xul_uart_set_termios,
> +/*	.pm		= xul_uart_pm,		Not supported yet */
> +/*	.set_wake	= xul_uart_set_wake,	Not supported yet */
> +	.type		= xul_uart_type,
> +	.release_port	= xul_uart_release_port,
> +	.request_port	= xul_uart_request_port,
> +	.config_port	= xul_uart_config_port,
> +	.verify_port	= xul_uart_verify_port
> +};
> +
> +	
> +/* ======================================================================== */
> +/* Interrupt handling                                                       */
> +/* ======================================================================== */
> +	
> +static int
> +xul_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs)
> +{
> +	struct tty_struct *tty = port->info->tty;
> +	unsigned char ch, flag;
> +	unsigned long status;
> +	
> +	status = in_be32((volatile unsigned *) (XUL(port) + XUL_STATUS_REG_OFFSET));
> +	
> +	/* While we can read, do so ! */
> +	if ((status & XUL_SR_RX_FIFO_VALID_DATA) == XUL_SR_RX_FIFO_VALID_DATA) {
> +
> +		/* Get the char */
> +		ch = recv_char(port);
> +		
> +		/* Handle sysreq char */
> +#ifdef SUPPORT_SYSRQ
> +		if (uart_handle_sysrq_char(port, ch, regs)) {
> +			port->sysrq = 0;
> +			continue;
> +		}
> +#endif
> +		/* Store it */
> +
> +		flag = TTY_NORMAL;
> +		port->icount.rx++;
> +	
> +		if (status & XUL_SR_PARITY_ERROR)
> +			flag = TTY_PARITY;
> +		else if (status & XUL_SR_FRAMING_ERROR)
> +			flag = TTY_FRAME;
> +	
> +		tty_insert_flip_char(tty, ch, flag);
> +
> +		if (status & XUL_SR_OVERRUN_ERROR) {
> +			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
> +		}
> +	}
> +
> +	spin_unlock(&port->lock);
> +	tty_flip_buffer_push(tty);
> +	spin_lock(&port->lock);
> +		
> +	return 0;
> +}
> +
> +static int
> +xul_uart_int_tx_chars(struct uart_port *port)
> +{
> +	struct circ_buf *xmit = &port->info->xmit;
> +	
> +	/* Process out of band chars */
> +	if (port->x_char) {
> +		xmit_char(port, port->x_char);
> +		port->icount.tx++;
> +		port->x_char = 0;
> +		return 1;
> +	}
> +
> +	/* Nothing to do ? */
> +	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
> +		xul_uart_stop_tx(port);
> +		return 0;
> +	}
> +
> +	/* Send chars */
> +	while (is_xmit_full(port) == 0)  {
> +		xmit_char(port, xmit->buf[xmit->tail]);
> +		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
> +		port->icount.tx++;
> +
> +		if (uart_circ_empty(xmit))
> +			break;
> +	}
> +
> +	/* Wake up */
> +	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
> +		uart_write_wakeup(port);
> +	}
> +
> +	/* Maybe we're done after all */
> +	if (uart_circ_empty(xmit)) {
> +		xul_uart_stop_tx(port);
> +		return 0;
> +	}
> +
> +	return 1;
> +}
> +
> +static irqreturn_t 
> +xul_uart_int(int irq, void *dev_id, struct pt_regs *regs)
> +{
> +	struct uart_port *port = (struct uart_port *) dev_id;
> +	unsigned long pass = ISR_PASS_LIMIT;
> +	unsigned int keepgoing;
> +
> +	if ( irq != port->irq ) {
> +		printk( KERN_WARNING
> +		        "xul_uart_int : " \
> +		        "Received wrong int %d. Waiting for %d\n",
> +		       irq, port->irq);
> +		return IRQ_NONE;
> +	}
> +	
> +	spin_lock(&port->lock);
> +	
> +	/* While we have stuff to do, we continue */
> +	do {
> +		/* If we don't find anything to do, we stop */
> +		keepgoing = 0; 
> +		
> +		/* Do we need to receive chars ? */
> +		if (is_recv_empty(port) == 0) {
> +			keepgoing |= xul_uart_int_rx_chars(port, regs);
> +		}
> +
> +		/* Do we need to send chars ? */
> +		if (is_xmit_empty(port)) {
> +			keepgoing |= xul_uart_int_tx_chars(port);
> +		}
> +		
> +		/* Limit number of iteration */
> +		if ( !(--pass) )
> +			keepgoing = 0;
> +
> +	} while (keepgoing);
> +	
> +	spin_unlock(&port->lock);
> +	
> +	return IRQ_HANDLED;
> +}
> +
> +
> +/*
> + * Utility routines
> + */
> +
> +static void __init xul_uart_init_ports(void)
> +{
> +	int i;
> +	static int once = 1;
> +
> +	/* Initialize ports only once */
> +	if (!once)
> +		return;
> +	once = 0;
> +	
> +	for (i = 0; i < XPAR_XUARTLITE_NUM_INSTANCES; ++i) {
> +		struct uart_port *xup = &xul_uart_ports[i];
> +		
> +		xup->line = i;
> +		spin_lock_init(&xup->lock);
> +		xup->uartclk	= xul_data[i].uartclk / 16;
> +		xup->fifosize	= 16;
> +		xup->iotype	= UPIO_MEM;
> +		xup->flags	= UPF_BOOT_AUTOCONF | UPF_IOREMAP;
> +		xup->ops	= &xul_uart_ops;
> +		xup->irq	= xul_data[i].irq;
> +		xup->mapbase = xul_data[i].mapbase;
> +	}
> +}
> +
> +static void __init xul_uart_register_ports(struct uart_driver *driver)
> +{
> +	int i, ret;
> +	
> +	for(i = 0; i < XPAR_XUARTLITE_NUM_INSTANCES; ++i) {
> +		struct uart_port *port = &xul_uart_ports[i];
> +		/* Add the port to the uart sub-system */
> +		ret = uart_add_one_port(driver, port);
> +	}
> +}
> +
> +/* ======================================================================== */
> +/* Console ( if applicable )                                                */
> +/* ======================================================================== */
> +
> +#ifdef CONFIG_SERIAL_XUL_CONSOLE
> +
> +static void  
> +xul_console_write(struct console *co, const char *s, unsigned int count)
> +{
> +	struct uart_port *port = &xul_uart_ports[co->index];
> +	unsigned int i, j;
> +
> +	/* Disable interrupts */
> +	
> +	spin_lock(&port->lock);
> +	out_be32((volatile unsigned *) (XUL(port) + XUL_CONTROL_REG_OFFSET), 0);
> +	spin_unlock(&port->lock);
> +	
> +	/* Wait the TX buffer to be empty */
> +	j = 5000000;	/* Maximum wait */	
> +	while (!(is_xmit_empty(port)) &&
> +	       --j)
> +		udelay(1);
> +
> +	for (i = 0; i < count; i++, s++) {
> +		if (*s == '\n')
> +			xmit_char(port, '\r');
> +
> +		xmit_char(port, *s);
> +	}
> +
> +	/* Restore interrupt state */
> +	out_be32((volatile unsigned *) (XUL(port) + XUL_CONTROL_REG_OFFSET), 0); 
> +}
> +
> +static int __init
> +xul_console_setup(struct console *co, char *options)
> +{
> +	struct uart_port *port;
> +	int baud;
> +	int bits;
> +	int parity;
> +	int flow;
> +
> +	if (co->index < 0 || co->index >= XPAR_XUARTLITE_NUM_INSTANCES)
> +		return -EINVAL;
> +
> +	port = &xul_uart_ports[co->index];
> +
> +	/* We ioremap ourself */
> +	port->membase = ioremap(port->mapbase, xul_data[co->index].size);
> +
> +	if (port->membase == NULL) {	
> +		return -EINVAL;
> +	}
> +
> +	port->flags &= ~UPF_IOREMAP;
> +
> +	baud = xul_data[co->index].baud;
> +	parity = xul_data[co->index].parity;
> +	bits = xul_data[co->index].bits;
> +	flow = xul_data[co->index].flow;
> +
> +	return uart_set_options(port, co, baud, parity, bits, flow);
> +}
> +
> +static struct uart_driver xul_uart_driver;
> +
> +static struct console xul_console = {
> +	.name	= "ttyXUL",
> +	.write	= xul_console_write,
> +	.device	= uart_console_device,
> +	.setup	= xul_console_setup,
> +	.flags	= CON_PRINTBUFFER,
> +	.index	= -1,	/* Specified on the cmdline (e.g. console=ttyXUL0 ) */
> +	.data	= &xul_uart_driver,
> +};
> +
> +	
> +static int __init 
> +xul_console_init(void)
> +{
> +	xul_uart_init_ports();
> +	register_console(&xul_console);
> +	return 0;
> +}
> +
> +console_initcall(xul_console_init);
> +
> +#define XUL_CONSOLE &xul_console
> +#else
> +#define XUL_CONSOLE NULL
> +#endif
> +
> +
> +/* ======================================================================== */
> +/* UART Driver                                                              */
> +/* ======================================================================== */
> +
> +static struct uart_driver xul_uart_driver = {
> +	.owner			= THIS_MODULE,
> +	.driver_name	= "xul_uart",
> +	.dev_name		= "ttyXUL",
> +	.major			= SERIAL_XUL_MAJOR,
> +	.minor			= SERIAL_XUL_MINOR,
> +	.nr				= XPAR_XUARTLITE_NUM_INSTANCES,
> +	.cons			= XUL_CONSOLE,
> +};
> +
> +
> +/* ======================================================================== */
> +/* Platform Driver                                                          */
> +/* ======================================================================== */
> +
> +static int __devinit
> +xul_uart_probe(struct platform_device *dev)
> +{
> +	/* Probe does nothing */
> +	return 0;
> +}
> +
> +static int
> +xul_uart_remove(struct platform_device *dev)
> +{
> +	struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
> +
> +	platform_set_drvdata(dev, NULL);
> +
> +	if (port)
> +		uart_remove_one_port(&xul_uart_driver, port);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int
> +xul_uart_suspend(struct platform_device *dev, pm_message_t state)
> +{
> +	struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
> +
> +	if (port)
> +		uart_suspend_port(&xul_uart_driver, port);
> +
> +	return 0;
> +}
> +
> +static int
> +xul_uart_resume(struct platform_device *dev)
> +{
> +	struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
> +
> +	if (port)
> +		uart_resume_port(&xul_uart_driver, port);
> +
> +	return 0;
> +}
> +#endif
> +
> +static struct platform_driver xul_uart_platform_driver = {
> +	.probe		= xul_uart_probe,
> +	.remove		= xul_uart_remove,
> +#ifdef CONFIG_PM
> +	.suspend	= xul_uart_suspend,
> +	.resume		= xul_uart_resume,
> +#endif
> +	.driver		= {
> +		.name	= "xul_uart"
> +	},
> +};
> +
> +
> +/* ======================================================================== */
> +/* Module                                                                   */
> +/* ======================================================================== */
> +
> +static int __init
> +xul_uart_init(void)
> +{
> +	int ret;
> +
> +	printk(KERN_INFO "Serial: Xilinx UART Lite driver\n");	
> +	
> +	xul_uart_init_ports();
> +
> +	ret = uart_register_driver(&xul_uart_driver);
> +
> +	if (ret == 0) {
> +		xul_uart_register_ports(&xul_uart_driver);
> +		
> +		ret = platform_driver_register(&xul_uart_platform_driver);
> +
> +		if (ret) {
> +			printk(KERN_WARNING "platform_driver_register failed! :%i\n", ret);
> +			uart_unregister_driver(&xul_uart_driver);
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +static void __exit
> +xul_uart_exit(void)
> +{
> +	platform_driver_unregister(&xul_uart_platform_driver);
> +	uart_unregister_driver(&xul_uart_driver);
> +}
> +
> +
> +module_init(xul_uart_init);
> +module_exit(xul_uart_exit);
> +
> +MODULE_AUTHOR("David Bolcsfoldi <dbolcsfoldi@gmail.com>");
> +MODULE_DESCRIPTION("Xilinx UART Lite");
> +MODULE_LICENSE("GPL");
> +
>   
> ------------------------------------------------------------------------
>
> --- 2.6.18/arch/ppc/platforms/4xx/xilinx_ml403.c	2006-10-04 14:31:15.000000000 -0700
> +++ patched/arch/ppc/platforms/4xx/xilinx_ml403.c	2006-10-07 10:41:50.000000000 -0700
> @@ -69,6 +69,7 @@
>  		.device_list	= (enum ppc_sys_devices[])
>  		{
>  			VIRTEX_UART,
> +			VIRTEX_XUL_UART,
>  		},
>  	},
>  };
>   
> ------------------------------------------------------------------------
>
> --- 2.6.18/include/linux/serial_core.h	2006-10-04 14:31:19.000000000 -0700
> +++ patched/include/linux/serial_core.h	2006-10-07 10:52:24.000000000 -0700
> @@ -132,6 +132,8 @@
>  
>  #define PORT_S3C2412	73
>  
> +/* Xilinx UART Lite */
> +#define PORT_XUL 74
>  
>  #ifdef __KERNEL__
>  
>   
> ------------------------------------------------------------------------
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded


-- 
Dave Lynch 					  	    DLA Systems
Software Development:  				         Embedded Linux
717.627.3770 	       dhlii@dlasys.net 	  http://www.dlasys.net
fax: 1.253.369.9244 			           Cell: 1.717.587.7774
Over 25 years' experience in platforms, languages, and technologies too numerous to list.

"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein


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

^ permalink raw reply

* Re: [PATCH 0/21]: powerpc/cell spidernet bugfixes, etc.
From: James K Lewis @ 2006-10-11 21:06 UTC (permalink / raw)
  To: Arnd Bergmann, jim; +Cc: akpm, jeff, netdev, linux-kernel, linuxppc-dev
In-Reply-To: <200610111802.43996.arnd@arndb.de>

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

Jeff,

  Please apply and forward these Spidernet patches. Thanks!

Jim Lewis
Advisory Software Engineer
IBM Linux Technology Center
512-838-7754






Arnd Bergmann <arnd@arndb.de> 
10/11/2006 11:02 AM

To
Linas Vepstas <linas@austin.ibm.com>
cc
akpm@osdl.org, jeff@garzik.org, James K Lewis/Austin/IBM@ibmus, 
netdev@vger.kernel.org, linux-kernel@vger.kernel.org, 
linuxppc-dev@ozlabs.org
Subject
Re: [PATCH 0/21]: powerpc/cell spidernet bugfixes, etc.






On Tuesday 10 October 2006 22:49, Linas Vepstas wrote:
> Andrew, please apply/forward upstream.
> 
> The following set of 21 patches (!) are all aimed at the the 
> spidernet ethernet device driver. The spidernet is an etherenet
> controller built into the Toshiba southbridge for the PowerPC Cell
> processor. (This is the only device in existance that with this
> ethernet hardware in it).
> 
> These patches re-package/re-order/re-cleanup a previous
> set of patches I've previously mailed. Thus, some have
> been previously Acked-by lines, most do not. Most of
> these patches are tiny, and handle problems that cropped
> up during testing. Sorry about there being so many of them.
> 
> The first set of 12 patches fix a large variety of mostly 
> minor bugs. 
> 
> The important patches are 13 through 17: these overcome a 
> debilitating performance problem on transmit (6 megabits
> per second !!) on transmit of patches 500 bytes or larger.
> After applying these, I am able to get the following:
> 
> pkt sz   speed (100K buffs)       speed (4M buffs)
> ------   -----------------        ----------------
> 1500     700 Mbits/sec            951 Mbits/sec
> 1000     658 Mbits/sec            770
> 800      600                      648
> 500      500                      500
> 300      372                      372
> 60        70                       70
> 
> Above buf size refers to /proc/sys/net/core/wmem_default

Excellent work! I guess this the best tx performance we've
seen so far on this hardware.

Consider this as an Acked-by: for all the patches, I'll save
the effort of replying to each one of them separately.

Jeff, do you plan on merging these fixes for 2.6.19?

                 Arnd <><


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

^ permalink raw reply

* RE: plb_temac, ML403, linux 2.4.26, EDK 7.1
From: robert corley @ 2006-10-11 20:46 UTC (permalink / raw)
  To: linuxppc-embedded

Ming;=0A=0AHere is what the EDK generates in this file:=0A=0AC:\EDK\project=
s\startup_network\ppc405_0\libsrc\linux_mvl31_v1_01_a\linux\arch\ppc\platfo=
rms\xilinx_ocp\xparameters_ml300.h=0A=0A<snip>=0A#define XPAR_XTEMAC_NUM_IN=
STANCES 1=0A#define XPAR_PLB_TEMAC_0_BASEADDR 0x60000000=0A#define XPAR_PLB=
_TEMAC_0_HIGHADDR 0x60003FFF=0A#define XPAR_PLB_TEMAC_0_DEVICE_ID 0=0A#defi=
ne XPAR_PLB_TEMAC_0_IPIF_RDFIFO_DEPTH 131072=0A#define XPAR_PLB_TEMAC_0_IPI=
F_WRFIFO_DEPTH 131072=0A#define XPAR_PLB_TEMAC_0_MAC_FIFO_DEPTH 64=0A#defin=
e XPAR_PLB_TEMAC_0_DMA_TYPE 3=0A#define XPAR_PLB_TEMAC_0_TEMAC_DCR_HOST 0=
=0A#define XPAR_PLB_TEMAC_0_INCLUDE_DRE 1=0A<snip>=0A=0A=0AWhich is fine.  =
However, the file in the linux distribution: linux_2_4_devel/drivers/net/xi=
linx_enet/adapter.c is looking for "XEMAC" instead of "XTEMAC" as above.=0A=
=0AAlso, when I look at the EDK project directory =0A=0A"C:\EDK\projects\st=
artup_network\ppc405_0\libsrc\linux_mvl31_v1_01_a\linux\drivers\net\"=0A=0A=
I see that it is empty.  Which means that nothing in the MVL tree will be o=
verwritten (specifically the adapter.c file, which uses the above defines).=
=0A=0ASo, it appears that the driver is not being properly insterted into t=
he tree as expected.  Would you agree?=0A=0A-R=0A=0A

^ permalink raw reply


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