LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: AltiVec in the kernel
From: Paul Mackerras @ 2006-07-19 18:19 UTC (permalink / raw)
  To: Linas Vepstas; +Cc: 'linuxppc-dev list'
In-Reply-To: <20060719181047.GL5905@austin.ibm.com>

Linas Vepstas writes:

> But perhaps, in principle, couldn't one run four independent streams 
> in parallel?  Thus, for example, on an SSL-enabled web server, one 
> could service multiple encryption/decryption threads at once. 

Generally that would work.  If one had 4 separate streams to compute a
SHA1 of, one could do all 4 at once with altivec.  It would have to be
4 separate streams though, not 4 parts of a single stream.

> As to non-kernel applications, is there anything for GMP (the 
> Gnu Multi-Precision library, an arbitrary-precision math library)
> on the Altivec? How aout the Cell?

I don't really know, sorry.

Paul.

^ permalink raw reply

* Re: MPC8260 SCC UART hardware flow control
From: Wolfgang Denk @ 2006-07-19 18:37 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linuxppc-embedded
In-Reply-To: <200607191718.00328.laurent.pinchart@tbox.biz>

In message <200607191718.00328.laurent.pinchart@tbox.biz> you wrote:
> 
> I was wondering if anyone had implemented hardware flow control support in the 
> cpm_uart driver. If not, I would appreciate pointers regarding how to do so.

You can probably take our 2.4 kernel code as a starting point. But be
aware of the inherent restrictions of the CPM, see
http://www.denx.de/wiki/view/DULG/UseSCCUARTWithHardwareHandshake

[In the end, you might want to configure  the  handshake  signals  as
GPIO lines and controll these manually. But then you will have to ask
yourself why you are using a CPM...]

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
The average woman would rather have beauty than brains,  because  the
average man can see better than he can think.

^ permalink raw reply

* Re: AltiVec in the kernel
From: Johannes Berg @ 2006-07-19 18:38 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: 'linuxppc-dev list'
In-Reply-To: <17598.30626.663773.229019@cargo.ozlabs.ibm.com>

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

On Thu, 2006-07-20 at 04:19 +1000, Paul Mackerras wrote:
> Linas Vepstas writes:
> 
> > But perhaps, in principle, couldn't one run four independent streams 
> > in parallel?  Thus, for example, on an SSL-enabled web server, one 
> > could service multiple encryption/decryption threads at once. 
> 
> Generally that would work.  If one had 4 separate streams to compute a
> SHA1 of, one could do all 4 at once with altivec.  It would have to be
> 4 separate streams though, not 4 parts of a single stream.

I'd think it'd be pretty hard to get a real benefit from this because
the data is going to come from 4 totally different places, hence you
can't just load a single vector register and get data for all 4
streams...

johannes

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

^ permalink raw reply

* Re: [PATCH] Add USB to MPC8349 PB platform support
From: Li Yang @ 2006-07-19 18:59 UTC (permalink / raw)
  To: Dan Malek; +Cc: linuxppc-dev, linux-usb-devel
In-Reply-To: <1E6652B1-3126-4B69-BE9D-8DCE8DCACE7C@embeddedalley.com>

On 7/19/06, Dan Malek <dan@embeddedalley.com> wrote:
>
> On Jul 19, 2006, at 9:14 AM, Kumar Gala wrote:
>
> > This is an incorrect assumption.  Its more often that people dont
> > post their ports to the Linux kernel for acceptance.  We will
> > accept any port that is willing to work with the community.   for
> > example
>
> I agree.  The customers of board ports I've done over the years
> are always eager to get these into the public sources.  It just
> seems we run out of time during the pressure of trying to get
> the products done, and they just issue them on CDs or for
> download afterward.

But why?  Most embedded products facing end-user wouldn't like users
to modify the system by themselves.  Sometimes they even put effort in
preventing user to do so.  If no one else is going to modify the code,
what is the value of putting them in public sources?  Just to show the
compliance with GPL?  The only kind of products I can think of, which
want the users to modify the code is reference boards, IMHO.  Please
correct me if I'm wrong.

^ permalink raw reply

* export-objs in spi Makefile broke in latest linuxppc_2_4_devel?
From: Rowan, Chad @ 2006-07-19 19:01 UTC (permalink / raw)
  To: linuxppc-embedded

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

Shouldn't export-objs in drivers\spi be:

            export-objs := spi-core.o spi-algo-mpc5xxx.o
spi-algo-mpc5xxx-psc.o \
               spi-iti5200.o spi-eval.o

 

instead of:

            export-objs := spi-core.o spi-algo-mpc5xxx.o
spi-algo-mpc5200psc.o \
               spi-iti5200.o spi-eval.o

            



 


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

^ permalink raw reply

* Re: [linux-usb-devel] [PATCH] Add USB to MPC8349 PB platform support
From: Pete Zaitcev @ 2006-07-19 19:19 UTC (permalink / raw)
  To: Li Yang; +Cc: linuxppc-dev, zaitcev, linux-usb-devel
In-Reply-To: <a0bc9bf80607191159l679ce8ddm35a30236a9d887c7@mail.gmail.com>

On Thu, 20 Jul 2006 02:59:44 +0800, "Li Yang" <LeoLi@freescale.com> wrote:

> But why?  Most embedded products facing end-user wouldn't like users
> to modify the system by themselves.

Certainly vendors won't like to give consumers extra freedoms.
However, consumers like those freedoms, even if they would not
use them in any specific instance.

>  Sometimes they even put effort in preventing user to do so.

Jerks and criminals, that's what they are. Why would Linux developers
care about needs of these people?

Free software is about protecting the rights of users against
vendors who "wouldn't like" users doing what they want with the
product they bought.

> The only kind of products I can think of, which
> want the users to modify the code is reference boards, IMHO.

Ever heard of WRT54? But in fact, every product out there may provide
its owner an additional value when customized. I'd love to fix some
bugs in my microwave, for instance. The silly thing will not start
the timer if the door is open. It probably uses the same function
which prevents cooking from starting (it also has a hardware interlock
that cuts the magnetron, but this is different).

-- Pete

^ permalink raw reply

* Re: AltiVec in the kernel
From: Linas Vepstas @ 2006-07-19 18:57 UTC (permalink / raw)
  To: Johannes Berg; +Cc: 'linuxppc-dev list', Paul Mackerras
In-Reply-To: <1153334301.2546.40.camel@johannes.berg>

On Wed, Jul 19, 2006 at 08:38:21PM +0200, Johannes Berg wrote:
> On Thu, 2006-07-20 at 04:19 +1000, Paul Mackerras wrote:
> > Linas Vepstas writes:
> > 
> > > But perhaps, in principle, couldn't one run four independent streams 
> > > in parallel?  Thus, for example, on an SSL-enabled web server, one 
> > > could service multiple encryption/decryption threads at once. 
> > 
> > Generally that would work.  If one had 4 separate streams to compute a
> > SHA1 of, one could do all 4 at once with altivec.  It would have to be
> > 4 separate streams though, not 4 parts of a single stream.
> 
> I'd think it'd be pretty hard to get a real benefit from this because
> the data is going to come from 4 totally different places, hence you
> can't just load a single vector register and get data for all 4
> streams...

Dohh. Right. I actually thought that while writing the email, and then
it eveporated from my head before I hit the send button.  One would 
have to copy the incoming data into vectors, and the mem access latency
would probably overwhelm the performance gain (per "hot cache" as Paul
discussed).

--linas

^ permalink raw reply

* export-objs in spi Makefile broke in latest linuxppc_2_4_devel [r eposted]?
From: Rowan, Chad @ 2006-07-19 19:13 UTC (permalink / raw)
  To: linuxppc-embedded

Shouldn't export-objs in drivers/spi be:

export-objs	:= spi-core.o spi-algo-mpc5xxx.o spi-algo-mpc5xxx-psc.o \
		   spi-iti5200.o spi-eval.o

instead of:
	
export-objs	:= spi-core.o spi-algo-mpc5xxx.o spi-algo-mpc5200psc.o \
		   spi-iti5200.o spi-eval.o

I believe the spi-algo-mpc5200psc.o should be spi-algo-mpc5xxx-psc.o,
correct?

Excuse the previous post.  Office, hosed the format.

^ permalink raw reply

* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
From: Guennadi Liakhovetski @ 2006-07-19 20:02 UTC (permalink / raw)
  To: Mark A. Greer; +Cc: linuxppc-dev
In-Reply-To: <20060523005846.GA15797@mag.az.mvista.com>

Mark, Ben,

On Mon, 22 May 2006, Mark A. Greer wrote:

> Thanks for your time, Ben.  Sorry for taking so long to get back to you.

don't have much to comment to specific points, but quoting the entire 
discussion below in case you'll want to further add to it.

What's the status of this work? Mark, have you been further working on 
your port? I'd like to integrate kurobox/linkstation support with 
sandpoint (also 8241). I think, it would be very interesting as it would 
allow us to develop / test the "universal" kernel idea, and at the same 
time explore the limits of board-specific support. Kurobox have a couple 
of very nice "specialities", like a serially attached AVR acting as a 
power-manager, thus requiring __special__ halt and reboot callbacks (so, 
please, Ben, don't remove them).

Any progress with fdt-parsing library for the wrapper / kernel and with 
replacing hard-coded constants and tables with dt-entries?

I'd love to discuss the stuff and come to an acceptable design / APIs.

Thanks
Guennadi

> For the record, this patch was only a hack that I've done to get a sandpoint
> up ASAP.  I should have made it clear to not take Kconfig, etc. stuffs very
> seriously.  I was more worried about how we should fit flattened dt into the
> bootwrapper.
> 
> I'm glad you did look at it so closely though and bring up a lot of good
> questions.  I'm not familiar with 64-bit platforms so all of my babbling
> below is based on my 32-bit platform knowledge.
> 
> Mark
> ---
> 
> On Thu, May 18, 2006 at 03:32:55PM +1000, Benjamin Herrenschmidt wrote:
> > On Wed, 2006-05-17 at 17:21 -0700, Mark A. Greer wrote:
> 
> <snip>
> 
> > > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> > > index 6729c98..de09eac 100644
> > > --- a/arch/powerpc/Kconfig
> > > +++ b/arch/powerpc/Kconfig
> > > @@ -323,7 +323,10 @@ config PPC_ISERIES
> > >  
> > >  config EMBEDDED6xx
> > >  	bool "Embedded 6xx/7xx/7xxx-based board"
> > > -	depends on PPC32 && BROKEN
> > > +	depends on PPC32
> > > +	select PPC_UDBG_16550
> > > +	select MPIC
> > > +	select MPIC_SERIAL
> > 
> > Not totally related to your patch but I'm tempted to turn that into a
> > "Generic 6xx/7xx/7xxx" rather than "embedded" if we manage to always
> > avoid board specific code most of the time, but instead add necessary
> > bits in the device-tree. We still need a per-board Kconfig option I
> > think that will just select the necessary bits and pieces (and more than
> > one can be selected at one time). Also, I think right now, the embedded
> > stuff is +/- exclusive from the MULTIPLATFORM stuff, that must be fixed
> > asap. We are all living in the same kernel now :)
> 
> OK.
> 
> > > +
> > > +config MPIC_SERIAL
> > > +	depends on EMBEDDED6xx
> > > +	bool
> > > +	default n
> > 
> > Not sure what the above is, I'll have a look further in the patch but I
> > can already tell you that it should be your per-board
> > CONFIG_PPC_SANDPOINT for example that "selects" the various bits you
> > need, and thus the above should depend on it, not EMBEDDED6xx... In fact
> > I'm wondering wether we should kill EMBEDDED6xx :) Unless it's purely a
> > reference to arch/powerpc/platforms/embedded6xx/ as a storage place for
> > board setup_xxx.c files which is useful for platforms that really don't
> > need more than one or 2 files in there.
> 
> I have no attachment to "embedded" so I'm happy to see it
> go...especially if I correctly understand what you're saying below.
> 
> > > +ifeq ($(CONFIG_EMBEDDED6xx),y)
> > > +src-boot += prom_embedded.c ns16550.c dts/sandpoint.S \
> > > +	dt_utils.c sandpoint.c mpc10x.c
> > > +else
> > > +src-boot += prom.c
> > > +endif
> > 
> > Again, I think CONFIG_EMBEDDED6xx is the wrong approach.  I'd like to
> > avoid the word "embedded" altogether anyway :) Thing is, it would be
> > good if ultimately, embedded boards firmware was capable of passing a
> > device-tree. Thus, embedded a device-tree in the zImage wrapper is more
> > like a "fallback" solution which has the side effect of creating machine
> > specific zImage's.
> >
> > That is why, I think, what we should do is have rules for building
> > separate zImage wrappers. The basic OF one (which exists in both real
> > and virtual mode versions and that I'd like to make capable of also
> > working if a flat device-tree is passed in), the zImage.sandpoint, the
> > zImage.prep, and whatever...
> >
> > Thus enabling CONFIG_PPC_MYBOARD should trigger the build of the
> > board-flavored version of the wrapper in addition to all the other ones
> > for the other boards built as part of a given config.
> >
> > I know it's a bit difficult because the current boot Kbuild rules aren't
> > really design for multiple targets but I think that's the way to go.
> 
> Okay, to make sure I understand, you're saying that you want to support a
> .config file having several CONFIG_PPC_BOARD1, CONFIG_PPC_BOARD2,
> CONFIG_PPC_BOARD3 defined at the same time.  The resulting zImage would
> run on all 3 boards, right?
> 
> I'd be happy with that.  It should meet the requirements of both
> the multiplatform and embedded folks.  You could combine that with the
> tool paulus talked about a couple weeks ago which would tack the
> appropriate flattened device tree (fdt) onto the zImage after the fact.
> 
> http://ozlabs.org/pipermail/linuxppc-dev/2006-April/022435.html
> 
> We just need to come up with the tool and make the bootwrapper code
> smart enough to know what dt to use (an OF dt, an fdt from a firmware, a
> fdt tacked on by the tool (along with code to take bd stuff & put it
> into the fdt?)).
> 
> All of the boards would likely have to be of the same "class".
> Where "class" would be:
> 	1) OF system
> 	2) e300 core + PQIIPro (e.g., 83xx)
> 	3) e500 core + PQIII (e.g., 85xx)
> 	4) 6xx/7xx/74xx + mpc10x (e.g., sandpoint)
> etc.  Something like that, anyway--maybe there are only "OF" and
> "non-OF'?
> 
> Basically, if its not OF, then its classified by its core + bridge.
> 
> So, first thing the zImage does is look for an attached ftb (attached by
> paulus' tool).  If its there, use it.  If its not there, use either the
> OFDT (for OF class) or expect a dt to be passed in from the firmware (for
> all the other classes).  That way you can easily override the dt in the field.
> 
> >  .../...
> > 
> > About the .dts file, we should look into "shipping" a pre-built one so
> > that dtc is not required for building a kernel.
> 
> Okay, paulus' tool would allow that.  We should also make it smart
> enough to replace an attached dts (really dtb--'b' for 'binary') with
> a new one.
> 
> > I think we already have
> > a mecanism for providing "shipped" versions of files and having the
> > option of rebuilding them from source (though I don't have the details
> > in mind at the moment) 
> 
> I don't know what you're referring to here.
> 
> > > diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
> > 
> >  .../.. io stuffs ...
> > 
> > Well... io accessors in here can't harm, the question is more how they
> > are used ;)
> >
> > > +#define	PCI_DEVFN(slot,func)	((((slot) & 0x1f) << 3) | ((func) & 0x07))
> > > +
> > > +/* Indirect PCI config space access routines */
> > > +static inline void
> > > +pci_indirect_read_config_byte(u32 *cfg_addr, u32 *cfg_data, int devfn,
> > > +		int offset, u8 *val)
> > > +{
> > > +	out_be32(cfg_addr,
> > > +		((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
> > > +	*val = in_8((u8 *)(cfg_data + (offset & 3)));
> > > +	return;
> > > +}
> > > +
> > > +static inline void
> > > +pci_indirect_read_config_dword(u32 *cfg_addr, u32 *cfg_data, int devfn,
> > > +		int offset, u32 *val)
> > > +{
> > > +	out_be32(cfg_addr,
> > > +		((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
> > > +	*val = in_le32(cfg_data + (offset & 3));
> > > +	return;
> > > +}
> > 
> > That's more annoying... if we start having PCI config space access in
> > the boot wrapper how far will it stop ? I'd rather keep that sort of
> > stuff local to myboard.c file unless it's really worth sharing... Unless
> > we end up with really common need for them in which case those should be
> > in separate files, possibly in a separate dir (thinking about it, prep
> > will probably need that too)
> 
> Sure.  I was just grabbing code I needed and sticking it whereever to
> get things to work.  If mpc10x.c is the only one that uses those routines
> then they should be in that file only.
> 
> > The main problem is how do we do printf kind of things from such a
> > bootloader. That needs IO, thus uart drivers etc... possibly parsing
> > from the device-tree etc... I'm tempted to just have a global
> > "boot_puts" function pointer set by the board and/or OF code to use
> > through the bootloader, maybe a shared uart.c file with various uart
> > bits and keep the gory implementation details of mapping the uart and
> > using those uart bits in the myboard.c file...
> 
> Okay.
> 
> Question: are we still going to allow cmdline editing in the
> bootwrapper?  If so, we also need to get uart input and munge the dtb
> to put the new args back into the /chosen/bootargs field.
> 
> > > +#ifdef CONFIG_PPC_OF
> > >  typedef void (*kernel_entry_t)( unsigned long,
> > >                                  unsigned long,
> > >                                  void *,
> > >  				void *);
> > > +#else
> > > +void platform_fixups(void *dt_blob);
> > > +extern void *dt_blob_start;
> > > +extern void *dt_blob_end;
> > > +void edit_cmdline(void *dt_blob_start);
> > > +typedef void (*kernel_entry_t)(void *dtb_addr, void *kernel_entry_paddr,
> > > +		void *must_be_null);
> > > +#endif
> > 
> > Why 2 different prototypes for kernel_entry ?
> 
> One for "OF", one for "non-OF" but I'll change it to
> "typedef void (*kernel_entry_t)(void *addr, ...);"
> to support both.  Hrm, I may have another idea...  Anyway, I'll do
> something about the #ifdef.
> 
> > I think we need something like CONFIG_PPC_BOOT_HAS_BUILTIN_DT that
> > enables various DT related stuff in a clean way and have a builtin_dt.h
> > file with related prototypes & definitions.
> 
> If we have the tool mentioned above, we shouldn't need a CONFIG option.
> Just check for a NULL ptr or something like that which indicates there's
> no dtb attached.
> 
> > >  #undef DEBUG
> > > @@ -218,7 +227,7 @@ void start(unsigned long a1, unsigned lo
> > >  	if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
> > >  		exit();
> > >  
> > > -	printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
> > > +	printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start,sp);
> > 
> > Gratuituous uglyfication :)
> 
> Again, I was just hacking stuff...
> 
> <snip>
> 
> > >  
> > >  	/* Eventually gunzip the kernel */
> > > @@ -299,6 +311,7 @@ #endif
> > >  	flush_cache((void *)vmlinux.addr, vmlinux.size);
> > >  
> > >  	kernel_entry = (kernel_entry_t)vmlinux.addr;
> > > +#ifdef CONFIG_PPC_OF
> > >  #ifdef DEBUG
> > >  	printf( "kernel:\n\r"
> > >  		"        entry addr = 0x%lx\n\r"
> > > @@ -311,9 +324,20 @@ #ifdef DEBUG
> > >  #endif
> > 
> > >  	kernel_entry(a1, a2, prom, NULL);
> > > +#else /* !CONFIG_PPC_OF ==> flattened device tree */
> > > +#ifdef DEBUG
> > > +	printf("kernel:\n\r"
> > > +		"        entry addr   = 0x%lx\n\r"
> > > +		"        flattened dt = 0x%lx\n\r",
> > > +		(unsigned long)kernel_entry, &dt_blob_start);
> > > +#endif
> > > +	edit_cmdline(&dt_blob_start);
> > > +	platform_fixups(&dt_blob_start);
> > >  
> > > +	kernel_entry(&dt_blob_start, (void *)vmlinux.addr, NULL);
> > > +#endif
> > 
> > Let's avoid #ifdef's if we can... provide function pointers where it
> > matter setup by the board/OF init code maybe but not ifdef's. Afaik,
> > only WD actually _likes_ ifdef's :)
> 
> I'll fix it up.
> 
> > > +++ b/arch/powerpc/boot/mpc10x.c
> > 
> > We'll need some subdirs here or it will get messy quick...
> 
> Yep.
> 
> > > diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
> > 
> > Same comment as above
> > 
> > > +/* XXXX Get info from dt instead */
> > > +static struct {
> > > +	int baud_base;
> > > +	unsigned long com_port;
> > > +	u16 iomem_reg_shift;
> > > +} rs_table[RS_TABLE_SIZE] = {
> > > +        { BASE_BAUD, SANDPOINT_SERIAL_0, 0 },
> > > +        { BASE_BAUD, SANDPOINT_SERIAL_1, 0 },
> > > +};
> > 
> > Well, your own comment says it all :) I think we might need an
> > equivalent of prom_parse.c in the bootloader
> 
> Yes, this was just a hack to get the sandpoint going.
> 
> > +
> > > +/* #ifndef CONFIG_PPC_OF XXXX */
> > > +
> > > +/* Definitions used by the flattened device tree */
> > > +#define OF_DT_HEADER		0xd00dfeed	/* marker */
> > > +#define OF_DT_BEGIN_NODE	0x1		/* Start of node, full name */
> > > +#define OF_DT_END_NODE		0x2		/* End node */
> > > +#define OF_DT_PROP		0x3		/* Property: name off, size,
> > > +						 * content */
> > > +#define OF_DT_NOP		0x4		/* nop */
> > > +#define OF_DT_END		0x9
> > > +
> > > +#define OF_DT_VERSION		0x10
> > 
> >    .../... (flat DT definitions)
> > 
> > Can't we share the kernel definition here ? Maybe split the kenrel one
> > in two if necessary ? I don't like that sort of duplication...
> 
> I hope so.  I'm hoping we can make a special dir somewhere that has the
> definitions of stuff shared between the bootwrapper & the kernel.
> 
> How about arch/powerpc/shared?  I dunno, something sensible.
> 
> > > +unsigned long serial_init(int chan, void *ignored);
> > > +void serial_putc(unsigned long com_port, unsigned char c);
> > > +unsigned char serial_getc(unsigned long com_port);
> > > +int serial_tstc(unsigned long com_port);
> > 
> > Forgot to mention that earlier, but those should be uart_* imho (or even
> > 16550_*) since we'll surely have different species of serial ports to
> > deal with and I don't like name mixup. Unless we consider that only ever
> > one of those serial files get built in a given zImage wrapper in which
> > case it makes some sense...
> 
> Okay.
> 
> > > +call_prom(const char *service, int nargs, int nret, ...)
> > > +{
> > > +
> > > +	static struct {
> > > +		char	*service;
> > > +		int	((*rtn)(int nargs, int nret, va_list args));
> > > +	} services[] = {
> > > +		{ "exit", service_exit },
> > > +		{ "finddevice", service_finddevice },
> > > +		{ "getprop", service_getprop },
> > > +		/* { "write", service_write }, */
> > > +	};
> > > +	va_list args;
> > > +	int i, rc = 0;
> > > +
> > > +	for (i=0; i<ARRAY_SIZE(services); i++)
> > > +		if (!strcmp(service, services[i].service)) {
> > > +			va_start(args, nret);
> > > +			rc = services[i].rtn(nargs, nret, args);
> > > +			va_end(args);
> > > +		}
> > > +
> > > +	return (nret > 0)? rc : 0;
> > > +}
> > 
> > I don't think call_prom is the right abstraction :) We have to decide
> > here, we have two choices:
> > 
> >  - Either a given zImage wrapper can be booted from both a real OF and
> > have an embedded flat DT, in which case we need function pointers and I
> > think the right abstraction is for individual prom functions to have
> > their function pointer rathaer than "multiplex" through call_prom
> > 
> >  - Or a given zImage wrapper is a single board thingy. That is it is
> > either the OF wrapper _or_ it can contain an embedded DT. Probably
> > easier that way and no need for funciton pointers nor mux at all... I
> > tend to think that might be the right way to go at this point...
> > Especially since as I wrote before, I'm tempted to think we should just
> > in that case build multiple zImage wrappers. The only thing there is
> > that if we go that route, I'd like the "OF" one to also be able to boot
> > with a flat DT passed on entry to it so it will be useable as a generic
> > zImage for firmwares that have a flat DT to pass to the kernel. The only
> > "issue" with that is it might be difficult to have console output unless
> > we do the putc function pointer thing I described earlier and have
> > several "uart" impleentations with differnet names and enough
> > device-tree parsing to be able to instanciate them (almost a copy of
> > kernel's legacy serial stuff). Another option if we want console output
> > is to add something to the DT header specifically for use by such early
> > boot code that specifies a function that can be called back for
> > displaying thing as long as a given memory range isn't overriden (the FW
> > itself)
> > 
> > Comments are welcome here, this is I think the most tricky point and
> > where we need to make a decision...
> 
> I'm very happy to not use the 'call_prom' abstraction. :)
> 
> I guess I have the first one in mind.  You have a zImage that runs on
> 1 to n different platforms.  The zImage has to determine which DT to use
> (OF DT, fdt from firmware, fdt attached by tool) and pick it apart to
> find the I/O resources and serial driver to use.  The CONFIG_<BOARD>'s
> that are defined would determine the drivers that get built in to the zImage.
> 
> > > diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
> > > index 6e67b5b..2feca55 100644
> > > --- a/arch/powerpc/kernel/legacy_serial.c
> > > +++ b/arch/powerpc/kernel/legacy_serial.c
> > > @@ -147,9 +147,11 @@ static int __init add_legacy_isa_port(st
> > >  	if (reg == NULL)
> > >  		return -1;
> > >  
> > > +#if 0 /* XXXX */
> > >  	/* Verify it's an IO port, we don't support anything else */
> > >  	if (!(reg[0] & 0x00000001))
> > >  		return -1;
> > > +#endif
> > 
> > Gack ? Care to explain ?
> 
> This 'if' always executed and threw me into the weeds.  I didn't get
> back to really figuring it out.  This was a hack to get going.
> 
> > > +obj-$(CONFIG_EMBEDDED6xx)	+= embedded6xx/
> > 
> > Hrmph.... (random noises)
> 
> ?  No, I needed that to get the build to go into platforms/embedded6xx.
> Since platforms/embedded6xx was already there, I assumed that was where
> I was to put things like the sandpoint.  If/when we get rid of
> "embedded", I'll move it to whereever it should go then.
> 
> > > +/*
> > > + * Define all of the IRQ senses and polarities.  Taken from the
> > > + * Sandpoint X3 User's manual.
> > > + */
> > > +static u_char sandpoint_openpic_initsenses[] __initdata = {
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 0: SIOINT */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 1: XXXX FILL?? */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 2: PCI Slot 1 */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 3: PCI Slot 2 */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 4: PCI Slot 3 */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 5: PCI Slot 4 */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 6: XXXX FILL?? */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 7: XXXX FILL?? */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 8: IDE (INT C) */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 9: IDE (INT D) */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 10: */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 11: */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 12: */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 13: */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 14: */
> > > +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 15: */
> > > +};
> > 
> > Of course you already know that this has to go into the device-tree :)
> 
> Yeah, I guess it should.  I'll have to figure out how to do that.
> 
> > > +/*
> > > + * Interrupt setup and service.  Interrrupts on the Sandpoint come
> > > + * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
> > > + * The 8259 is cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4,
> > > + * IDE is on EPIC 7 and 8.
> > > + */
> > > +static void __init
> > > +sandpoint_init_IRQ(void)
> > > +{
> > > +	struct mpic *mpic;
> > > +	phys_addr_t openpic_paddr = 0xfc000000 + /* XXXX */
> > > +		MPC10X_EUMB_EPIC_OFFSET;
> > > +
> > > +	/* This doesn't handle i2c, dma, i2o, or timer intrs right now XXXX */
> > > +	mpic = mpic_alloc(openpic_paddr, MPIC_PRIMARY,
> > > +			16 /* XXXX otherwise num_sources used */ ,
> > > +			NUM_8259_INTERRUPTS,
> > > +			0, /* was 16 */
> > > +			NR_IRQS - 4 /* XXXX */,
> > > +			sandpoint_openpic_initsenses,
> > > +			sizeof(sandpoint_openpic_initsenses), " EPIC     ");
> > > +
> > > +	BUG_ON(mpic == NULL); /* XXXX */
> > > +	mpic_assign_isu(mpic,  0, openpic_paddr + 0x10200);
> > > +	mpic_init(mpic);
> > > +	mpic_setup_cascade(NUM_8259_INTERRUPTS, i8259_irq_cascade, NULL);
> > > +	i8259_init(0xfef00000, 0); /* pci iack addr */
> > > +}
> > 
> > It would be really nice if we could define properties to put in the
> > "mpic" node that defines the various attributes to pass to it and that
> > sort of thing so that we can have a generic "mpic_init_IRQ" that walks
> > all MPICs and instanciate & link them in cascade when necessary... Oh
> > well, food for thought, no high priority there.
> 
> That would be great to have!
> 
> > > +/*
> > > + * Freescale Sandpoint interrupt routing.
> > > + */
> > > +static inline int
> > > +x3_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
> > > +{
> > > +	static char pci_irq_table[][4] =
> > > +	/*
> > > +	 *	PCI IDSEL/INTPIN->INTLINE
> > > +	 * 	   A   B   C   D
> > > +	 */
> > > +	{
> > > +		{ 16,  0,  0,  0 },	/* IDSEL 11 - i8259 on Winbond */
> > > +		{  0,  0,  0,  0 },	/* IDSEL 12 - unused */
> > > +		{ 18, 21, 20, 19 },	/* IDSEL 13 - PCI slot 1 */
> > > +		{ 19, 18, 21, 20 },	/* IDSEL 14 - PCI slot 2 */
> > > +		{ 20, 19, 18, 21 },	/* IDSEL 15 - PCI slot 3 */
> > > +		{ 21, 20, 19, 18 },	/* IDSEL 16 - PCI slot 4 */
> > > +	};
> > > +
> > > +	const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
> > > +	return PCI_IRQ_TABLE_LOOKUP;
> > > +}
> > 
> > Of course you also know that the above has to go into the device-tree as
> > well :)
> 
> Okay...  :)
> 
> > > +static void __init
> > > +sandpoint_setup_winbond_83553(struct pci_controller *hose)
> > > +{
> > > +	int		devfn;
> > > +
> > > +	/*
> > > +	 * Route IDE interrupts directly to the 8259's IRQ 14 & 15.
> > > +	 * We can't route the IDE interrupt to PCI INTC# or INTD# because those
> > > +	 * woule interfere with the PMC's INTC# and INTD# lines.
> > > +	 */
> > > +	/*
> > > +	 * Winbond Fcn 0
> > > +	 */
> > > +	devfn = PCI_DEVFN(11,0);
> > > +
> > > +	early_write_config_byte(hose,
> > > +				0,
> > > +				devfn,
> > > +				0x43, /* IDE Interrupt Routing Control */
> > > +				0xef);
> > > +	early_write_config_word(hose,
> > > +				0,
> > > +				devfn,
> > > +				0x44, /* PCI Interrupt Routing Control */
> > > +				0x0000);
> > > +
> > > +	/* Want ISA memory cycles to be forwarded to PCI bus */
> > > +	early_write_config_byte(hose,
> > > +				0,
> > > +				devfn,
> > > +				0x48, /* ISA-to-PCI Addr Decoder Control */
> > > +				0xf0);
> > > +
> > > +	/* Enable Port 92.  */
> > > +	early_write_config_byte(hose,
> > > +				0,
> > > +				devfn,
> > > +				0x4e,	/* AT System Control Register */
> > > +				0x06);
> > > +	/*
> > > +	 * Winbond Fcn 1
> > > +	 */
> > > +	devfn = PCI_DEVFN(11,1);
> > > +
> > > +	/* Put IDE controller into native mode. */
> > > +	early_write_config_byte(hose,
> > > +				0,
> > > +				devfn,
> > > +				0x09,	/* Programming interface Register */
> > > +				0x8f);
> > > +
> > > +	/* Init IRQ routing, enable both ports, disable fast 16 */
> > > +	early_write_config_dword(hose,
> > > +				0,
> > > +				devfn,
> > > +				0x40,	/* IDE Control/Status Register */
> > > +				0x00ff0011);
> > > +	return;
> > > +}
> > 
> > How much of the above could/should be done by the wrapper since it does
> > config space access hacks ? My idea is that we might be able to remove
> > pretty much _everything_ from this sandpoint.c file ... My dream would
> > be to have a generic board support that matches a list of known boards
> > for which no special code is needed, only the device-tree (and possibly
> > the zImage wrapper).
> 
> That's a good dream.  :)
> 
> > The main things preventing us from doing that at the moment is that we
> > need to define enough standard nodes/properties to have the ability to
> > the setup interrupt controller tree entirely from it, and the PCI host
> > bridges as well. For the later, that means encoding enough of the bridge
> > type and config access method to allow having a generic device-tree
> > based piece of code that does what add_bridges() does in a generic way. 
> 
> Yep.
> 
> > > +static int
> > > +x3_exclude_device(u_char bus, u_char devfn)
> > > +{
> > > +	if ((bus == 0) && (PCI_SLOT(devfn) == 0))
> > > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > > +	else
> > > +		return PCIBIOS_SUCCESSFUL;
> > > +}
> > 
> > If we need to exclude devices in a generic way, we could define a
> > specific exclude list property... or use what I think has already been
> > defined by OF for indicating which slots should be probed :)
> 
> I'll try to do it through pci quirks, if I can.  If not, then I agree.
> 
> > > +static int __init
> > > +add_bridge(struct device_node *dev)
> > > +{
> > > +	int len;
> > > +	struct pci_controller *hose;
> > > +	int *bus_range;
> > > +
> > > +	printk("Adding PCI host bridge %s\n", dev->full_name);
> > > +
> > > +	bus_range = (int *) get_property(dev, "bus-range", &len);
> > > +	if (bus_range == NULL || len < 2 * sizeof(int))
> > > +		printk(KERN_WARNING "Can't get bus-range for %s, assume"
> > > +				" bus 0\n", dev->full_name);
> > > +
> > > +	hose = pcibios_alloc_controller();
> > > +	if (hose == NULL)
> > > +		return -ENOMEM;
> > > +	hose->first_busno = bus_range ? bus_range[0] : 0;
> > > +	hose->last_busno = bus_range ? bus_range[1] : 0xff;
> > > +	setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
> > > +
> > > +	/* Interpret the "ranges" property */
> > > +	/* This also maps the I/O region and sets isa_io/mem_base */
> > > +	pci_process_bridge_OF_ranges(hose, dev, 1);
> > > +
> > > +	return 0;
> > > +}
> > 
> > See above comments.... Looks ok but how many boards will end up having
> > very small variations of that same code and thus can we find a way to
> > make that totally generic...
> 
> Many...
> 
> > > +u32 mag_dbg = 0;
> > > +
> > > +static void __init
> > > +sandpoint_setup_arch(void)
> > > +{
> > > +	loops_per_jiffy = 100000000 / HZ;
> > > +	isa_io_base = 0xfe000000;
> > > +	isa_mem_base = 0x80000000;
> > > +	pci_dram_offset = 0;
> > 
> > The isa stuff should probably be deduced from the device-tree, the
> > default LPJ too, probably not even useful anymore since we are using the
> > timebase nowadays.
> 
> Okay.
> 
> > > +#ifdef CONFIG_BLK_DEV_INITRD
> > > +	if (initrd_start)
> > > +		ROOT_DEV = Root_RAM0;
> > > +	else
> > > +#endif
> > > +#ifdef	CONFIG_ROOT_NFS
> > > +		ROOT_DEV = Root_NFS;
> > > +#else
> > > +		ROOT_DEV = Root_HDA1;
> > > +#endif
> > 
> > Same comment as above, this is fairly generic and we could even imagine
> > something like a linux,default-boot-device thing in the DT...
> 
> OK.
> 
> > > +#if 1 /* XXXX NEW */
> > > +	{
> > > +		struct device_node *np;
> > > +
> > > +		mag_dbg = 1;
> > > +		for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
> > > +			add_bridge(np);
> > > +		mag_dbg = 0;
> > > +
> > > +		ppc_md.pci_swizzle = common_swizzle;
> > > +		ppc_md.pci_map_irq = x3_map_irq;
> > > +		ppc_md.pci_exclude_device = x3_exclude_device; /* XXXX */
> > > +	}
> > > +#endif
> > 
> > The problem of IRQ mapping & swizzling will be solved real soon
> > (hopefully early 2.6.18) so that we can completely rely on the
> > device-tree without needing device_node's for every PCI device. Only P2P
> > bridges that don't do standard swizzling (typically bridges soldered on
> > the motherboard) will require device nodes. I'm working on it :)
> > 
> > The idea is that the host bridge will need the standard interrupt-map &
> > interrupt-map-mask which will indicate the interrupt mapping for every
> > line of every slot/device in the standard way handled by OF (that
> > already works). And I'll add code that will be able to handle PCI
> > devices without a node by artificially building their "interrupts"
> > property based on the interrupt pin config space entry and walking up
> > the PCI tree, doing standard swizzling when encountering a P2P bridge
> > until we hit something with a device-node in which case we hook our
> > result to the interrupt-map of that device-node.
> 
> Cool.  I'll keep an eye out for that.
> 
> > > +	if (cpu_has_feature(CPU_FTR_SPEC7450))
> > > +		/* 745x is different.  We only want to pass along enable. */
> > > +		_set_L2CR(L2CR_L2E);
> > > +	else if (cpu_has_feature(CPU_FTR_L2CR))
> > > +		/* All modules have 1MB of L2.  We also assume that an
> > > +		 * L2 divisor of 3 will work.
> > > +		 */
> > > +		_set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
> > > +				| L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
> > 
> > Keeping in mind my idea of having as much generic code as possible,
> > whould we do the above in the boot wrapper or if not, should we provide
> > some DT entries indicating that L2CR should be reset and to which
> > values ?
> 
> I vote for a DT entry.
> 
> > > +#if 0
> > > +	/* Untested right now. */
> > > +	if (cpu_has_feature(CPU_FTR_L3CR)) {
> > > +		/* Magic value. */
> > > +		_set_L3CR(0x8f032000);
> > > +	}
> > > +#endif
> > > +}
> > 
> > Same comment as above but for L3CR
> 
> DT entry. :)
> 
> >  .../...
> > 
> > > +/*
> > > + * Fix IDE interrupts.
> > > + */
> > > +static int __init
> > > +sandpoint_fix_winbond_83553(void)
> > > +{
> > > +	/* Make some 8259 interrupt level sensitive */
> > > +	outb(0xe0, 0x4d0);
> > > +	outb(0xde, 0x4d1);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +arch_initcall(sandpoint_fix_winbond_83553);
> > > +
> > > +/*
> > > + * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip.
> > > + */
> > > +static int __init
> > > +sandpoint_setup_natl_87308(void)
> > > +{
> > > +	u_char	reg;
> > > +
> > > +	/*
> > > +	 * Enable all the devices on the Super I/O chip.
> > > +	 */
> > > +	SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */
> > > +	SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */
> > > +	SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */
> > > +	SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */
> > > +	SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */
> > > +	SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */
> > > +	SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */
> > > +	SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */
> > > +	SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
> > > +	SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */
> > > +	SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
> > > +
> > > +	/* Set up floppy in PS/2 mode */
> > > +	outb(0x09, SIO_CONFIG_RA);
> > > +	reg = inb(SIO_CONFIG_RD);
> > > +	reg = (reg & 0x3F) | 0x40;
> > > +	outb(reg, SIO_CONFIG_RD);
> > > +	outb(reg, SIO_CONFIG_RD);	/* Have to write twice to change! */
> > > +
> > > +	return 0;
> > > +}
> > 
> > Looks like zImage wrapper work to me... Unless we ever get booted by a
> > firmware that both provides a flat DT and doesn't do the above....
> >
> > Ok, I'm not _ABSOLUTELY_ trying to remove the need for a myboar.c file
> > here ... but it might be worth doing something generic enough so that
> > it's either reduced to the strict minimum in many cases _or_ made
> > completely unnecessary if we can...
> 
> OK
> 
> > > +arch_initcall(sandpoint_setup_natl_87308);
> > > +
> > > +static int __init
> > > +sandpoint_request_io(void)
> > > +{
> > > +	request_region(0x00,0x20,"dma1");
> > > +	request_region(0x20,0x20,"pic1");
> > > +	request_region(0x40,0x20,"timer");
> > > +	request_region(0x80,0x10,"dma page reg");
> > > +	request_region(0xa0,0x20,"pic2");
> > > +	request_region(0xc0,0x20,"dma2");
> > > +
> > > +	return 0;
> > > +}
> > 
> > The above has to go... not sure yet what is the best way but it's just a
> > pain... Could be made dependent on the OFDT too
> 
> OK
> 
> > > +arch_initcall(sandpoint_request_io);
> > > +#endif
> > > +
> > > +static void __init
> > > +sandpoint_map_io(void)
> > > +{
> > > +	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
> > > +}
> > 
> > To kill absolutely. What is it there for ? At the very least, make
> > io_block_mapping allocate virtual space as discussed earlier. I'd like
> > to keep BATs for RAM anyway
> 
> It'll go away eventually.
> 
> > > +static void
> > > +sandpoint_restart(char *cmd)
> > > +{
> > > +	local_irq_disable();
> > > +
> > > +	/* Set exception prefix high - to the firmware */
> > > +	_nmask_and_or_msr(0, MSR_IP);
> > > +
> > > +	/* Reset system via Port 92 */
> > > +	outb(0x00, 0x92);
> > > +	outb(0x01, 0x92);
> > > +
> > > +	for(;;);	/* Spin until reset happens */
> > > +}
> > 
> > The above is fairly common. (Or variations of it). In the context of a
> > "generic" board, we could imagine having a list of known "reboot
> > methods" and have a DT node indicating which one to use...
> 
> Yep.
> 
> > > +static void
> > > +sandpoint_power_off(void)
> > > +{
> > > +	local_irq_disable();
> > > +	for(;;);	/* No way to shut power off with software */
> > > +	/* NOTREACHED */
> > > +}
> > 
> > The above is _VERY_ commmon :) probably worth just not having a callback
> > in ppc_md. at all...
> > 
> > > +static void
> > > +sandpoint_halt(void)
> > > +{
> > > +	sandpoint_power_off();
> > > +	/* NOTREACHED */
> > > +}
> > 
> > Same comment as before.
> 
> I do see a couple in arch/ppc/platforms that do something different so
> how about keeping ppc_md.power_off/_halt but making the above the default
> (with only 1 implementation) which can be changed by board code?
> 
> > > +static void
> > > +sandpoint_show_cpuinfo(struct seq_file *m)
> > > +{
> > > +	seq_printf(m, "vendor\t\t: Freescale\n");
> > > +	seq_printf(m, "machine\t\t: Sandpoint\n");
> > > +}
> > 
> > Do we need that ? We could define standard DT properties that get
> > printed in cpuinfo and have that in setup-common.c ...
> 
> That would be better.
> 
> >  .../... (commented out IDE code)
> > 
> > This is a windbond ? Can't it just be probed/detected using normal PCI
> > probing ?
> 
> I have to revisit all of the IDE stuff in that file and figure out
> what's really needed (if any).  That's why I have it all '#if 0' right
> now.  I will get to it eventually.
> 
> > > +
> > > +/*
> > > + * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
> > > + */
> > > +static __inline__ void
> > > +sandpoint_set_bat(void)
> > > +{
> > > +	unsigned long bat3u, bat3l;
> > > +
> > > +	__asm__ __volatile__(
> > > +			" lis %0,0xf800\n	\
> > > +			ori %1,%0,0x002a\n	\
> > > +			ori %0,%0,0x0ffe\n	\
> > > +			mtspr 0x21e,%0\n	\
> > > +			mtspr 0x21f,%1\n	\
> > > +			isync\n			\
> > > +			sync "
> > > +			: "=r" (bat3u), "=r" (bat3l));
> > > +}
> > 
> > WTF ?
> 
> It'll disappear.  The sandpoint.c is copied from arch/ppc and hacked.
> Its pretty old so there's lots of code that can probably be weeded out.
> 
> > > +TODC_ALLOC();
> > > +
> > > +static int __init
> > > +sandpoint_probe(void)
> > > +{
> > > +	return 1;
> > > +}
> > 
> > WTF (bis) ? :)
> 
> bis?
> 
> Its just a hack to get it going.
> 
> > > +define_machine(sandpoint) {
> > > +	.name			= "Sandpoint",
> > > +	.probe			= sandpoint_probe,
> > > +	.setup_arch		= sandpoint_setup_arch,
> > > +	.setup_io_mappings	= sandpoint_map_io,
> > > +	.init_IRQ		= sandpoint_init_IRQ,
> > > +	.show_cpuinfo		= sandpoint_show_cpuinfo,
> > > +	.get_irq		= mpic_get_irq,
> > > +	.restart		= sandpoint_restart,
> > > +	.power_off		= sandpoint_power_off,
> > > +	.halt			= sandpoint_halt,
> > > +	.calibrate_decr		= generic_calibrate_decr,
> > > +	/*
> > > +	.progress		= udbg_progress,
> > > +	*/
> > > +};
> > 
> > So on the TODO list, replace as much as we can of the above with
> > generic_* equivalents until nothing remains :)
> 
> Yep, that's the goal.
> 
> > > diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
> > > index 7dcdfcb..1badbec 100644
> > > --- a/arch/powerpc/sysdev/mpic.c
> > > +++ b/arch/powerpc/sysdev/mpic.c
> > > @@ -629,6 +629,13 @@ #endif /* CONFIG_SMP */
> > >  			mb();
> > >  	}
> > >  
> > > +#ifdef CONFIG_MPIC_SERIAL
> > > +	/* For serial interrupts & set clock ratio */
> > > +	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1,
> > > +		mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1)
> > > +			| (1<<27) | (0x7<<28));
> > > +#endif
> > 
> > This should not be an #ifdef.... this should be an MPIC init flag passed
> > when initializing it. (and if we do generic device-tree instanciation of
> > PIC's, we could define standard properties to put in the MPIC node to
> > enable those flags).
> 
> Okay, I'll move it into the dt.
> 
> > Keep up the good work ! :)
> 
> Heh.
> 
> > Cheers,
> > Ben.
> 
> Thanks for the comments.
> 
> Mark
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

---
Guennadi Liakhovetski

^ permalink raw reply

* Re: [PATCH] Add USB to MPC8349 PB platform support
From: Kumar Gala @ 2006-07-19 20:09 UTC (permalink / raw)
  To: Li Yang; +Cc: linuxppc-dev, linux-usb-devel
In-Reply-To: <44B7857A.2060101@freescale.com>


On Jul 14, 2006, at 6:52 AM, Li Yang wrote:

> This adds USB platform support to MPC8349 PB.  It works with the  
> fsl_usb2_udc driver.
>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
>
> arch/powerpc/platforms/83xx/Kconfig       |   4  ++
> arch/powerpc/platforms/83xx/mpc834x_sys.c |   72 +++++++++++++++++++ 
> ++++++++++
> arch/powerpc/platforms/83xx/mpc834x_sys.h |   24 ++++++++++
> 3 files changed, 113 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/ 
> platforms/83xx/Kconfig
> index 7675e67..8404cdf 100644
> --- a/arch/powerpc/platforms/83xx/Kconfig
> +++ b/arch/powerpc/platforms/83xx/Kconfig
> @@ -24,4 +31,14 @@ config MPC834x
> 	select PPC_INDIRECT_PCI
> 	default y if MPC834x_SYS
>
> +config 834x_USB_SUPPORT
> +	bool
> +	default y if MPC834x_SYS && (USB || USB_GADGET)
> +	
> endmenu

I dont think we need this, we should be able to use the USB, and 834x  
CONFIG options in the code.

> diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/ 
> powerpc/platforms/83xx/mpc834x_sys.c
> index 7e789d2..f10d4ae 100644
> --- a/arch/powerpc/platforms/83xx/mpc834x_sys.c
> +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c
> @@ -36,6 +36,7 @@ #include <asm/irq.h>
> #include <asm/prom.h>
> #include <asm/udbg.h>
> #include <sysdev/fsl_soc.h>
> +#include <linux/fsl_devices.h>
> #include "mpc83xx.h"
> @@ -71,6 +72,72 @@ mpc83xx_map_irq(struct pci_dev *dev, uns
> }
> #endif				/* CONFIG_PCI */
> +#ifdef CONFIG_834x_USB_SUPPORT

Just make it dependent on CONFIG_USB_EHCI_HCD or something like that.

> +void mpc834x_usb_board_cfg(void)
> +{
> +	unsigned char __iomem *bcsr;
> +	volatile unsigned char *bcsr5_p;
> +
> +	/*
> +	 * if SYS board is plug into PIB board,
> +	 * force to use the PHY on SYS board
> +	 * */
> +	bcsr = ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
> +	bcsr5_p = bcsr + BCSR5_OFF;
> +	if ( (*bcsr5_p & BCSR5_INT_USB) == 0 )
> +		*bcsr5_p = (*bcsr5_p | BCSR5_INT_USB);
> +	iounmap(bcsr);
> +}
> +
> +/* Note: This is only for PB, not for PB+PIB
> + * On PB only port0 is connected using ULPI */
> +static int mpc834x_usb_cfg(void)
> +{
> +	unsigned long sccr, sicrl;
> +	volatile unsigned long *p;
> +	unsigned long __iomem *immap;
> +	struct device_node *np = NULL;
> +	int port0_is_dr = 0;
> +
> +	if ((np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) !=  
> NULL)
> +		port0_is_dr = 1;
> +	if ((np = of_find_compatible_node(np, "usb", "fsl-usb2-mph")) !=  
> NULL){
> +		if (port0_is_dr) {
> +			printk(KERN_WARNING
> +				"There is only one USB port on PB board! \n");
> +			return -1;
> +		} else if (!port0_is_dr)
> +			/* No usb port enabled */
> +			return -1;
> +	}
> +	
> +	immap = ioremap(get_immrbase(), 0x100000);
> +	
> +	/* Configure clock */
> +	p = (volatile unsigned long *)((u32)immap + MPC83XX_SCCR_OFFS);
> +	sccr = *p;
> +	if (port0_is_dr)
> +		sccr |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
> +	else
> +		sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
> +	*p = sccr;

This really needs to take into account the platform frequency.  I  
guess technically, at 1:3 we will always be below the max 133Mhz.

> +
> +	/* Configure Pin */
> +	p = (volatile unsigned long *)((u32)immap + MPC83XX_SICRL_OFFS);  
> +	sicrl = *p;
> +	/* set port0 only */
> +	if (port0_is_dr) +		sicrl |= MPC83XX_SICRL_USB0;
> +	else +		sicrl &= ~(MPC83XX_SICRL_USB0);
> +	*p = sicrl;
> +

Why dont we just do all this in fsl_usb_of_init

> +	iounmap(immap);
> +	return 0;
> +}
> +
> +#endif /* CONFIG_834x_USB_SUPPORT */
> +
> /*  
> ********************************************************************** 
> **
>  *
>  * Setup the architecture
> @@ -102,6 +169,11 @@ #ifdef CONFIG_PCI
> 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
> #endif
> +#ifdef CONFIG_834x_USB_SUPPORT
> +	mpc834x_usb_cfg();
> +	mpc834x_usb_board_cfg();
> +#endif
> +
> #ifdef  CONFIG_ROOT_NFS
> 	ROOT_DEV = Root_NFS;
> #else
> diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.h b/arch/ 
> powerpc/platforms/83xx/mpc834x_sys.h
> index fedecb7..30e45e8 100644
> --- a/arch/powerpc/platforms/83xx/mpc834x_sys.h
> +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.h
> @@ -20,4 +20,28 @@ #define PIRQB	MPC83xx_IRQ_EXT5
> #define PIRQC	MPC83xx_IRQ_EXT6
> #define PIRQD	MPC83xx_IRQ_EXT7
> +#define BCSR_PHYS_ADDR		((uint)0xf8000000)
> +#define BCSR_SIZE		((uint)(32 * 1024))
> + +#define BCSR5_OFF		0x05
> +#define BCSR5_INT_USB		0x02
> +
> +#define MPC83XX_SCCR_OFFS          0xA08
> +#define MPC83XX_SCCR_USB_MPHCM_11  0x00c00000
> +#define MPC83XX_SCCR_USB_MPHCM_01  0x00400000
> +#define MPC83XX_SCCR_USB_MPHCM_10  0x00800000
> +#define MPC83XX_SCCR_USB_DRCM_11   0x00300000
> +#define MPC83XX_SCCR_USB_DRCM_01   0x00100000
> +#define MPC83XX_SCCR_USB_DRCM_10   0x00200000
> +
> +/* system i/o configuration register low */
> +#define MPC83XX_SICRL_OFFS         0x114
> +#define MPC83XX_SICRL_USB0         0x40000000
> +#define MPC83XX_SICRL_USB1         0x20000000
> +
> +/* system i/o configuration register high */
> +#define MPC83XX_SICRH_OFFS         0x118
> +#define MPC83XX_SICRH_USB_UTMI     0x00020000

Are these really generic to all MPC83XX?  We should move these to  
include something like asm-ppc/mpc83xx.h

> +
> +
> #endif				/* __MACH_MPC83XX_SYS_H__ */

- kumar

^ permalink raw reply

* Re: [PATCH] Add USB to MPC8349 PB platform support
From: Timur Tabi @ 2006-07-19 20:13 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1153166894.4459.4.camel@basalt.austin.ibm.com>

Hollis Blanchard wrote:

> Seems to me that it's far better to have init code in the kernel than
> firmware. For one example, look at the x86 video card init problem
> PowerPC Linux has. It's also far easier to fix/deploy Linux code than
> firmware code, as Li observed, and on top of that it's less work for
> non-UBoot firmwares in the future.

I also agree 100%.  The boot loader should only be required to initialize whatever hardware it uses.  The kernel should be required to initialize whatever hardware it supports.  The kernel should not assume that USB or PCI or whatever has already been initialized by the boot loader.  This doesn't happen on x86, so we should it happen on PPC?

-- 
Timur Tabi
Linux Kernel Developer @ Freescale

^ permalink raw reply

* Re: [PATCH] Add USB to MPC8349 PB platform support
From: Marc Leeman @ 2006-07-19 20:19 UTC (permalink / raw)
  To: Dan Malek; +Cc: linuxppc-dev
In-Reply-To: <1E6652B1-3126-4B69-BE9D-8DCE8DCACE7C@embeddedalley.com>

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

> I agree.  The customers of board ports I've done over the years
> are always eager to get these into the public sources.  It just
> seems we run out of time during the pressure of trying to get
> the products done, and they just issue them on CDs or for
> download afterward.

For our boards, I am somewhat more eager to get our port in U-Boot than
in the Linux kernel for a number of reasons.

First; it is always interesting to see how other ppl handle simular
problems during boot up.

Secondly; U-Boot is used to set configuration options at bootup, e.g.
for multi purpose pins. Having your changes (to registers), fixes or
silicon bugs might help ppl and avoid them to look for a silicon bug
workaround.

If I submit a port of our board to U-Boot, clearly comment the changes
(e.g. enable GPIO on pin X while setting registers); I hope that some
ppl can use it. Next to this, Wolfgang is doing a *very* good job of
keeping his tree clean and giving good pointers to problems and clean up
strategies that serve us all.

Having my changes for our boards that are very specific since they are
connected to FPGAs would IMHO serve little purpose in the Linux kernel:
there is very limited access to the hardware and it would only serve to
clutter the kernel with an exponentionally growing number of ports that
most ppl will never use. I think (even though using ARCH and
CROSS_COMPILE during compilation limits the audience); the target
audience between U-Boot and the Linux kernel is slightly different.

Though I do agree that there is a gap: it would be nice to have some
place to submit the kernel patches; possibly not included in the main
tree; just to see how other ppl are tackling the same problem and
avoiding re-doing the same work for the nth time (e.g. writing some
communciation protocol where there are a number of references of ppl
haveing done them, but no real code).

-- 
  greetz, marc
Aeryn died so you could live John. She would want you to keep fighting.
	D'Argo - Season of Death
scorpius.homelinux.org 2.6.17 #2 PREEMPT Thu Jun 22 07:18:33 CEST 2006 GNU/Linux

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

^ permalink raw reply

* Re: [PATCH] Add USB to MPC8349 PB platform support
From: Kumar Gala @ 2006-07-19 20:48 UTC (permalink / raw)
  To: Timur Tabi; +Cc: linuxppc-dev
In-Reply-To: <44BE9268.9040806@freescale.com>


On Jul 19, 2006, at 3:13 PM, Timur Tabi wrote:

> Hollis Blanchard wrote:
>
>> Seems to me that it's far better to have init code in the kernel than
>> firmware. For one example, look at the x86 video card init problem
>> PowerPC Linux has. It's also far easier to fix/deploy Linux code than
>> firmware code, as Li observed, and on top of that it's less work for
>> non-UBoot firmwares in the future.
>
> I also agree 100%.  The boot loader should only be required to  
> initialize whatever hardware it uses.  The kernel should be  
> required to initialize whatever hardware it supports.  The kernel  
> should not assume that USB or PCI or whatever has already been  
> initialized by the boot loader.  This doesn't happen on x86, so we  
> should it happen on PPC?

Let's not drag what x86 does as a good or bad example of anything :)

- k

^ permalink raw reply

* Re: [PATCH] Add USB to MPC8349 PB platform support
From: Kumar Gala @ 2006-07-19 20:55 UTC (permalink / raw)
  To: Marc Leeman; +Cc: linuxppc-dev
In-Reply-To: <20060719201941.GW5219@scorpius.homelinux.org>

[snip]

> Having my changes for our boards that are very specific since they are
> connected to FPGAs would IMHO serve little purpose in the Linux  
> kernel:
> there is very limited access to the hardware and it would only  
> serve to
> clutter the kernel with an exponentionally growing number of ports  
> that
> most ppl will never use. I think (even though using ARCH and
> CROSS_COMPILE during compilation limits the audience); the target
> audience between U-Boot and the Linux kernel is slightly different.
>
> Though I do agree that there is a gap: it would be nice to have some
> place to submit the kernel patches; possibly not included in the main
> tree; just to see how other ppl are tackling the same problem and
> avoiding re-doing the same work for the nth time (e.g. writing some
> communciation protocol where there are a number of references of ppl
> haveing done them, but no real code).

This should be the kernel.  The general rule of thumb I've used is if  
its useful to more than one other person its worth trying to get into  
the kernel.  However, I can see if you are doing a one off kernel for  
your embedded product that getting your changes into the kernel  
wouldn't be worth while.  You have to have a desire to interact with  
the community if you want to get your code in.

Personally, I see it useful if for no other reason that someone will  
fixup my board port if/when they change something which will make my  
moving to a newer kernel release that much easier.

- k

^ permalink raw reply

* Re: export-objs in spi Makefile broke in latest linuxppc_2_4_devel [r eposted]?
From: Kumar Gala @ 2006-07-19 21:16 UTC (permalink / raw)
  To: Rowan, Chad; +Cc: linuxppc-embedded
In-Reply-To: <86EC6E02268B3D4BA41C1B0C61FB14E60B3C8335@mdcexc01.na.ops.local>


On Jul 19, 2006, at 2:13 PM, Rowan, Chad wrote:

> Shouldn't export-objs in drivers/spi be:
>
> export-objs	:= spi-core.o spi-algo-mpc5xxx.o spi-algo-mpc5xxx-psc.o \
> 		   spi-iti5200.o spi-eval.o
>
> instead of:
> 	
> export-objs	:= spi-core.o spi-algo-mpc5xxx.o spi-algo-mpc5200psc.o \
> 		   spi-iti5200.o spi-eval.o
>
> I believe the spi-algo-mpc5200psc.o should be spi-algo-mpc5xxx-psc.o,
> correct?

Are you really serious about linuxppc_2_4_devel?  I can't believe  
linuxppc_2_4_devel has changed in months (if not over a year).

- k

^ permalink raw reply

* RE: export-objs in spi Makefile broke in latest linuxppc_2_4_deve l [r eposted]?
From: Rowan, Chad @ 2006-07-19 22:02 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-embedded

linuxppc_2_4_devel is alive and well.

http://www.denx.de/cgi-bin/gitweb.cgi?p=linuxppc_2_4_devel.git;a=shortlog

-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org] 
Sent: Wednesday, July 19, 2006 4:17 PM
To: Rowan, Chad
Cc: linuxppc-embedded@ozlabs.org
Subject: Re: export-objs in spi Makefile broke in latest linuxppc_2_4_devel
[r eposted]?


On Jul 19, 2006, at 2:13 PM, Rowan, Chad wrote:

> Shouldn't export-objs in drivers/spi be:
>
> export-objs	:= spi-core.o spi-algo-mpc5xxx.o spi-algo-mpc5xxx-psc.o \
> 		   spi-iti5200.o spi-eval.o
>
> instead of:
> 	
> export-objs	:= spi-core.o spi-algo-mpc5xxx.o spi-algo-mpc5200psc.o \
> 		   spi-iti5200.o spi-eval.o
>
> I believe the spi-algo-mpc5200psc.o should be spi-algo-mpc5xxx-psc.o,
> correct?

Are you really serious about linuxppc_2_4_devel?  I can't believe  
linuxppc_2_4_devel has changed in months (if not over a year).

- k

^ permalink raw reply

* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
From: Mark A. Greer @ 2006-07-19 22:10 UTC (permalink / raw)
  To: Guennadi Liakhovetski; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.60.0607192144310.6432@poirot.grange>

Hi Guennadi,

On Wed, Jul 19, 2006 at 10:02:01PM +0200, Guennadi Liakhovetski wrote:
> Mark, Ben,
> 
> On Mon, 22 May 2006, Mark A. Greer wrote:
> 
> > Thanks for your time, Ben.  Sorry for taking so long to get back to you.
> 
> don't have much to comment to specific points, but quoting the entire 
> discussion below in case you'll want to further add to it.

Ben and I have talked a little bit privately and the ball is in my court
to produce a set of patches.  To that end, I have them ready so expect to
see them shortly.

> What's the status of this work? Mark, have you been further working on 
> your port?

Patches to come...

> I'd like to integrate kurobox/linkstation support with 
> sandpoint (also 8241). I think, it would be very interesting as it would 
> allow us to develop / test the "universal" kernel idea, and at the same 
> time explore the limits of board-specific support. Kurobox have a couple 
> of very nice "specialities", like a serially attached AVR acting as a 
> power-manager, thus requiring __special__ halt and reboot callbacks (so, 
> please, Ben, don't remove them).
>
> Any progress with fdt-parsing library for the wrapper / kernel and with 
> replacing hard-coded constants and tables with dt-entries?

No real progress with making a library because even though a lot of
functionality is duplicated, most of the kernel code does it on an
internal representation of the fdt and not on the actual fdt.  The
bootwrapper code needs to work directly on the fdt so I didn't bother
library-izing it.  Once the dust settles, we can library-ize the duplicate
code but for now, its all in arch/powerpc/boot/fdt.c (in my upcoming patches).

> I'd love to discuss the stuff and come to an acceptable design / APIs.

Me too. :)

Mark

^ permalink raw reply

* Re: [PATCH 0/3] powerpc: Instrument Hypervisor Calls
From: Mike Kravetz @ 2006-07-19 22:11 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20060719033618.GA3944@monkey.ibm.com>

On Tue, Jul 18, 2006 at 08:36:18PM -0700, Mike Kravetz wrote:
> > My other comment is this: wouldn't it actually turn out simpler if we
> > read the timebase (and PURR, if we really want to do that too) in the
> > assembly code that implements plpar_hcall_*?
> 
> I'll give that a try.  My assembly skills are a bit rusty, so it may
> take a little longer to produce something.

Getting the timebase and PURR in assembly is easy enough.  So, I thought
about updating the per-cpu statistics while in there.  But, I couldn't
find any other assembly code that does this.  Sure there is asm code that
updated fields in the PACA, but none that messes with paca.data_offset
(that I could find).

Should the statistic updates also be done in the assembly routines?  Or,
how about a call out to a C routine for this?

-- 
Mike

^ permalink raw reply

* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
From: Guennadi Liakhovetski @ 2006-07-19 22:29 UTC (permalink / raw)
  To: Mark A. Greer; +Cc: linuxppc-dev
In-Reply-To: <20060719221019.GA32203@mag.az.mvista.com>

On Wed, 19 Jul 2006, Mark A. Greer wrote:
> 
> Ben and I have talked a little bit privately and the ball is in my court
> to produce a set of patches.  To that end, I have them ready so expect to
> see them shortly.

Great! So, I can really relax and enjoy my holiday next week in beautiful 
Eifel:-) And as your patches arrive we'll see how best to integrate 
kurobox with them.

One question so far. Looking at your sandpoint.dts pci map:

	ranges = <80000000 80000000 70000000	/* pci mem space */
		  fc000000 fc000000 00100000	/* EUMB */
		  fe000000 fe000000 00c00000	/* pci i/o space */
		  fec00000 fec00000 00300000	/* pci cfg regs */
		  fef00000 fef00000 00100000>;	/* pci iack */

I can match hardware addresses against defines in 
include/asm-ppc/mpc10x.h, but virtual one - is the map above just an 
example and anyway-not-used, or is it a new mapping, or am I missing 
something and it has always been like that (1-to-1)? At least this comment

 * MAP B (CHRP Map)
 *   Processor: 0xfe000000 - 0xfebfffff -> PCI I/O: 0x00000000 - 0x00bfffff
 *   Processor: 0x80000000 - 0xbfffffff -> PCI MEM: 0x80000000 - 0xbfffffff
 *   PCI MEM:   0x00000000 -> Processor System Memory: 0x00000000
 *   EUMB mapped to: ioremap_base - 0x00100000 (ioremap_base - 1 MB)

seems to contradict with the above map in pci io area, as well as this 
one:

	 * Want processor accesses of 0xFDxxxxxx to be mapped
	 * to PCI memory space at 0x00000000.  Do not want

Actually, I cannot even match these 2 together?

Thanks
Guennadi
---
Guennadi Liakhovetski

^ permalink raw reply

* [PATCH 0/6] bootwrapper: arch/powerpc/boot code reorg patches
From: Mark A. Greer @ 2006-07-19 22:53 UTC (permalink / raw)
  To: linuxppc-dev

Hi,

The following emails from me in this thread are the latest set of
patches that reorg the bootwrapper code so that OF and non-OF
platforms can live together.

I punted somewhat on "The Tool" that's been talked about that takes a
kernel and attaches a flattened device tree (fdt) to it.  I thought
about it for a while but I think we need to clarify the requirements
better before it makes sense to spend a lot of cycles on it.

In the interim, dt_blob_start defined in arch/powerpc/boot/main.c allocates
8KB in a separate ELF section called '__builtin_fdt'.  You can then
'dd' a dtb generated by the dtc utility directly into that section and it
the bootwrapper will use it.  I tried playing with loader scripts so
that the section could be deleted and a new, larger one added
(and that preserves all the alignments, etc. in the zImage) but couldn't
figure out the magic so I've given up for now.

I hope that after OLS (or during?), "The Tool" will be discussed and we
can get that finished.  Unless what I've done is good enough but I doubt it...

Notes:
- These patches will collide with Milton Miller's kexec patches but they
  haven't been accepted yet so I didn't put my patches on top of them.
- Below is the script that I use to copy a dtb into the __builtin_fdt
  section of a zImage so that non-OF machines can use the zImage.
  Its basically a hack of the script that Michal Ostrowski provided
  for copying a new cmdline to an ELF section.

Mark
--

#!/bin/bash
#
# Copyright (C) 2006 Michal Ostrowski <mostrows at watson.ibm.com <https://ozlabs.org/mailman/listinfo/linuxppc-dev>>, IBM Corp.
#
# Modified to put a dtb into the "__builtin_fdt" section by Mark A. Greer
# <mgreer@mvista.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

usage(){
    echo 'set_builtin_fdt [--fdt <file>] <input_obj> [<output_obj>]'
    echo '    Sets the builtin command line embedded in an object file.'
    echo
    echo '    If <output_obj> is not specified, <input_obj> is modified'
    echo '    in place.'
    echo '    If --fdt <file> argument is present contents of embedded'
    echo '    command line will be copied from <file>, otherwise from stdin.'
    exit 1
}

fdt_file=

while case "$#" in 0) break ;; esac
do
  
        case "$1" in
        --fdt)
		case "$#" in
		    1)
			usage ;;
		    *)
			fdt_file="$2";
			shift;;
		esac;;
        *)
                set x "$@"
                shift
                break ;;
        esac
        shift
done

if [ "$#" -lt 1 ]; then
    echo "No input object specified." ; 
    usage;
fi

if [ "$#" -gt 2 ]; then
    echo "Unrecognized arguments: $@";
    usage;
fi


infile=$1
shift;

if [ ! -r "$infile" ] ; then 
    echo "Can't read '$infile'."; 
    usage;
fi

if [ "$#" -eq 0 ] ; then
    outfile=$infile;
else
    outfile=$1;
    if ! cp $infile $outfile ;  then
	echo "Can't create output: '$outfile' $?" 
	usage;
    fi
    shift;
fi

offset=$(objdump -h  $infile | \
         gawk -- '{if($2=="__builtin_fdt") {print strtonum("0x" $6);}}')
size=$(objdump -h  $infile | \
       gawk -- '{if($2=="__builtin_fdt") {print strtonum("0x" $3);}}')

if [ "x$offset" != "x" ] ; then 
    if [ "$offset" -ne 0  ] ; then
	set -e
	# Zero the destination buffer first
	exec 2>/dev/null
	dd if=$fdt_file of=$outfile bs=1 seek=$offset conv=notrunc count=$size
	exit $?
    fi
fi

^ permalink raw reply

* [PATCH 1/6] bootwrapper: arch/powerpc/boot code reorg
From: Mark A. Greer @ 2006-07-19 23:00 UTC (permalink / raw)
  To: linuxppc-dev

Abstract the operations used in the bootwrapper.  The operations
have been divided up into platform ops (platform_ops), firware ops
(fw_ops), device tree ops (dt_ops), and console ops (console_ops).

The proper operations will be hooked up at runtime to provide the
functionality that you need.

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

 main.c  |  219 +++++++++++++++++++++++++++++-----------------------------------
 ops.h   |  117 ++++++++++++++++++++++++++++++++++
 stdio.c |    4 -
 types.h |   29 ++++++++
 4 files changed, 248 insertions(+), 121 deletions(-)
--

diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index b66634c..0e49f58 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -14,17 +14,11 @@ #include "elf.h"
 #include "page.h"
 #include "string.h"
 #include "stdio.h"
-#include "prom.h"
 #include "zlib.h"
+#include "ops.h"
 
 extern void flush_cache(void *, unsigned long);
 
-
-/* Value picked to match that used by yaboot */
-#define PROG_START	0x01400000	/* only used on 64-bit systems */
-#define RAM_END		(512<<20)	/* Fixme: use OF */
-#define	ONE_MB		0x100000
-
 extern char _start[];
 extern char __bss_start[];
 extern char _end[];
@@ -33,14 +27,6 @@ extern char _vmlinux_end[];
 extern char _initrd_start[];
 extern char _initrd_end[];
 
-/* 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.
- */
-static char builtin_cmdline[512]
-	__attribute__((section("__builtin_cmdline")));
-
-
 struct addr_range {
 	unsigned long addr;
 	unsigned long size;
@@ -55,17 +41,8 @@ static unsigned long elfoffset;
 static char scratch[46912];	/* scratch space for gunzip, from zlib_inflate_workspacesize() */
 static char elfheader[256];
 
-
-typedef void (*kernel_entry_t)( unsigned long,
-                                unsigned long,
-                                void *,
-				void *);
-
-
 #undef DEBUG
 
-static unsigned long claim_base;
-
 #define HEAD_CRC	2
 #define EXTRA_FIELD	4
 #define ORIG_NAME	8
@@ -123,24 +100,6 @@ static void gunzip(void *dst, int dstlen
 	zlib_inflateEnd(&s);
 }
 
-static unsigned long try_claim(unsigned long size)
-{
-	unsigned long addr = 0;
-
-	for(; claim_base < RAM_END; claim_base += ONE_MB) {
-#ifdef DEBUG
-		printf("    trying: 0x%08lx\n\r", claim_base);
-#endif
-		addr = (unsigned long)claim(claim_base, size, 0);
-		if ((void *)addr != (void *)-1)
-			break;
-	}
-	if (addr == 0)
-		return 0;
-	claim_base = PAGE_ALIGN(claim_base + size);
-	return addr;
-}
-
 static int is_elf64(void *hdr)
 {
 	Elf64_Ehdr *elf64 = hdr;
@@ -169,16 +128,6 @@ static int is_elf64(void *hdr)
 	vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
 	vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
 
-#if defined(PROG_START)
-	/*
-	 * Maintain a "magic" minimum address. This keeps some older
-	 * firmware platforms running.
-	 */
-
-	if (claim_base < PROG_START)
-		claim_base = PROG_START;
-#endif
-
 	return 1;
 }
 
@@ -212,47 +161,11 @@ static int is_elf32(void *hdr)
 	return 1;
 }
 
-void export_cmdline(void* chosen_handle)
-{
-        int len;
-        char cmdline[2] = { 0, 0 };
-
-	if (builtin_cmdline[0] == 0)
-		return;
-
-        len = getprop(chosen_handle, "bootargs", cmdline, sizeof(cmdline));
-        if (len > 0 && cmdline[0] != 0)
-		return;
-
-	setprop(chosen_handle, "bootargs", builtin_cmdline,
-		strlen(builtin_cmdline) + 1);
-}
-
-
-void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
+static void prep_kernel(unsigned long *a1, unsigned long *a2, void *sp)
 {
 	int len;
-	kernel_entry_t kernel_entry;
-
-	memset(__bss_start, 0, _end - __bss_start);
-
-	prom = (int (*)(void *)) promptr;
-	chosen_handle = finddevice("/chosen");
-	if (chosen_handle == (void *) -1)
-		exit();
-	if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
-		exit();
-
-	printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
-
-	/*
-	 * The first available claim_base must be above the end of the
-	 * the loaded kernel wrapper file (_start to _end includes the
-	 * initrd image if it is present) and rounded up to a nice
-	 * 1 MB boundary for good measure.
-	 */
 
-	claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
+	printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start,sp);
 
 	vmlinuz.addr = (unsigned long)_vmlinux_start;
 	vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
@@ -263,43 +176,46 @@ void start(unsigned long a1, unsigned lo
 		gunzip(elfheader, sizeof(elfheader),
 				(unsigned char *)vmlinuz.addr, &len);
 	} else
-		memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader));
+		memcpy(elfheader, (const void *)vmlinuz.addr,sizeof(elfheader));
 
 	if (!is_elf64(elfheader) && !is_elf32(elfheader)) {
 		printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
 		exit();
 	}
 
-	/* We need to claim the memsize plus the file offset since gzip
+	/* We need to alloc the memsize plus the file offset since gzip
 	 * will expand the header (file offset), then the kernel, then
 	 * possible rubbish we don't care about. But the kernel bss must
 	 * be claimed (it will be zero'd by the kernel itself)
 	 */
 	printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
-	vmlinux.addr = try_claim(vmlinux.memsize);
+	vmlinux.addr = (unsigned long)malloc(vmlinux.memsize);
 	if (vmlinux.addr == 0) {
 		printf("Can't allocate memory for kernel image !\n\r");
 		exit();
 	}
 
 	/*
-	 * Now we try to claim memory for the initrd (and copy it there)
+	 * Now we try to alloc memory for the initrd (and copy it there)
 	 */
 	initrd.size = (unsigned long)(_initrd_end - _initrd_start);
 	initrd.memsize = initrd.size;
 	if ( initrd.size > 0 ) {
-		printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
-		initrd.addr = try_claim(initrd.size);
+		printf("Allocating 0x%lx bytes for initrd ...\n\r",initrd.size);
+		initrd.addr = (unsigned long)malloc((u32)initrd.size);
 		if (initrd.addr == 0) {
-			printf("Can't allocate memory for initial ramdisk !\n\r");
+			printf("Can't allocate memory for initial "
+					"ramdisk !\n\r");
 			exit();
 		}
-		a1 = initrd.addr;
-		a2 = initrd.size;
-		printf("initial ramdisk moving 0x%lx <- 0x%lx (0x%lx bytes)\n\r",
-		       initrd.addr, (unsigned long)_initrd_start, initrd.size);
-		memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
-		printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd.addr));
+		*a1 = initrd.addr;
+		*a2 = initrd.size;
+		printf("initial ramdisk moving 0x%lx <- 0x%lx "
+			"(0x%lx bytes)\n\r", initrd.addr,
+			(unsigned long)_initrd_start, initrd.size);
+		memmove((void *)initrd.addr, (void *)_initrd_start,initrd.size);
+		printf("initrd head: 0x%lx\n\r",
+				*((unsigned long *)initrd.addr));
 	}
 
 	/* Eventually gunzip the kernel */
@@ -314,8 +230,6 @@ void start(unsigned long a1, unsigned lo
 		memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
 	}
 
-	export_cmdline(chosen_handle);
-
 	/* Skip over the ELF header */
 #ifdef DEBUG
 	printf("... skipping 0x%lx bytes of ELF header\n\r",
@@ -324,23 +238,90 @@ #endif
 	vmlinux.addr += elfoffset;
 
 	flush_cache((void *)vmlinux.addr, vmlinux.size);
+}
 
-	kernel_entry = (kernel_entry_t)vmlinux.addr;
-#ifdef DEBUG
-	printf( "kernel:\n\r"
-		"        entry addr = 0x%lx\n\r"
-		"        a1         = 0x%lx,\n\r"
-		"        a2         = 0x%lx,\n\r"
-		"        prom       = 0x%lx,\n\r"
-		"        bi_recs    = 0x%lx,\n\r",
-		(unsigned long)kernel_entry, a1, a2,
-		(unsigned long)prom, NULL);
-#endif
+/* 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.
+ */
+static char builtin_cmdline[COMMAND_LINE_SIZE]
+	__attribute__((__section__("__builtin_cmdline")));
 
-	kernel_entry(a1, a2, prom, NULL);
+static void get_cmdline(char *buf, int size)
+{
+	void *devp;
+	int len = strlen(builtin_cmdline);
 
-	printf("Error: Linux kernel returned to zImage bootloader!\n\r");
+	buf[0] = '\0';
 
-	exit();
+	if (len > 0) { /* builtin_cmdline overrides dt's /chosen/bootargs */
+		len = min(len, size-1);
+		strncpy(buf, builtin_cmdline, len);
+		buf[len] = '\0';
+	}
+	else if ((devp = finddevice("/chosen")))
+		getprop(devp, "bootargs", buf, size);
+}
+
+static void set_cmdline(char *buf)
+{
+	void *devp;
+
+	if ((devp = finddevice("/chosen")))
+		setprop(devp, "bootargs", buf, strlen(buf) + 1);
 }
 
+/* Section where fdt can be tacked on after zImage is built */
+#define	EMPTY_SECTION_STR	"no fdt"
+
+char dt_blob_start[8*1024]
+	__attribute__((__section__("__builtin_fdt"),__aligned__(8)))
+		= EMPTY_SECTION_STR;
+
+struct ops *ops;
+
+void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
+{
+	char cmdline[COMMAND_LINE_SIZE];
+
+	memset(__bss_start, 0, _end - __bss_start);
+
+	ops = platform_init(promptr);
+
+	/* Override the dt_ops if there was an fdt attached to the zImage */
+	if (strcmp(dt_blob_start, EMPTY_SECTION_STR))
+		ops->dt_ops = fdt_init(dt_blob_start);
+
+	if (!ops || !ops->platform_ops || !ops->fw_ops || !ops->dt_ops
+			|| !ops->console_ops)
+		exit();
+
+	if (ops->console_ops->open && (ops->console_ops->open() < 0))
+		exit();
+	if (ops->platform_ops->fixups)
+		ops->platform_ops->fixups();
+
+	prep_kernel(&a1, &a2, sp);
+
+	/* If cmdline came from zimage wrapper or if we can edit the one
+	 * in the dt, print it out and edit it, if possible.
+	 */
+	if ((strlen(builtin_cmdline) > 0) || ops->console_ops->edit_cmdline) {
+		get_cmdline(cmdline, COMMAND_LINE_SIZE);
+		printf("\n\rLinux/PowerPC load: %s", cmdline);
+		if (ops->console_ops->edit_cmdline)
+			ops->console_ops->edit_cmdline(cmdline,
+					COMMAND_LINE_SIZE);
+		printf("\n\r");
+		set_cmdline(cmdline);
+	}
+
+	if (ops->console_ops->close)
+		ops->console_ops->close();
+
+	ops->dt_ops->call_kernel((void *)vmlinux.addr, a1, a2, promptr, sp);
+
+	/* console closed so printf below may not work */
+	printf("Error: Linux kernel returned to zImage bootloader!\n\r");
+	exit();
+}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
new file mode 100644
index 0000000..94d97b0
--- /dev/null
+++ b/arch/powerpc/boot/ops.h
@@ -0,0 +1,117 @@
+/*
+ * Global definition of all the bootwrapper operations.
+ *
+ * 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.
+ */
+#ifndef _PPC_BOOT_OPS_H_
+#define _PPC_BOOT_OPS_H_
+
+#include "types.h"
+
+/* Platform specific operations */
+struct platform_ops {
+	void	(*fixups)(void);
+	void	(*exit)(void);
+};
+
+/* Firmware specific operations */
+struct fw_ops {
+	void *	(*malloc)(u32 size);
+	void	(*free)(void *ptr, u32 size);
+	void	(*exit)(void);
+};
+
+/* Device Tree operations */
+struct dt_ops {
+	void *	(*finddevice)(const char *name);
+	int	(*getprop)(void *node, const char *name, void *buf, int buflen);
+	int	(*setprop)(void *node, const char *name, void *buf, int buflen);
+	u64	(*translate_addr)(char *path, u32 *in_addr, u32 addr_len);
+	void	(*call_kernel)(void *entry_addr, unsigned long a1,
+			unsigned long a2, void *promptr, void *sp);
+};
+
+/* Serial console operations */
+struct serial_console_data {
+	int		(*open)(void);
+	void		(*putc)(unsigned char c);
+	unsigned char	(*getc)(void);
+	u8		(*tstc)(void);
+	void		(*close)(void);
+	unsigned char	*base;
+	u8		reg_shift;
+};
+
+/* Console operations */
+struct console_ops {
+	int	(*open)(void);
+	void	(*write)(char *buf, int len);
+	void	(*edit_cmdline)(char *buf, int len);
+	void	(*close)(void);
+	void	*data;
+};
+
+struct ops {
+	struct platform_ops	*platform_ops;
+	struct fw_ops		*fw_ops;
+	struct dt_ops		*dt_ops;
+	struct console_ops	*console_ops;
+};
+
+extern struct ops *ops;
+
+extern struct ops *platform_init(void *promptr);
+extern struct fw_ops *dink_init(void);
+extern struct dt_ops *fdt_init(void *dt_blob);
+extern struct console_ops *ns16550_init(void);
+
+extern int serial_open(void);
+extern void serial_write(char *buf, int len);
+extern void serial_edit_cmdline(char *buf, int len);
+extern void serial_close(void);
+
+static inline void *finddevice(const char *name)
+{
+	return (ops->dt_ops->finddevice) ? ops->dt_ops->finddevice(name) : NULL;
+}
+
+static inline int getprop(void *devp, const char *name, void *buf, int buflen)
+{
+	return (ops->dt_ops->getprop) ?
+			ops->dt_ops->getprop(devp, name, buf, buflen) : -1;
+}
+
+static inline int setprop(void *devp, const char *name, void *buf, int buflen)
+{
+	return (ops->dt_ops->setprop) ?
+			ops->dt_ops->setprop(devp, name, buf, buflen) : -1;
+}
+
+static inline void *malloc(u32 size)
+{
+	return (ops->fw_ops->malloc) ? ops->fw_ops->malloc(size) : NULL;
+}
+
+static inline void free(void *ptr, u32 size)
+{
+	if (ops->fw_ops->free)
+		ops->fw_ops->free(ptr, size);
+}
+
+static inline void exit(void)
+{
+	if (ops) {
+		if (ops->platform_ops && ops->platform_ops->exit)
+			ops->platform_ops->exit();
+		if (ops->fw_ops && ops->fw_ops->exit)
+			ops->fw_ops->exit();
+	}
+	for(;;);
+}
+
+#endif /* _PPC_BOOT_OPS_H_ */
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index b5aa522..7ccc504 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -10,7 +10,7 @@ #include <stdarg.h>
 #include <stddef.h>
 #include "string.h"
 #include "stdio.h"
-#include "prom.h"
+#include "ops.h"
 
 size_t strnlen(const char * s, size_t count)
 {
@@ -320,6 +320,6 @@ printf(const char *fmt, ...)
 	va_start(args, fmt);
 	n = vsprintf(sprint_buf, fmt, args);
 	va_end(args);
-	write(stdout, sprint_buf, n);
+	ops->console_ops->write(sprint_buf, n);
 	return n;
 }
diff --git a/arch/powerpc/boot/types.h b/arch/powerpc/boot/types.h
new file mode 100644
index 0000000..2a2fa2b
--- /dev/null
+++ b/arch/powerpc/boot/types.h
@@ -0,0 +1,29 @@
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+#define	COMMAND_LINE_SIZE	512
+#define	MAX_PATH_LEN		256
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+typedef unsigned char		u8;
+typedef unsigned short		u16;
+typedef unsigned int		u32;
+#ifdef __powerpc64__
+typedef unsigned long		u64;
+#else
+typedef unsigned long long	u64;
+#endif
+
+#define min(x,y) ({ \
+	typeof(x) _x = (x);	\
+	typeof(y) _y = (y);	\
+	(void) (&_x == &_y);	\
+	_x < _y ? _x : _y; })
+
+#define max(x,y) ({ \
+	typeof(x) _x = (x);	\
+	typeof(y) _y = (y);	\
+	(void) (&_x == &_y);	\
+	_x > _y ? _x : _y; })
+
+#endif /* _TYPES_H_ */

^ permalink raw reply related

* [PATCH 2/6] bootwrapper: Add in OF operations (and rename to of.c)
From: Mark A. Greer @ 2006-07-19 23:03 UTC (permalink / raw)
  To: linuxppc-dev

This patch adds the operations necessary for the bootwrapper to run on
an OF platform.  This code used to be in prom.[ch] but was moved to of.c
because its a more accurate name (IMHO).

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

 arch/powerpc/boot/prom.c     |  165 -----------------------
 arch/powerpc/boot/prom.h     |   41 -----
 b/arch/powerpc/boot/Makefile |    5 
 b/arch/powerpc/boot/of.c     |  301 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 305 insertions(+), 207 deletions(-)
--

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index afc776f..c2bb541 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -36,7 +36,10 @@ zliblinuxheader := zlib.h zconf.h zutil.
 $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
 #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
 
-src-boot := crt0.S string.S prom.c stdio.c main.c div64.S
+src-boot := crt0.S string.S stdio.c main.c div64.S
+ifeq ($(CONFIG_PPC_MULTIPLATFORM),y)
+src-boot += of.c
+endif
 src-boot += $(zlib)
 src-boot := $(addprefix $(obj)/, $(src-boot))
 obj-boot := $(addsuffix .o, $(basename $(src-boot)))
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
new file mode 100644
index 0000000..313f125
--- /dev/null
+++ b/arch/powerpc/boot/of.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+typedef void *ihandle;
+typedef void *phandle;
+
+extern char _end[];
+
+/* Value picked to match that used by yaboot */
+#define PROG_START	0x01400000	/* only used on 64-bit systems */
+#define RAM_END		(512<<20)	/* Fixme: use OF */
+#define	ONE_MB		0x100000
+
+int (*prom) (void *);
+
+
+static unsigned long claim_base;
+
+static int call_prom(const char *service, int nargs, int nret, ...)
+{
+	int i;
+	struct prom_args {
+		const char *service;
+		int nargs;
+		int nret;
+		unsigned int args[12];
+	} args;
+	va_list list;
+
+	args.service = service;
+	args.nargs = nargs;
+	args.nret = nret;
+
+	va_start(list, nret);
+	for (i = 0; i < nargs; i++)
+		args.args[i] = va_arg(list, unsigned int);
+	va_end(list);
+
+	for (i = 0; i < nret; i++)
+		args.args[nargs+i] = 0;
+
+	if (prom(&args) < 0)
+		return -1;
+
+	return (nret > 0)? args.args[nargs]: 0;
+}
+
+static int call_prom_ret(const char *service, int nargs, int nret,
+		  unsigned int *rets, ...)
+{
+	int i;
+	struct prom_args {
+		const char *service;
+		int nargs;
+		int nret;
+		unsigned int args[12];
+	} args;
+	va_list list;
+
+	args.service = service;
+	args.nargs = nargs;
+	args.nret = nret;
+
+	va_start(list, rets);
+	for (i = 0; i < nargs; i++)
+		args.args[i] = va_arg(list, unsigned int);
+	va_end(list);
+
+	for (i = 0; i < nret; i++)
+		args.args[nargs+i] = 0;
+
+	if (prom(&args) < 0)
+		return -1;
+
+	if (rets != (void *) 0)
+		for (i = 1; i < nret; ++i)
+			rets[i-1] = args.args[nargs+i];
+
+	return (nret > 0)? args.args[nargs]: 0;
+}
+
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
+ */
+static int need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
+
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
+{
+	for (; *s2; ++s2)
+		if (*s1++ != *s2)
+			return 0;
+	return 1;
+}
+
+static int check_of_version(void)
+{
+	phandle oprom, chosen;
+	char version[64];
+
+	oprom = finddevice("/openprom");
+	if (oprom == (phandle) -1)
+		return 0;
+	if (getprop(oprom, "model", version, sizeof(version)) <= 0)
+		return 0;
+	version[sizeof(version)-1] = 0;
+	printf("OF version = '%s'\r\n", version);
+	if (!string_match(version, "Open Firmware, 1.")
+	    && !string_match(version, "FirmWorks,3."))
+		return 0;
+	chosen = finddevice("/chosen");
+	if (chosen == (phandle) -1) {
+		chosen = finddevice("/chosen@0");
+		if (chosen == (phandle) -1) {
+			printf("no chosen\n");
+			return 0;
+		}
+	}
+	if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+		printf("no mmu\n");
+		return 0;
+	}
+	memory = (ihandle) call_prom("open", 1, 1, "/memory");
+	if (memory == (ihandle) -1) {
+		memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
+		if (memory == (ihandle) -1) {
+			printf("no memory node\n");
+			return 0;
+		}
+	}
+	printf("old OF detected\r\n");
+	return 1;
+}
+
+static void *claim(unsigned long virt, unsigned long size, unsigned long align)
+{
+	int ret;
+	unsigned int result;
+
+	if (need_map < 0)
+		need_map = check_of_version();
+	if (align || !need_map)
+		return (void *) call_prom("claim", 3, 1, virt, size, align);
+
+	ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
+			    align, size, virt);
+	if (ret != 0 || result == -1)
+		return (void *) -1;
+	ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+			    align, size, virt);
+	/* 0x12 == coherent + read/write */
+	ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
+			0x12, size, virt, virt);
+	return (void *) virt;
+}
+
+static void *of_try_claim(u32 size)
+{
+	unsigned long addr = 0;
+	static u8 first_time = 1;
+
+	if (first_time) {
+#if defined(PROG_START)
+		/*
+		 * Maintain a "magic" minimum address. This keeps some older
+		 * firmware platforms running.
+		 */
+
+		if (claim_base < PROG_START)
+			claim_base = PROG_START;
+#endif
+		claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
+		first_time = 0;
+	}
+
+	for(; claim_base < RAM_END; claim_base += ONE_MB) {
+#ifdef DEBUG
+		printf("    trying: 0x%08lx\n\r", claim_base);
+#endif
+		addr = (unsigned long)claim(claim_base, size, 0);
+		if ((void *)addr != (void *)-1)
+			break;
+	}
+	if (addr == 0)
+		return NULL;
+	claim_base = PAGE_ALIGN(claim_base + size);
+	return (void *)addr;
+}
+
+static void of_fw_exit(void)
+{
+	call_prom("exit", 0, 0);
+}
+
+/*
+ * OF device tree routines
+ */
+static void *of_finddevice(const char *name)
+{
+	return (phandle) call_prom("finddevice", 1, 1, name);
+}
+
+static int of_getprop(void *phandle, const char *name,
+			  void *buf, int buflen)
+{
+	return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
+}
+
+static int of_setprop(void *phandle, const char *name,
+			  void *buf, int buflen)
+{
+	return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
+}
+
+static void of_call_kernel(void *entry_addr, unsigned long a1,
+		unsigned long a2, void *promptr, void *sp)
+{
+	void (*kernel_entry)(unsigned long a1, unsigned long a2, void *promptr,
+			void *sp);
+
+	kernel_entry = entry_addr;
+	kernel_entry(a1, a2, promptr, sp);
+}
+
+/*
+ * OF console routines
+ */
+static void *of_stdout_handle;
+
+static int of_console_open(void)
+{
+	void *devp;
+
+	if (((devp = finddevice("/chosen")) != NULL)
+			&& (getprop(devp, "stdout", &of_stdout_handle,
+				sizeof(of_stdout_handle))
+				== sizeof(of_stdout_handle)))
+		return 0;
+
+	return -1;
+}
+
+static void of_console_write(char *buf, int len)
+{
+	call_prom("write", 3, 1, of_stdout_handle, buf, len);
+}
+
+/* Init code that hooks up all of the routines */
+static struct platform_ops of_platform_ops;
+static struct fw_ops of_fw_ops;
+static struct dt_ops of_dt_ops;
+static struct console_ops of_console_ops;
+static struct ops of_ops;
+
+struct ops *platform_init(void *promptr)
+{
+	of_platform_ops.fixups = NULL;
+	of_platform_ops.exit = NULL;
+
+	of_fw_ops.malloc = of_try_claim;
+	of_fw_ops.free = NULL;
+	of_fw_ops.exit = of_fw_exit;
+
+	of_dt_ops.finddevice = of_finddevice;
+	of_dt_ops.getprop = of_getprop;
+	of_dt_ops.setprop = of_setprop;
+	of_dt_ops.call_kernel = of_call_kernel;
+
+	of_console_ops.open = of_console_open;
+	of_console_ops.write = of_console_write;
+	of_console_ops.edit_cmdline = NULL;
+	of_console_ops.close = NULL;
+	of_console_ops.data = NULL;
+
+	of_ops.platform_ops = &of_platform_ops;
+	of_ops.fw_ops = &of_fw_ops;
+	of_ops.dt_ops = &of_dt_ops;
+	of_ops.console_ops = &of_console_ops;
+
+	prom = (int (*)(void *))promptr;
+
+	return &of_ops;
+}
diff --git a/arch/powerpc/boot/prom.c b/arch/powerpc/boot/prom.c
deleted file mode 100644
index fa00577..0000000
--- a/arch/powerpc/boot/prom.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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 <stdarg.h>
-#include <stddef.h>
-#include "string.h"
-#include "stdio.h"
-#include "prom.h"
-
-int (*prom)(void *);
-phandle chosen_handle;
-ihandle stdout;
-
-int call_prom(const char *service, int nargs, int nret, ...)
-{
-	int i;
-	struct prom_args {
-		const char *service;
-		int nargs;
-		int nret;
-		unsigned int args[12];
-	} args;
-	va_list list;
-
-	args.service = service;
-	args.nargs = nargs;
-	args.nret = nret;
-
-	va_start(list, nret);
-	for (i = 0; i < nargs; i++)
-		args.args[i] = va_arg(list, unsigned int);
-	va_end(list);
-
-	for (i = 0; i < nret; i++)
-		args.args[nargs+i] = 0;
-
-	if (prom(&args) < 0)
-		return -1;
-
-	return (nret > 0)? args.args[nargs]: 0;
-}
-
-int call_prom_ret(const char *service, int nargs, int nret,
-		  unsigned int *rets, ...)
-{
-	int i;
-	struct prom_args {
-		const char *service;
-		int nargs;
-		int nret;
-		unsigned int args[12];
-	} args;
-	va_list list;
-
-	args.service = service;
-	args.nargs = nargs;
-	args.nret = nret;
-
-	va_start(list, rets);
-	for (i = 0; i < nargs; i++)
-		args.args[i] = va_arg(list, unsigned int);
-	va_end(list);
-
-	for (i = 0; i < nret; i++)
-		args.args[nargs+i] = 0;
-
-	if (prom(&args) < 0)
-		return -1;
-
-	if (rets != (void *) 0)
-		for (i = 1; i < nret; ++i)
-			rets[i-1] = args.args[nargs+i];
-
-	return (nret > 0)? args.args[nargs]: 0;
-}
-
-int write(void *handle, void *ptr, int nb)
-{
-	return call_prom("write", 3, 1, handle, ptr, nb);
-}
-
-/*
- * Older OF's require that when claiming a specific range of addresses,
- * we claim the physical space in the /memory node and the virtual
- * space in the chosen mmu node, and then do a map operation to
- * map virtual to physical.
- */
-static int need_map = -1;
-static ihandle chosen_mmu;
-static phandle memory;
-
-/* returns true if s2 is a prefix of s1 */
-static int string_match(const char *s1, const char *s2)
-{
-	for (; *s2; ++s2)
-		if (*s1++ != *s2)
-			return 0;
-	return 1;
-}
-
-static int check_of_version(void)
-{
-	phandle oprom, chosen;
-	char version[64];
-
-	oprom = finddevice("/openprom");
-	if (oprom == (phandle) -1)
-		return 0;
-	if (getprop(oprom, "model", version, sizeof(version)) <= 0)
-		return 0;
-	version[sizeof(version)-1] = 0;
-	printf("OF version = '%s'\r\n", version);
-	if (!string_match(version, "Open Firmware, 1.")
-	    && !string_match(version, "FirmWorks,3."))
-		return 0;
-	chosen = finddevice("/chosen");
-	if (chosen == (phandle) -1) {
-		chosen = finddevice("/chosen@0");
-		if (chosen == (phandle) -1) {
-			printf("no chosen\n");
-			return 0;
-		}
-	}
-	if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
-		printf("no mmu\n");
-		return 0;
-	}
-	memory = (ihandle) call_prom("open", 1, 1, "/memory");
-	if (memory == (ihandle) -1) {
-		memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
-		if (memory == (ihandle) -1) {
-			printf("no memory node\n");
-			return 0;
-		}
-	}
-	printf("old OF detected\r\n");
-	return 1;
-}
-
-void *claim(unsigned long virt, unsigned long size, unsigned long align)
-{
-	int ret;
-	unsigned int result;
-
-	if (need_map < 0)
-		need_map = check_of_version();
-	if (align || !need_map)
-		return (void *) call_prom("claim", 3, 1, virt, size, align);
-	
-	ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
-			    align, size, virt);
-	if (ret != 0 || result == -1)
-		return (void *) -1;
-	ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
-			    align, size, virt);
-	/* 0x12 == coherent + read/write */
-	ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
-			0x12, size, virt, virt);
-	return (void *) virt;
-}
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h
deleted file mode 100644
index a57b184..0000000
--- a/arch/powerpc/boot/prom.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef _PPC_BOOT_PROM_H_
-#define _PPC_BOOT_PROM_H_
-
-typedef void *phandle;
-typedef void *ihandle;
-
-extern int (*prom) (void *);
-extern phandle chosen_handle;
-extern ihandle stdout;
-
-int	call_prom(const char *service, int nargs, int nret, ...);
-int	call_prom_ret(const char *service, int nargs, int nret,
-		      unsigned int *rets, ...);
-
-extern int write(void *handle, void *ptr, int nb);
-extern void *claim(unsigned long virt, unsigned long size, unsigned long aln);
-
-static inline void exit(void)
-{
-	call_prom("exit", 0, 0);
-}
-
-static inline phandle finddevice(const char *name)
-{
-	return (phandle) call_prom("finddevice", 1, 1, name);
-}
-
-static inline int getprop(void *phandle, const char *name,
-			  void *buf, int buflen)
-{
-	return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
-}
-
-
-static inline int setprop(void *phandle, const char *name,
-			  void *buf, int buflen)
-{
-	return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
-}
-
-#endif				/* _PPC_BOOT_PROM_H_ */

^ permalink raw reply related

* [PATCH 3/6] bootwrapper: Add device tree ops for flattened device tree
From: Mark A. Greer @ 2006-07-19 23:05 UTC (permalink / raw)
  To: linuxppc-dev

This patch adds the device tree operations (dt_ops) for a flattened
device tree (fdt).

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

 Makefile |    2 
 fdt.c    |  525 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 526 insertions(+), 1 deletion(-)
--

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index c2bb541..3e767e5 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -36,7 +36,7 @@ zliblinuxheader := zlib.h zconf.h zutil.
 $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
 #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
 
-src-boot := crt0.S string.S stdio.c main.c div64.S
+src-boot := crt0.S string.S stdio.c main.c div64.S fdt.c
 ifeq ($(CONFIG_PPC_MULTIPLATFORM),y)
 src-boot += of.c
 endif
diff --git a/arch/powerpc/boot/fdt.c b/arch/powerpc/boot/fdt.c
new file mode 100644
index 0000000..ad7e7d5
--- /dev/null
+++ b/arch/powerpc/boot/fdt.c
@@ -0,0 +1,525 @@
+/*
+ * Simple dtb (binary flattened device tree) search/manipulation routines.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ * 	- The code for strrchr() was copied from lib/string.c and is
+ * 	copyrighted by Linus Torvalds.
+ * 	- The smarts for fdt_finddevice() were copied with the author's
+ * 	permission from u-boot:common/ft_build.c which was written by
+ * 	Pantelis Antoniou <pantelis@embeddedalley.com>.
+ * 	- Many of the routines related to fdt_translate_addr() came
+ * 	from arch/powerpc/kernel/prom_parse.c which has no author or
+ * 	copyright notice.
+ *
+ * 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.
+ */
+
+/* Supports dtb version 0x10 only */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "page.h"
+#include "string.h"
+#include "stdio.h"
+#include "ops.h"
+
+/* Definitions used by the flattened device tree */
+#define OF_DT_HEADER		0xd00dfeed	/* marker */
+#define OF_DT_BEGIN_NODE	0x1		/* Start of node, full name */
+#define OF_DT_END_NODE		0x2		/* End node */
+#define OF_DT_PROP		0x3		/* Property: name off, size,
+						 * content */
+#define OF_DT_NOP		0x4		/* nop */
+#define OF_DT_END		0x9
+
+#define OF_DT_VERSION		0x10
+
+struct boot_param_header
+{
+	u32	magic;			/* magic word OF_DT_HEADER */
+	u32	totalsize;		/* total size of DT block */
+	u32	off_dt_struct;		/* offset to structure */
+	u32	off_dt_strings;		/* offset to strings */
+	u32	off_mem_rsvmap;		/* offset to memory reserve map */
+	u32	version;		/* format version */
+	u32	last_comp_version;	/* last compatible version */
+	/* version 2 fields below */
+	u32	boot_cpuid_phys;	/* Physical CPU id we're booting on */
+	/* version 3 fields below */
+	u32	dt_strings_size;	/* size of the DT strings block */
+};
+
+static void *dtb_start;
+static void *dtb_end;
+
+#define MAX_ADDR_CELLS	4
+#define BAD_ADDR	((u64)-1)
+
+struct fdt_bus {
+	u64	(*map)(u32 *addr, u32 *range, int na, int ns, int pna);
+	int	(*translate)(u32 *addr, u64 offset, int na);
+};
+
+static inline struct boot_param_header *
+fdt_get_bph(void *dt_blob)
+{
+	return (struct boot_param_header *)dt_blob;
+}
+
+static char *
+fdt_strrchr(const char *s, int c)
+{
+	const char *p = s + strlen(s);
+
+	do {
+		if (*p == (char)c)
+			return (char *)p;
+	} while (--p >= s);
+	return NULL;
+}
+
+/* 'path' is modified */
+static void
+fdt_parentize(char *path, u8 leave_slash)
+{
+	char *s = &path[strlen(path) - 1];
+
+	if (*s == '/')
+		*s = '\0';
+	s = fdt_strrchr(path, '/');
+	if (s != NULL) {
+		if (leave_slash)
+			s[1] = '\0';
+		else if (s[0] == '/')
+			s[0] = '\0';
+	}
+}
+
+static inline u32 *
+fdt_next(u32 *dp, u32 **tagpp, char **namepp, char **datapp, u32 **sizepp)
+{
+	static char *str_region;
+
+	*namepp = NULL;
+	*datapp = NULL;
+	*sizepp = NULL;
+
+	if (dp == NULL) { /* first time */
+		struct boot_param_header *bph = fdt_get_bph(dtb_start);
+
+		if (bph->magic != OF_DT_HEADER) {
+			*tagpp = NULL;
+			return NULL;
+		}
+		dp = (u32 *)((u32)dtb_start + bph->off_dt_struct);
+		str_region = (char *)((u32)dtb_start + bph->off_dt_strings);
+	}
+
+	*tagpp = dp;
+
+	switch (*dp++) { /* Tag */
+	case OF_DT_PROP:
+		*sizepp = dp++;
+		*namepp = str_region + *dp++;
+		*datapp = (char *)dp;
+		dp = (u32 *)_ALIGN_UP((unsigned long)dp + **sizepp, 4);
+		break;
+	case OF_DT_BEGIN_NODE:
+		*namepp = (char *)dp;
+		dp = (u32 *)_ALIGN_UP((u32)dp + strlen((char *)dp) + 1, 4);
+		break;
+	case OF_DT_END_NODE:
+	case OF_DT_NOP:
+		break;
+	case OF_DT_END:
+	default:
+		dp = NULL;
+		break;
+	}
+
+	return dp;
+}
+
+static void *
+fdt_finddevice(const char *name)
+{
+	u32 *dp, *tagp, *sizep;
+	char *namep, *datap;
+	static char path[MAX_PATH_LEN];
+
+	path[0] = '\0';
+	dp = NULL;
+
+	while ((dp = fdt_next(dp, &tagp, &namep, &datap, &sizep)) != NULL)
+		switch (*tagp) {
+		case OF_DT_BEGIN_NODE:
+			strcat(path, namep);
+			if (!strcmp(path, name))
+				return tagp;
+			strcat(path, "/");
+			break;
+		case OF_DT_END_NODE:
+			fdt_parentize(path, 1);
+			break;
+		}
+	return NULL;
+}
+
+static int
+fdt_getprop(void *node, const char *name, void *buf, int buflen)
+{
+	u32 *dp, *tagp, *sizep, size;
+	char *namep, *datap;
+	int level;
+
+	level = 0;
+	dp = node;
+
+	while ((dp = fdt_next(dp, &tagp, &namep, &datap, &sizep)) != NULL)
+		switch (*tagp) {
+		case OF_DT_PROP:
+			if ((level == 1) && !strcmp(namep, name)) {
+				size = min(*sizep, (u32)buflen);
+				memcpy(buf, datap, size);
+				return size;
+			}
+			break;
+		case OF_DT_BEGIN_NODE:
+			level++;
+			break;
+		case OF_DT_END_NODE:
+			if (--level <= 0)
+				return -1;
+			break;
+		}
+	return -1;
+}
+
+static void
+fdt_modify_prop(u32 *dp, char *datap, u32 *old_prop_sizep, char *buf,
+		int buflen)
+{
+	u32 old_prop_data_len, new_prop_data_len;
+
+	old_prop_data_len = _ALIGN_UP(*old_prop_sizep, 4);
+	new_prop_data_len = _ALIGN_UP(buflen, 4);
+
+	/* Check if new prop data fits in old prop data area */
+	if (new_prop_data_len == old_prop_data_len) {
+		memcpy(datap, buf, buflen);
+		*old_prop_sizep = buflen;
+	}
+	else { /* Need to alloc new area to put larger or smaller fdt */
+		struct boot_param_header *old_bph, *new_bph;
+		u32 *old_tailp, *new_tailp, *new_datap;
+		u32 old_total_size, new_total_size, head_len, tail_len, diff;
+		void *new_dtb_start, *new_dtb_end;
+
+		old_bph = fdt_get_bph(dtb_start),
+		old_total_size = old_bph->totalsize;
+		head_len = (u32)datap - (u32)dtb_start;
+		tail_len = old_total_size - (head_len + old_prop_data_len);
+		old_tailp = (u32 *)((u32)dtb_end - tail_len);
+		new_total_size = head_len + new_prop_data_len + tail_len;
+
+		if (!(new_dtb_start = malloc(new_total_size))) {
+			printf("Can't alloc space for new fdt\n\r");
+			exit();
+		}
+
+		new_dtb_end = (void *)((u32)new_dtb_start + new_total_size);
+		new_datap = (u32 *)((u32)new_dtb_start + head_len);
+		new_tailp = (u32 *)((u32)new_dtb_end - tail_len);
+
+		memcpy(new_dtb_start, dtb_start, head_len);
+		memcpy(new_datap, buf, buflen);
+		memcpy(new_tailp, old_tailp, tail_len);
+		*(new_datap - 2) = buflen;
+
+		new_bph = fdt_get_bph(new_dtb_start),
+		new_bph->totalsize = new_total_size;
+
+		diff = new_prop_data_len - old_prop_data_len;
+
+		/* Adjust offsets of other sections, if necessary */
+		if (new_bph->off_dt_strings > new_bph->off_dt_struct)
+			new_bph->off_dt_strings += diff;
+
+		if (new_bph->off_mem_rsvmap > new_bph->off_dt_struct)
+			new_bph->off_mem_rsvmap += diff;
+
+		free(dtb_start, old_total_size);
+
+		dtb_start = new_dtb_start;
+		dtb_end = new_dtb_end;
+	}
+}
+
+/* Only modifies existing properties */
+static int
+fdt_setprop(void *node, const char *name, void *buf, int buflen)
+{
+	u32 *dp, *tagp, *sizep;
+	char *namep, *datap;
+	int level;
+
+	level = 0;
+	dp = node;
+
+	while ((dp = fdt_next(dp, &tagp, &namep, &datap, &sizep)) != NULL)
+		switch (*tagp) {
+		case OF_DT_PROP:
+			if ((level == 1) && !strcmp(namep, name)) {
+				fdt_modify_prop(tagp, datap, sizep, buf,buflen);
+				return *sizep;
+			}
+			break;
+		case OF_DT_BEGIN_NODE:
+			level++;
+			break;
+		case OF_DT_END_NODE:
+			if (--level <= 0)
+				return -1;
+			break;
+		}
+	return -1;
+}
+
+static u32
+fdt_find_cells(char *path, char *prop)
+{
+	void *devp;
+	u32 num;
+	char p[MAX_PATH_LEN];
+
+	strcpy(p, path);
+	do {
+		if ((devp = finddevice(p))
+				&& (getprop(devp, prop, &num, sizeof(num)) > 0))
+			return num;
+		fdt_parentize(p, 0);
+	} while (strlen(p) > 0);
+	return 1; /* default of 1 */
+}
+
+static u64
+fdt_read_addr(u32 *cell, int size)
+{
+	u64 r = 0;
+	while (size--)
+		r = (r << 32) | *(cell++);
+	return r;
+}
+
+static u64
+fdt_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna)
+{
+	u64 cp, s, da;
+
+	cp = fdt_read_addr(range, na);
+	s  = fdt_read_addr(range + na + pna, ns);
+	da = fdt_read_addr(addr, na);
+
+	if (da < cp || da >= (cp + s))
+		return BAD_ADDR;
+	return da - cp;
+}
+
+static int
+fdt_bus_default_translate(u32 *addr, u64 offset, int na)
+{
+	u64 a = fdt_read_addr(addr, na);
+	memset(addr, 0, na * 4);
+	a += offset;
+	if (na > 1)
+		addr[na - 2] = a >> 32;
+	addr[na - 1] = a & 0xffffffffu;
+
+	return 0;
+}
+
+static u64
+fdt_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna)
+{
+	u64 cp, s, da;
+
+	/* Check address type match */
+	if ((addr[0] ^ range[0]) & 0x03000000)
+		return BAD_ADDR;
+
+	/* Read address values, skipping high cell */
+	cp = fdt_read_addr(range + 1, na - 1);
+	s  = fdt_read_addr(range + na + pna, ns);
+	da = fdt_read_addr(addr + 1, na - 1);
+
+	if (da < cp || da >= (cp + s))
+		return BAD_ADDR;
+	return da - cp;
+}
+
+static int
+fdt_bus_pci_translate(u32 *addr, u64 offset, int na)
+{
+	return fdt_bus_default_translate(addr + 1, offset, na - 1);
+}
+
+static u64
+fdt_bus_isa_map(u32 *addr, u32 *range, int na, int ns, int pna)
+{
+	u64 cp, s, da;
+
+	/* Check address type match */
+	if ((addr[0] ^ range[0]) & 0x00000001)
+		return BAD_ADDR;
+
+	/* Read address values, skipping high cell */
+	cp = fdt_read_addr(range + 1, na - 1);
+	s  = fdt_read_addr(range + na + pna, ns);
+	da = fdt_read_addr(addr + 1, na - 1);
+
+	if (da < cp || da >= (cp + s))
+		return BAD_ADDR;
+	return da - cp;
+}
+
+static int
+fdt_bus_isa_translate(u32 *addr, u64 offset, int na)
+{
+	return fdt_bus_default_translate(addr + 1, offset, na - 1);
+}
+
+static void
+fdt_match_bus(char *path, struct fdt_bus *bus)
+{
+	void *devp;
+	char dtype[128]; /* XXXX */
+
+	if ((devp = finddevice(path)) && (getprop(devp, "device_type", dtype,
+					sizeof(dtype)) > 0)) {
+		if (!strcmp(dtype, "isa")) {
+			bus->map = fdt_bus_isa_map;
+			bus->translate = fdt_bus_isa_translate;
+		} else if (!strcmp(dtype, "pci")) {
+			bus->map = fdt_bus_pci_map;
+			bus->translate = fdt_bus_pci_translate;
+		} else {
+			bus->map = fdt_bus_default_map;
+			bus->translate = fdt_bus_default_translate;
+		}
+	}
+}
+
+static int
+fdt_translate_one(char *path, struct fdt_bus *bus, struct fdt_bus *pbus,
+		u32 *addr, u32 na, u32 ns, u32 pna)
+{
+	void *devp;
+	u32 ranges[10 * (na + pna + ns)]; /* XXXX */
+	u32 *rp;
+	unsigned int rlen;
+	int rone;
+	u64 offset = BAD_ADDR;
+
+	if (!(devp = finddevice(path))
+			|| ((rlen = getprop(devp, "ranges", ranges,
+						sizeof(ranges))) < 0)
+			|| (rlen == 0)) {
+		offset = fdt_read_addr(addr, na);
+		memset(addr, 0, pna * 4);
+		goto finish;
+	}
+
+	rlen /= 4;
+	rone = na + pna + ns;
+	rp = ranges;
+	for (; rlen >= rone; rlen -= rone, rp += rone) {
+		offset = bus->map(addr, rp, na, ns, pna);
+		if (offset != BAD_ADDR)
+			break;
+	}
+	if (offset == BAD_ADDR)
+		return 1;
+	memcpy(addr, rp + na, 4 * pna);
+
+finish:
+	/* Translate it into parent bus space */
+	return pbus->translate(addr, offset, pna);
+}
+
+/* 'addr' is modified */
+static u64
+fdt_translate_addr(char *p, u32 *in_addr, u32 addr_len)
+{
+	struct fdt_bus	bus, pbus;
+	int na, ns, pna, pns;
+	u32 addr[MAX_ADDR_CELLS];
+	char path[MAX_PATH_LEN], ppath[MAX_PATH_LEN];
+
+	strcpy(ppath, p);
+	fdt_parentize(ppath, 0);
+	fdt_match_bus(ppath, &bus);
+	na = fdt_find_cells(ppath, "#address-cells");
+	ns = fdt_find_cells(ppath, "#size-cells");
+	memcpy(addr, in_addr, na * 4);
+
+	for (;;) {
+		strcpy(path, ppath);
+		fdt_parentize(ppath, 0);
+
+		if (strlen(ppath) == 0)
+			return fdt_read_addr(addr, na);
+
+		fdt_match_bus(ppath, &pbus);
+		pna = fdt_find_cells(ppath, "#address-cells");
+		pns = fdt_find_cells(ppath, "#size-cells");
+
+		if (fdt_translate_one(path, &bus, &pbus, addr, na, ns, pna))
+			exit();
+
+		na = pna;
+		ns = pns;
+		memcpy(&bus, &pbus, sizeof(struct fdt_bus));
+	}
+}
+
+static void
+fdt_call_kernel(void *entry_addr, unsigned long a1, unsigned long a2,
+		void *promptr, void *sp)
+{
+	void (*kernel_entry)(void *dt_blob, void *start_addr,
+			void *must_be_null);
+
+#ifdef DEBUG
+	printf("kernel:\n\r"
+		"        entry addr   = 0x%lx\n\r"
+		"        flattened dt = 0x%lx\n\r",
+		(unsigned long)entry_addr, dtb_start);
+#endif
+
+	kernel_entry = entry_addr;
+	kernel_entry(dtb_start, entry_addr, NULL);
+}
+
+static struct dt_ops fdt_dt_ops;
+
+struct dt_ops *
+fdt_init(void *dt_blob)
+{
+	struct boot_param_header *bph;
+
+	fdt_dt_ops.finddevice = fdt_finddevice;
+	fdt_dt_ops.getprop = fdt_getprop;
+	fdt_dt_ops.setprop = fdt_setprop;
+	fdt_dt_ops.translate_addr = fdt_translate_addr;
+	fdt_dt_ops.call_kernel = fdt_call_kernel;
+
+	dtb_start = dt_blob;
+	bph = fdt_get_bph(dtb_start);
+	dtb_end = (void *)((u32)dtb_start + bph->totalsize);
+
+	return &fdt_dt_ops;
+}

^ permalink raw reply related

* [PATCH 4/6] bootwrapper: Add non-OF serial console support
From: Mark A. Greer @ 2006-07-19 23:12 UTC (permalink / raw)
  To: linuxppc-dev

This patch adds support for serial I/O to the bootwrapper.

It is broken into 2 layers.  The first layer is generic serial
operations that calls uart-specific routines to do the actual I/O.
The second layer contains support for a 16550 compatible uart.

The division allows support for other serial devices to be easily
added in the future (e.g., the Marvell MPSC and the Freescale CPM).

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

 io.h      |   53 ++++++++++++++++++++++++++++
 ns16550.c |  117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 serial.c  |   89 +++++++++++++++++++++++++++++++++++++++++++++++
 util.S    |  101 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 360 insertions(+)
--

diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
new file mode 100644
index 0000000..05c5348
--- /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>
+ */
+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..661cfff
--- /dev/null
+++ b/arch/powerpc/boot/ns16550.c
@@ -0,0 +1,117 @@
+/*
+ * 16550 serial console support.
+ *
+ * Copied from <file:arch/ppc/boot/common/ns16550.c>
+ * Fdt code, etc. added 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 */
+
+int
+ns16550_get_dt_info(struct serial_console_data *scdp)
+{
+	u64 addr;
+	u32 reg[2], reg_shift;
+	void *devp;
+	char path[MAX_PATH_LEN+1], compat[MAX_PATH_LEN+1];
+
+	scdp->base = NULL;
+	scdp->reg_shift = 0;
+
+	if ((devp = finddevice("/chosen"))
+			&& (getprop(devp, "linux,stdout-path", path,
+					sizeof(path)) > 0)
+			&& (devp = finddevice(path))
+			&& (getprop(devp, "compatible", compat, sizeof(compat))
+				> 0)
+			&& !strcmp(compat, "ns16550")
+			&& (getprop(devp, "reg", reg, sizeof(reg))
+				== sizeof(reg))) {
+
+		addr = ops->dt_ops->translate_addr(path, reg, sizeof(reg));
+		scdp->base = (unsigned char *)((u32)addr & 0xffffffffu);
+
+		if (getprop(devp, "reg_shift", &reg_shift, sizeof(reg_shift))
+				== sizeof(reg_shift))
+			scdp->reg_shift = reg_shift;
+		return 0;
+	}
+	return -1;
+}
+
+static int
+ns16550_open(void)
+{
+	struct serial_console_data *scdp = ops->console_ops->data;
+
+	if (ns16550_get_dt_info(scdp) < 0)
+		return -1;
+
+	out_8(scdp->base + (UART_FCR << scdp->reg_shift), 0x06);
+	return 0;
+}
+
+static void
+ns16550_putc(unsigned char c)
+{
+	struct serial_console_data *scdp = ops->console_ops->data;
+	while ((in_8(scdp->base + (UART_LSR << scdp->reg_shift))
+							& UART_LSR_THRE) == 0);
+	out_8(scdp->base, c);
+}
+
+static unsigned char
+ns16550_getc(void)
+{
+	struct serial_console_data *scdp = ops->console_ops->data;
+	while ((in_8(scdp->base + (UART_LSR << scdp->reg_shift))
+							& UART_LSR_DR) == 0);
+	return in_8(scdp->base);
+}
+
+static u8
+ns16550_tstc(void)
+{
+	struct serial_console_data *scdp = ops->console_ops->data;
+	return ((in_8(scdp->base + (UART_LSR << scdp->reg_shift)) & UART_LSR_DR)
+			!= 0);
+}
+
+static struct serial_console_data ns16550_scd;
+static struct console_ops ns16550_console_ops;
+
+struct console_ops *
+ns16550_init(void)
+{
+	ns16550_scd.open = ns16550_open;
+	ns16550_scd.putc = ns16550_putc;
+	ns16550_scd.getc = ns16550_getc;
+	ns16550_scd.tstc = ns16550_tstc;
+	ns16550_scd.close = NULL;
+	ns16550_scd.base = NULL;
+	ns16550_scd.reg_shift = 0;
+
+	ns16550_console_ops.open = serial_open;
+	ns16550_console_ops.write = serial_write;
+	ns16550_console_ops.edit_cmdline = serial_edit_cmdline;
+	ns16550_console_ops.close = serial_close;
+	ns16550_console_ops.data = &ns16550_scd;
+
+	return &ns16550_console_ops;
+}
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
new file mode 100644
index 0000000..6d064cb
--- /dev/null
+++ b/arch/powerpc/boot/serial.c
@@ -0,0 +1,89 @@
+/*
+ * 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);
+
+int
+serial_open(void)
+{
+	struct serial_console_data *scdp = ops->console_ops->data;
+	return scdp->open();
+}
+
+void
+serial_write(char *buf, int len)
+{
+	struct serial_console_data *scdp = ops->console_ops->data;
+
+	while (*buf != '\0')
+		scdp->putc(*buf++);
+}
+
+void
+serial_edit_cmdline(char *buf, int len)
+{
+	int timer = 0, count;
+	char ch, *cp;
+	struct serial_console_data *scdp = ops->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;
+}
+
+void
+serial_close(void)
+{
+	struct serial_console_data *scdp = ops->console_ops->data;
+
+	if (scdp->close)
+		scdp->close();
+}
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 5/6] bootwrapper: Add support for the DINK firmware
From: Mark A. Greer @ 2006-07-19 23:14 UTC (permalink / raw)
  To: linuxppc-dev

This patch adds the firmware operations that support the DINK firmware
from Freescale.

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

 dink.c |   56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 56 insertions(+)
--

diff --git a/arch/powerpc/boot/dink.c b/arch/powerpc/boot/dink.c
new file mode 100644
index 0000000..aa446e2
--- /dev/null
+++ b/arch/powerpc/boot/dink.c
@@ -0,0 +1,56 @@
+/*
+ * Sandpoint specific fixups.
+ *
+ * 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 <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+#define	MB	(1024*1024)
+
+extern char _end[];
+
+static u32	cur_base;
+static u32	end_of_ram = 32 * MB;
+
+static void *
+dink_malloc(u32 size)
+{
+	void *area = NULL;
+	static u8 first_time = 1;
+
+	if (first_time) {
+		cur_base = _ALIGN_UP((unsigned long)_end, MB);
+		first_time = 0;
+	}
+
+	if ((cur_base + size) < end_of_ram) {
+		area = (void *)cur_base;
+		cur_base += _ALIGN_UP(size, MB);
+	}
+
+	return area;
+}
+
+static struct fw_ops dink_fw_ops;
+
+struct fw_ops *
+dink_init(void)
+{
+	dink_fw_ops.malloc = dink_malloc;
+	dink_fw_ops.free = NULL;
+	dink_fw_ops.exit = NULL;
+
+	return &dink_fw_ops;
+}

^ permalink raw reply related


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