LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 4/4] DTC: Begin the path to sane literals and expressions.
From: David Gibson @ 2007-10-22  0:51 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, Jon Loeliger
In-Reply-To: <20d6133a9294d4f06a7e78ca627ec4f3@kernel.crashing.org>

On Sun, Oct 21, 2007 at 07:30:45AM +0200, Segher Boessenkool wrote:
> > Property names have been limited to start with
> > characters from the set [a-zA-Z,._#?].  That is, the
> > digits and the expression symbols have been removed.
> 
> This cannot work; many property names start with a digit,
> for example.

Yes, crap.  Ok, I guess we just have to put the literal lexer rule
before the property name lexer rule, so literals will be recognized in
preference.  Disallowing just those property names which look like
literals is a little warty, but not likely to cause trouble in
practice, I think.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH 4/4] DTC: Begin the path to sane literals and expressions.
From: David Gibson @ 2007-10-22  0:37 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, Jon Loeliger
In-Reply-To: <6a6fcd2bc9b0121cb5e9cfc675d88f57@kernel.crashing.org>

On Sun, Oct 21, 2007 at 07:32:33AM +0200, Segher Boessenkool wrote:
> >> Use of "d#', "o#", "h#" and "b#" are gone in version 1.
> >
> > Also good.  We might want to keep b#, since there's no C way of doing
> > binary literals,
> 
> GCC supports "0b...", and it is proposed new ISO C syntax, too.

Ah, ok.  We should go with that instead, then.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: ep88xc_defconfig doesn't build
From: David Gibson @ 2007-10-22  0:36 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev, scott.wood
In-Reply-To: <20071020024355.GA20356@lixom.net>

On Fri, Oct 19, 2007 at 09:43:55PM -0500, Olof Johansson wrote:
> Hi,
> 
> Did it ever?! I get this with current mainline when building default target:

I think you must have an old dtc; I'm pretty sure I removed the check
for /chosen some time ago.  But then I also thought we added a force
to the dtc commant line in wrapper ages ago, so now I'm a bit confused.

>   WRAP    arch/powerpc/boot/cuImage.8xx
> DTC: dts->dtb  on file "/work/work/linux/k.org/arch/powerpc/boot/dts/ep88xc.dts"
> ERROR: Missing /chosen node
> Input tree has errors
>   WRAP    arch/powerpc/boot/zImage.ep88xc
> make[1]: *** [arch/powerpc/boot/cuImage.8xx] Error 1
> make[1]: *** Waiting for unfinished jobs....
> DTC: dts->dtb  on file "/work/work/linux/k.org/arch/powerpc/boot/dts/ep88xc.dts"
> ERROR: Missing /chosen node
> Input tree has errors
> make[1]: *** [arch/powerpc/boot/zImage.ep88xc] Error 1
> make: *** [zImage] Error 2
> 
> 
> 
> -Olof
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: Device trees and audio codecs
From: Jon Smirl @ 2007-10-22  0:29 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: PowerPC dev list
In-Reply-To: <5cac8057884ac400b0596988414c7ed7@kernel.crashing.org>

On 10/21/07, Segher Boessenkool <segher@kernel.crashing.org> wrote:
> > How do we want to be consistent with the Efika which uses an AC97
> > codec that only connects to i2s?
>
> Huh?  AC'97 isn't I2S.  Yeah you probably could hook it up to some I2S
> device if you do all the interleaving and whatever stuff by hand -- but
> then you probably shouldn't call the I2S "host" an I2S anymore, but name
> it "ac97" in the device tree, or "this-or-that-i2s-controller-hooked-up-
> in-this-particular-crazy-way".  You will want to know which driver to
> use for the device, and if it's hooked up in "strange and unforeseen"
> ways you want to know about it.

I meant an ac97 bus. ac97 is conceptually the same as i2s with the
control signals also routed over it. ac97 and i2s are handled in the
same PSC on the 5200.

I have received conflicting opinions as to whether a codec hooked to
an ac97 bus should get a chip specific codec entry in the device tree.
Without the codec specific entry only generic ac97 features can be
used. The Efika has a STA9766. Looking at the data sheet for the chip
I see that it implements some proprietary functions in addition to the
standard ones.

asoc has a generic ac97 driver. Should the ac97 bus be required to
have a entry for the generic ac97 device? It would make loading the
driver much easier.


> _Please_ don't name busses that are not plain I2S "i2s" in the device
> tree.  At best this means you'll need a quirk in the kernel code to deal
> with this later.

the i2s and ac97 drivers for the mpc5200 already exist. I'm using
these preexisting drivers.


-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply

* Re: [PATCH v3] Device tree bindings for Xilinx devices
From: David Gibson @ 2007-10-22  0:29 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: Leonid, Arnd Bergmann, microblaze-uclinux, linuxppc-dev,
	Wolfgang Reissnegger
In-Reply-To: <20071019234347.38C1111C006B@mail3-dub.bigfish.com>

On Fri, Oct 19, 2007 at 04:42:58PM -0700, Stephen Neuendorffer wrote:
> 
> Here's a full .dts generated using an updated version of
> gen_mhs_devtree.py, following the proposal.
> It happens to be a microblaze system, but you get the idea.
> 
> Grant: Is this pretty what you intend?
> 
> Steve
> 
> / {
> 	#address-cells = <1>;
> 	#size-cells = <1>;
> 	compatible = "ibm,plb4";
> 	model = "system.mhs";

Although strictly speaking the root node can represent the top-level
system bus, to match the other 4xx chips it would be beter, as Grant
says, to make a /plb node and put the devices under that.

> 	Ethernet_MAC {

Node names should be lower case, and must include a unit address
derived from the reg property.  Furthermore, the generic names
convention means this should be called just "ethernet@...".

> 		compatible =
> "xilinx,opb-ethernet-1.04.a\0xilinx,opb-ethernet";
> 		device_type = "opb_ethernet";
> 		interrupt-parent = <101>;
> 		interrupts = < 1 0 >;
> 		reg = < 40c00000 10000 >;
> 		xilinx,cam-exist = <0>;
> 		xilinx,dev-blk-id = <0>;
> 		xilinx,dev-mir-enable = <0>;
> 		xilinx,dma-present = <1>;
> 		xilinx,include-dev-pencoder = <0>;
> 		xilinx,ipif-rdfifo-depth = <4000>;
> 		xilinx,ipif-wrfifo-depth = <4000>;
> 		xilinx,jumbo-exist = <0>;
> 		xilinx,mac-fifo-depth = <10>;
> 		xilinx,mii-exist = <1>;
> 		xilinx,opb-clk-period-ps = <2710>;
> 		xilinx,reset-present = <1>;
> 		xilinx,rx-dre-type = <0>;
> 		xilinx,rx-include-csum = <0>;
> 		xilinx,tx-dre-type = <0>;
> 		xilinx,tx-include-csum = <0>;
> 	} ;
> 	IIC_EEPROM {

Apart from the fact that it should be "eeprom@..." this doesn't look
right.  Surely there must be an i2c bridge, then an eeprom device
behind it?

> 		compatible = "xilinx,opb-iic-1.02.a\0xilinx,opb-iic";
> 		device_type = "opb_iic";
> 		interrupt-parent = <101>;
> 		interrupts = < 2 0 >;
> 		reg = < 40800000 10000 >;
> 		xilinx,clk-freq = <5f5e100>;
> 		xilinx,iic-freq = <186a0>;
> 		xilinx,ten-bit-adr = <0>;
> 	} ;
> 	RS232_Uart_1 {

"serial@...."

> 		compatible =
> "xilinx,opb-uartlite-1.00.b\0xilinx,opb-uartlite";
> 		device_type = "opb_uartlite";
device_type = "serial"

> 		interrupt-parent = <101>;
> 		interrupts = < 3 0 >;
> 		reg = < 40600000 10000 >;
> 		xilinx,baudrate = <2580>;
> 		xilinx,clk-freq = <5f5e100>;
> 		xilinx,data-bits = <8>;
> 		xilinx,odd-parity = <0>;
> 		xilinx,use-parity = <0>;
> 	} ;
> 	chosen {
> 		bootargs = "root=/dev/xsysace/disc0/part2";
> 		interrupt-controller = <101>;
> 		linux,platform = <600>;
> 	} ;
> 	cpus {
> 		#address-cells = <1>;
> 		#cpus = <1>;
> 		#size-cells = <0>;
> 		microblaze_0,6.00. {

Should be "cpu@0".

> 			32-bit;
> 			clock-frequency = <5f5e1000>;
> 			d-cache-line-size = <10>;
> 			d-cache-size = <4000>;
> 			device_type = "cpu";
> 			i-cache-line-size = <10>;
> 			i-cache-size = <4000>;
> 			linux,boot-cpu;
> 			reg = <0>;
> 			timebase-frequency = <1fca055>;
> 			xilinx,cache-byte-size = <4000>;
> 			xilinx,dcache-baseaddr = <50000000>;
> 			xilinx,dcache-byte-size = <4000>;
> 			xilinx,dcache-highaddr = <5fffffff>;
> 			xilinx,debug-enabled = <1>;
> 			xilinx,div-zero-exception = <1>;
> 			xilinx,dopb-bus-exception = <1>;
> 			xilinx,fpu-exception = <1>;
> 			xilinx,icache-baseaddr = <50000000>;
> 			xilinx,icache-highaddr = <5fffffff>;
> 			xilinx,ill-opcode-exception = <1>;
> 			xilinx,iopb-bus-exception = <1>;
> 			xilinx,number-of-pc-brk = <2>;
> 			xilinx,pvr = <2>;
> 			xilinx,unaligned-exceptions = <1>;
> 			xilinx,use-barrel = <1>;
> 			xilinx,use-dcache = <1>;
> 			xilinx,use-div = <1>;
> 			xilinx,use-fpu = <1>;
> 			xilinx,use-icache = <1>;
> 			xilinx,use-msr-instr = <1>;
> 			xilinx,use-pcmp-instr = <1>;
> 		} ;
> 	} ;
> 	debug_module {
> 		compatible = "xilinx,opb-mdm-2.00.a\0xilinx,opb-mdm";
> 		device_type = "opb_mdm";

No device_type here.

> 		reg = < 41400000 10000 >;
> 		xilinx,mb-dbg-ports = <1>;
> 		xilinx,uart-width = <8>;
> 		xilinx,use-uart = <1>;
> 	} ;
> 	memory@50000000 {
> 		device_type = "memory";
> 		edk_name = "DDR2_SDRAM_32Mx32";
> 		memreg:reg = < 50000000 10000000 >;

Unless you're actually using the memreg: label, it shouldn't be there.

> 	} ;
> 	opb_hwicap_0 {
> 		compatible =
> "xilinx,opb-hwicap-1.10.a\0xilinx,opb-hwicap";
> 		device_type = "opb_hwicap";

No device_type.

> 		reg = < 41300000 10000 >;
> 	} ;
> 	opb_intc_0 {
Should be interrupt-controller@...

> 		#interrupt-cells = <2>;
> 		compatible = "xilinx,opb-intc-1.00.c\0xilinx,opb-intc";
> 		device_type = "opb_intc";

No device_type.

> 		interrupt-controller;
> 		linux,phandle = <101>;
> 		reg = < 41200000 10000 >;
> 	} ;
> 	opb_timer_1 {

Needs unit address

> 		compatible =
> "xilinx,opb-timer-1.00.b\0xilinx,opb-timer";
> 		device_type = "opb_timer";

No device_type here.

> 		interrupt-parent = <101>;
> 		interrupts = < 0 0 >;
> 		reg = < 41c00000 10000 >;
> 		xilinx,count-width = <20>;
> 		xilinx,one-timer-only = <1>;
> 	} ;
> } ; 
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: Device trees and audio codecs
From: Segher Boessenkool @ 2007-10-21 23:33 UTC (permalink / raw)
  To: Jon Smirl; +Cc: PowerPC dev list
In-Reply-To: <9e4733910710211433r7e0cf4b4sf6aed12c57dda375@mail.gmail.com>

> Fabric driver tells how the generic codec is hooked up on the specific
> board. Some of the codecs are extremely flexible and can be hooked up
> hundreds of different ways. It is like GPIO pins, they are wired in
> however is convenient for the design.

Gotcha.  *Very* much like GPIOs, indeed.

>>> The fabric driver corresponds to the 'layout-id' in the Apple model.
>>> It tells how to configure the generic codec driver for the specific
>>> configuration needed by the actual platform hardware.
>>
>> The apple layout-id selects one of several tables with *lots* of info.
>> I think you want a subset of that only.
>
> The fabric/layout-id stuff is platform specific.

I mean that Apple's layout-id abstraction is "bigger" than your fabric
abstraction seems to be.  Not too important a point, anyway.

>>> My target hardware has a codec that is linked to both i2s and i2c. 
>>> How
>>> should it be represented?
>>
>> Since the codec is addressable on i2c, and not on i2s, it should be
>> a child node of the i2c bus it sits on; and then you put a property
>> in the codec node pointing to the i2s bus node it is connected to.
>> Multiple of those (or multiple entries) if it is connected to more
>> than one i2s bus.  "i2s-parent" might be a good name for such a prop.
>
> How do we want to be consistent with the Efika which uses an AC97
> codec that only connects to i2s?

Huh?  AC'97 isn't I2S.  Yeah you probably could hook it up to some I2S
device if you do all the interleaving and whatever stuff by hand -- but
then you probably shouldn't call the I2S "host" an I2S anymore, but name
it "ac97" in the device tree, or "this-or-that-i2s-controller-hooked-up-
in-this-particular-crazy-way".  You will want to know which driver to
use for the device, and if it's hooked up in "strange and unforeseen"
ways you want to know about it.

Maybe the platform code should do this, dunno.

_Please_ don't name busses that are not plain I2S "i2s" in the device
tree.  At best this means you'll need a quirk in the kernel code to deal
with this later.

</rant>


So anyway, why is it inconsistent to have an audio codec that is 
configured
over i2c sit on that i2c bus in the device tree as well, and refer to 
the i2s
bus it pumps audio data over; vs. having an ac97 codec that sits on an 
ac97
bus sit on that ac97 bus in the device tree as well?  In both cases, the
device is a child of the bus via which it is addressed.

The one exceptional case would be a dumb codec that isn't addressable 
at all;
it would be a device tree child of the dumb transport bus (where else 
could
it be put)?

> Actually those platform-XXX entries may be the solution I am looking
> for.

Like Ben already said, no you _do not_ want the platform-do stuff.  
Trust
him on this.  Or if you're feeling brave, look at the existing kernel 
code
that handles some of it ;-P


Segher

^ permalink raw reply

* [PATCH] Uartlite: speed up console output
From: Grant Likely @ 2007-10-21 23:02 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev, jacmet

From: Grant Likely <grant.likely@secretlab.ca>

Change the wait_tx routine to call cpu_relax() instead of udelay() to
reduce console output latency and test for the TXFULL bit instead of
TXEMPTY.  That way the FIFO doesn't need to by 100% flushed before
writing the next character.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 drivers/serial/uartlite.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index dfef83f..a85f2d3 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -329,12 +329,14 @@ static struct uart_ops ulite_ops = {
 static void ulite_console_wait_tx(struct uart_port *port)
 {
 	int i;
+	u8 val;
 
-	/* wait up to 10ms for the character(s) to be sent */
-	for (i = 0; i < 10000; i++) {
-		if (readb(port->membase + ULITE_STATUS) & ULITE_STATUS_TXEMPTY)
+	/* Spin waiting for TX fifo to have space available */
+	for (i = 0; i < 100000; i++) {
+		val = readb(port->membase + ULITE_STATUS);
+		if ((val & ULITE_STATUS_TXFULL) == 0)
 			break;
-		udelay(1);
+		cpu_relax();
 	}
 }
 

^ permalink raw reply related

* Re: Device trees and audio codecs
From: Benjamin Herrenschmidt @ 2007-10-21 22:19 UTC (permalink / raw)
  To: Jon Smirl; +Cc: PowerPC dev list
In-Reply-To: <9e4733910710211512v238fbc89m35783d5eb5b82bf6@mail.gmail.com>


On Sun, 2007-10-21 at 18:12 -0400, Jon Smirl wrote:
> On 10/21/07, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> >
> > On Sun, 2007-10-21 at 17:33 -0400, Jon Smirl wrote:
> > > > This is one of the i2s channels on the macio.  Dunno why they put
> > > > all those platform-XXX entries in here, (most of) these don't
> > > > logically belong here.
> > >
> > > Actually those platform-XXX entries may be the solution I am looking
> > > for. I can use the generic i2s driver to load a fabric driver as an
> > > ALSA module.
> >
> > Yuck.
> 
> And your alternative is?
> 
> I can use the DTC to load the I2S and codec drivers.
> 
> How do I get the platform specific fabric driver loaded? There is no
> way to load a driver matching on the platform name.

platform-do-XXX is unrelated to that. It's a kind of script in a blob
that is used to toggle various bits, it's plain ugly, totally powermac
specific (the code to handle it is in platform/powermac and I won't make
it generic) and so you don't want it... ever.

For your problem, an option is to do like apple, and have a "sound"
pseudo device which represents the "sound subsystem" of the machine
which cn ahave a compatible property and other bits that you can use to
match your fabric against, and loads the other bits & pieces.

Except that I would put it at the root of the tree.

Ben.

^ permalink raw reply

* Re: Device trees and audio codecs
From: Jon Smirl @ 2007-10-21 22:12 UTC (permalink / raw)
  To: benh; +Cc: PowerPC dev list
In-Reply-To: <1193004399.6745.39.camel@pasglop>

On 10/21/07, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
>
> On Sun, 2007-10-21 at 17:33 -0400, Jon Smirl wrote:
> > > This is one of the i2s channels on the macio.  Dunno why they put
> > > all those platform-XXX entries in here, (most of) these don't
> > > logically belong here.
> >
> > Actually those platform-XXX entries may be the solution I am looking
> > for. I can use the generic i2s driver to load a fabric driver as an
> > ALSA module.
>
> Yuck.

And your alternative is?

I can use the DTC to load the I2S and codec drivers.

How do I get the platform specific fabric driver loaded? There is no
way to load a driver matching on the platform name.

-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply

* Re: Device trees and audio codecs
From: Benjamin Herrenschmidt @ 2007-10-21 22:06 UTC (permalink / raw)
  To: Jon Smirl; +Cc: PowerPC dev list
In-Reply-To: <9e4733910710211433r7e0cf4b4sf6aed12c57dda375@mail.gmail.com>


On Sun, 2007-10-21 at 17:33 -0400, Jon Smirl wrote:
> > This is one of the i2s channels on the macio.  Dunno why they put
> > all those platform-XXX entries in here, (most of) these don't
> > logically belong here.
> 
> Actually those platform-XXX entries may be the solution I am looking
> for. I can use the generic i2s driver to load a fabric driver as an
> ALSA module.

Yuck.

Ben.

^ permalink raw reply

* Re: Device trees and audio codecs
From: Jon Smirl @ 2007-10-21 21:33 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: PowerPC dev list
In-Reply-To: <a76a128145ec8a8f779727a7e11925ac@kernel.crashing.org>

On 10/21/07, Segher Boessenkool <segher@kernel.crashing.org> wrote:
> > I'm working on ALSA ASoC support for a codec chip on my mpc5200 based
> > target hardware.
>
> What is ASoC?

asoc = ALSA System on a Chip. It is in sound/soc

> > Under ASoC the device drivers for the codec chips are platform
> > independent.  In the current ASoC model there are three device
> > drivers: i2s (or spi, etc), the generic codec, and a platform specific
> > 'fabric' driver.  Some codecs are linked to both i2c and i2s.
>
> The i2s driver is simply for data transport, the codec driver does,
> well, what codecs do; and what is the fabric driver for?  Just to
> know which output ports are which, etc.?

Fabric driver tells how the generic codec is hooked up on the specific
board. Some of the codecs are extremely flexible and can be hooked up
hundreds of different ways. It is like GPIO pins, they are wired in
however is convenient for the design.

> > The fabric driver corresponds to the 'layout-id' in the Apple model.
> > It tells how to configure the generic codec driver for the specific
> > configuration needed by the actual platform hardware.
>
> The apple layout-id selects one of several tables with *lots* of info.
> I think you want a subset of that only.

The fabric/layout-id stuff is platform specific.

> > My target hardware has a codec that is linked to both i2s and i2c. How
> > should it be represented?
>
> Since the codec is addressable on i2c, and not on i2s, it should be
> a child node of the i2c bus it sits on; and then you put a property
> in the codec node pointing to the i2s bus node it is connected to.
> Multiple of those (or multiple entries) if it is connected to more
> than one i2s bus.  "i2s-parent" might be a good name for such a prop.

How do we want to be consistent with the Efika which uses an AC97
codec that only connects to i2s?

> > Apple has three entries. One for i2s, one for the codec, and one for
> > soundchip. What is the soundchip entry, does it correspond to real
> > hardware?
> >
> > /proc/device-tree/pci@f2000000/mac-io@17/i2s@0/i2s-a@10000:
>
> This is one of the i2s channels on the macio.  Dunno why they put
> all those platform-XXX entries in here, (most of) these don't
> logically belong here.

Actually those platform-XXX entries may be the solution I am looking
for. I can use the generic i2s driver to load a fabric driver as an
ALSA module.

> > /proc/device-tree/pci@f2000000/mac-io@17/i2s@0/i2s-a@10000/sound:
>
> The codec.  I guess Apple puts this here for their weirdo platform-do
> stuff; don't imitate this :-)
>
> > /proc/device-tree/pci@f2000000/mac-io@17/i2c@18000/i2c-bus@0/codec@6a:
>
> The codec.  _Do_ put it here in your tree :-)

-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply

* Re: rtlinux rtai interrupt latency
From: Wolfgang Denk @ 2007-10-21 21:25 UTC (permalink / raw)
  To: Nicholas Mc Guire; +Cc: linuxppc-dev, linuxppc-embedded
In-Reply-To: <Pine.LNX.4.60.0710202230230.1476@rtl14.hofr.at>

In message <Pine.LNX.4.60.0710202230230.1476@rtl14.hofr.at> you wrote:
> 
> There are free variants around as well - XtratuM/PPC (RTLinux-4.0) is
> running on 440EP/GR and 405 Octobus, im quite sur RTAI also is available
> for AMCC CPUs - check RTAI.org (mailing list link is to be found there) 

Not really. RTAI is a dead horse for anything except x86.

Instead, look at Xenomai ==> www.xenomai.org

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
G's Third Law:             In spite of all evidence  to  the  contra-
ry,  the  entire  universe  is composed of only two basic substances:
magic and bullshit.
H's Dictum:                There is no magic ...

^ permalink raw reply

* Re: [BUG] powerpc does not save msi state [was Re: [PATCH 5/7] pci: Export the pci_restore_msi_state() function
From: Benjamin Herrenschmidt @ 2007-10-21 21:13 UTC (permalink / raw)
  To: michael; +Cc: netdev, mcarlson, linuxppc-dev, mchan, linux-pci, David Miller
In-Reply-To: <1192862606.7688.4.camel@concordia>


> That's a pity, but AFAIK it shouldn't be a problem because we don't
> enable CONFIG_PM on those machines anyway. If we ever want to we'll need
> to sort out with firmware how that will work WRT restoring MSI state.

I think the current generic code for pci_restore_msi_state() or whatever
it's called wilol directly call into write_msi_msg() etc... might be a
problem.

Ben.

^ permalink raw reply

* Re: [PATCH] synchronize_irq needs a barrier
From: Benjamin Herrenschmidt @ 2007-10-21 21:10 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Linux Kernel Mailing List, linuxppc-dev, Thomas Gleixner, akpm,
	Linus Torvalds, Ingo Molnar
In-Reply-To: <1192769910.7367.106.camel@pasglop>


 .../...

> This patch (mostly written by Linus) fixes this by using spin
> > locks instead of memory barries on the synchronize_irq() path.
> > 
> > Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
> 
> Good for me.
> 
> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Hrm... not on yet. Herbert, care to resend, looks like it fell down the
wrong hole in Linus mailbox :-)

Cheers,
Ben.

^ permalink raw reply

* Re: Device trees and audio codecs
From: Segher Boessenkool @ 2007-10-21 19:14 UTC (permalink / raw)
  To: Jon Smirl; +Cc: PowerPC dev list
In-Reply-To: <9e4733910710200833x5d1c55b5l2cd400f77c13ec87@mail.gmail.com>

> I'm working on ALSA ASoC support for a codec chip on my mpc5200 based
> target hardware.

What is ASoC?

> Under ASoC the device drivers for the codec chips are platform
> independent.  In the current ASoC model there are three device
> drivers: i2s (or spi, etc), the generic codec, and a platform specific
> 'fabric' driver.  Some codecs are linked to both i2c and i2s.

The i2s driver is simply for data transport, the codec driver does,
well, what codecs do; and what is the fabric driver for?  Just to
know which output ports are which, etc.?

> The fabric driver corresponds to the 'layout-id' in the Apple model.
> It tells how to configure the generic codec driver for the specific
> configuration needed by the actual platform hardware.

The apple layout-id selects one of several tables with *lots* of info.
I think you want a subset of that only.

> My target hardware has a codec that is linked to both i2s and i2c. How
> should it be represented?

Since the codec is addressable on i2c, and not on i2s, it should be
a child node of the i2c bus it sits on; and then you put a property
in the codec node pointing to the i2s bus node it is connected to.
Multiple of those (or multiple entries) if it is connected to more
than one i2s bus.  "i2s-parent" might be a good name for such a prop.

> Apple has three entries. One for i2s, one for the codec, and one for
> soundchip. What is the soundchip entry, does it correspond to real
> hardware?
>
> /proc/device-tree/pci@f2000000/mac-io@17/i2s@0/i2s-a@10000:

This is one of the i2s channels on the macio.  Dunno why they put
all those platform-XXX entries in here, (most of) these don't
logically belong here.

> /proc/device-tree/pci@f2000000/mac-io@17/i2s@0/i2s-a@10000/sound:

The codec.  I guess Apple puts this here for their weirdo platform-do
stuff; don't imitate this :-)

> /proc/device-tree/pci@f2000000/mac-io@17/i2c@18000/i2c-bus@0/codec@6a:

The codec.  _Do_ put it here in your tree :-)


Segher

^ permalink raw reply

* Fwd: Please pull linux-2.6-mpc52xx.git
From: Grant Likely @ 2007-10-21 18:56 UTC (permalink / raw)
  To: linuxppc-dev, Paul Mackerras
In-Reply-To: <fa686aa40710211154r22d5ccbfu5f54d392aad99880@mail.gmail.com>

Paulus, please pull the following mpc52xx related changes.

The following changes since commit 2fb59d623ad85dfdb8ce03a660051743f7361896:
  Linus Torvalds (1):
        Merge branch 'audit.b43' of git://git.kernel.org/.../viro/audit-current

are available in the git repository at:

  git://git.secretlab.ca/git/linux-2.6-mpc52xx.git for-2.6.24

Grant Likely (1):
      [POWERPC] bestcomm: Restrict bus prefetch bugfix to original
mpc5200 silicon.

Marian Balakowicz (4):
      [POWERPC] Add mpc52xx_find_and_map_path(), refactor utility functions
      [POWERPC] Update device tree binding for mpc5200 gpt
      [POWERPC] Add restart support for mpc52xx based platforms
      [POWERPC] Enable restart support for lite5200 board

 .../powerpc/mpc52xx-device-tree-bindings.txt       |    4 +-
 arch/powerpc/boot/dts/lite5200.dts                 |   26 +++-----
 arch/powerpc/boot/dts/lite5200b.dts                |   26 +++-----
 arch/powerpc/platforms/52xx/lite5200.c             |    4 +
 arch/powerpc/platforms/52xx/mpc52xx_common.c       |   71 ++++++++++++++++++-
 arch/powerpc/sysdev/bestcomm/bestcomm.c            |    9 ++-
 drivers/watchdog/mpc5200_wdt.c                     |    3 +
 include/asm-powerpc/mpc52xx.h                      |    9 +++
 8 files changed, 109 insertions(+), 43 deletions(-)


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


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

^ permalink raw reply

* Re: [PATCH v4] FEC - fast ethernet controller for mpc52xx
From: Grant Likely @ 2007-10-21 18:32 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-dev, Jeff Garzik, netdev
In-Reply-To: <20071019112700.GD27403@nd47.coderock.org>

On 10/19/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> Driver for ethernet on mpc5200/mpc5200b SoCs (FEC).
>
>
> Signed-off-by: Domen Puncer <domen.puncer@telargo.com>

I've tested this on my lite5200.  It works well.

Jeff, I've got no objections to this going in.  All the needed
platform support has already been merged.

Cheers,
g.

>
> ---
> On 18/10/07 15:14 -0400, Jeff Garzik wrote:
> >
> > except a resend combining patches 3 and 4 as requested :)
>
> OK, here it goes. Sorry for the delay.
>
>
> diffstat:
>  drivers/net/Kconfig           |   24
>  drivers/net/Makefile          |    4
>  drivers/net/fec_mpc52xx.c     | 1107 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/fec_mpc52xx.h     |  315 +++++++++++
>  drivers/net/fec_mpc52xx_phy.c |  198 +++++++
>  5 files changed, 1648 insertions(+)
>
> Index: linux.git/drivers/net/Kconfig
> ===================================================================
> --- linux.git.orig/drivers/net/Kconfig
> +++ linux.git/drivers/net/Kconfig
> @@ -1895,6 +1895,30 @@ config FEC2
>           Say Y here if you want to use the second built-in 10/100 Fast
>           ethernet controller on some Motorola ColdFire processors.
>
> +config FEC_MPC52xx
> +       tristate "MPC52xx FEC driver"
> +       depends on PPC_MPC52xx
> +       select PPC_BESTCOMM
> +       select PPC_BESTCOMM_FEC
> +       select CRC32
> +       select PHYLIB
> +       ---help---
> +         This option enables support for the MPC5200's on-chip
> +         Fast Ethernet Controller
> +         If compiled as module, it will be called 'fec_mpc52xx.ko'.
> +
> +config FEC_MPC52xx_MDIO
> +       bool "MPC52xx FEC MDIO bus driver"
> +       depends on FEC_MPC52xx
> +       default y
> +       ---help---
> +         The MPC5200's FEC can connect to the Ethernet either with
> +         an external MII PHY chip or 10 Mbps 7-wire interface
> +         (Motorola? industry standard).
> +         If your board uses an external PHY connected to FEC, enable this.
> +         If not sure, enable.
> +         If compiled as module, it will be called 'fec_mpc52xx_phy.ko'.
> +
>  config NE_H8300
>         tristate "NE2000 compatible support for H8/300"
>         depends on H8300
> Index: linux.git/drivers/net/Makefile
> ===================================================================
> --- linux.git.orig/drivers/net/Makefile
> +++ linux.git/drivers/net/Makefile
> @@ -96,6 +96,10 @@ obj-$(CONFIG_SHAPER) += shaper.o
>  obj-$(CONFIG_HP100) += hp100.o
>  obj-$(CONFIG_SMC9194) += smc9194.o
>  obj-$(CONFIG_FEC) += fec.o
> +obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
> +ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
> +       obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
> +endif
>  obj-$(CONFIG_68360_ENET) += 68360enet.o
>  obj-$(CONFIG_WD80x3) += wd.o 8390.o
>  obj-$(CONFIG_EL2) += 3c503.o 8390.o
> Index: linux.git/drivers/net/fec_mpc52xx.c
> ===================================================================
> --- /dev/null
> +++ linux.git/drivers/net/fec_mpc52xx.c
> @@ -0,0 +1,1107 @@
> +/*
> + * Driver for the MPC5200 Fast Ethernet Controller
> + *
> + * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> and
> + * now maintained by Sylvain Munaut <tnt@246tNt.com>
> + *
> + * Copyright (C) 2007  Domen Puncer, Telargo, Inc.
> + * Copyright (C) 2007  Sylvain Munaut <tnt@246tNt.com>
> + * Copyright (C) 2003-2004  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 <linux/module.h>
> +
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/spinlock.h>
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/crc32.h>
> +#include <linux/hardirq.h>
> +#include <linux/delay.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +#include <linux/ethtool.h>
> +#include <linux/skbuff.h>
> +
> +#include <asm/io.h>
> +#include <asm/delay.h>
> +#include <asm/mpc52xx.h>
> +
> +#include <sysdev/bestcomm/bestcomm.h>
> +#include <sysdev/bestcomm/fec.h>
> +
> +#include "fec_mpc52xx.h"
> +
> +#define DRIVER_NAME "mpc52xx-fec"
> +
> +static irqreturn_t mpc52xx_fec_interrupt(int, void *);
> +static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *);
> +static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *);
> +static void mpc52xx_fec_stop(struct net_device *dev);
> +static void mpc52xx_fec_start(struct net_device *dev);
> +static void mpc52xx_fec_reset(struct net_device *dev);
> +
> +static u8 mpc52xx_fec_mac_addr[6];
> +module_param_array_named(mac, mpc52xx_fec_mac_addr, byte, NULL, 0);
> +MODULE_PARM_DESC(mac, "six hex digits, ie. 0x1,0x2,0xc0,0x01,0xba,0xbe");
> +
> +static void mpc52xx_fec_tx_timeout(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +
> +       dev_warn(&dev->dev, "transmit timed out\n");
> +
> +       mpc52xx_fec_reset(dev);
> +
> +       priv->stats.tx_errors++;
> +
> +       if (!priv->tx_full)
> +               netif_wake_queue(dev);
> +}
> +
> +static void mpc52xx_fec_set_paddr(struct net_device *dev, u8 *mac)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> +       out_be32(&fec->paddr1, *(u32 *)(&mac[0]));
> +       out_be32(&fec->paddr2, (*(u16 *)(&mac[4]) << 16) | FEC_PADDR2_TYPE);
> +}
> +
> +static void mpc52xx_fec_get_paddr(struct net_device *dev, u8 *mac)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> +       *(u32 *)(&mac[0]) = in_be32(&fec->paddr1);
> +       *(u16 *)(&mac[4]) = in_be32(&fec->paddr2) >> 16;
> +}
> +
> +static int mpc52xx_fec_set_mac_address(struct net_device *dev, void *addr)
> +{
> +       struct sockaddr *sock = addr;
> +
> +       memcpy(dev->dev_addr, sock->sa_data, dev->addr_len);
> +
> +       mpc52xx_fec_set_paddr(dev, sock->sa_data);
> +       return 0;
> +}
> +
> +static void mpc52xx_fec_free_rx_buffers(struct bcom_task *s)
> +{
> +       struct sk_buff *skb;
> +
> +       while (!bcom_queue_empty(s)) {
> +               skb = bcom_retrieve_buffer(s, NULL, NULL);
> +               kfree_skb(skb);
> +       }
> +}
> +
> +static int mpc52xx_fec_alloc_rx_buffers(struct bcom_task *rxtsk)
> +{
> +       while (!bcom_queue_full(rxtsk)) {
> +               struct sk_buff *skb;
> +               struct bcom_fec_bd *bd;
> +
> +               skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
> +               if (skb == NULL)
> +                       return -EAGAIN;
> +
> +               /* zero out the initial receive buffers to aid debugging */
> +               memset(skb->data, 0, FEC_RX_BUFFER_SIZE);
> +
> +               bd = (struct bcom_fec_bd *)bcom_prepare_next_buffer(rxtsk);
> +
> +               bd->status = FEC_RX_BUFFER_SIZE;
> +               bd->skb_pa = virt_to_phys(skb->data);
> +
> +               bcom_submit_next_buffer(rxtsk, skb);
> +       }
> +
> +       return 0;
> +}
> +
> +/* based on generic_adjust_link from fs_enet-main.c */
> +static void mpc52xx_fec_adjust_link(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct phy_device *phydev = priv->phydev;
> +       int new_state = 0;
> +
> +       if (phydev->link != PHY_DOWN) {
> +               if (phydev->duplex != priv->duplex) {
> +                       struct mpc52xx_fec __iomem *fec = priv->fec;
> +                       u32 rcntrl;
> +                       u32 tcntrl;
> +
> +                       new_state = 1;
> +                       priv->duplex = phydev->duplex;
> +
> +                       rcntrl = in_be32(&fec->r_cntrl);
> +                       tcntrl = in_be32(&fec->x_cntrl);
> +
> +                       rcntrl &= ~FEC_RCNTRL_DRT;
> +                       tcntrl &= ~FEC_TCNTRL_FDEN;
> +                       if (phydev->duplex == DUPLEX_FULL)
> +                               tcntrl |= FEC_TCNTRL_FDEN;      /* FD enable */
> +                       else
> +                               rcntrl |= FEC_RCNTRL_DRT;       /* disable Rx on Tx (HD) */
> +
> +                       out_be32(&fec->r_cntrl, rcntrl);
> +                       out_be32(&fec->x_cntrl, tcntrl);
> +               }
> +
> +               if (phydev->speed != priv->speed) {
> +                       new_state = 1;
> +                       priv->speed = phydev->speed;
> +               }
> +
> +               if (priv->link == PHY_DOWN) {
> +                       new_state = 1;
> +                       priv->link = phydev->link;
> +                       netif_schedule(dev);
> +                       netif_carrier_on(dev);
> +                       netif_start_queue(dev);
> +               }
> +
> +       } else if (priv->link) {
> +               new_state = 1;
> +               priv->link = PHY_DOWN;
> +               priv->speed = 0;
> +               priv->duplex = -1;
> +               netif_stop_queue(dev);
> +               netif_carrier_off(dev);
> +       }
> +
> +       if (new_state && netif_msg_link(priv))
> +               phy_print_status(phydev);
> +}
> +
> +static int mpc52xx_fec_init_phy(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct phy_device *phydev;
> +       char phy_id[BUS_ID_SIZE];
> +
> +       snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT,
> +                       (unsigned int)dev->base_addr, priv->phy_addr);
> +
> +       priv->link = PHY_DOWN;
> +       priv->speed = 0;
> +       priv->duplex = -1;
> +
> +       phydev = phy_connect(dev, phy_id, &mpc52xx_fec_adjust_link, 0, PHY_INTERFACE_MODE_MII);
> +       if (IS_ERR(phydev)) {
> +               dev_err(&dev->dev, "phy_connect failed\n");
> +               return PTR_ERR(phydev);
> +       }
> +       dev_info(&dev->dev, "attached phy %i to driver %s\n",
> +                       phydev->addr, phydev->drv->name);
> +
> +       priv->phydev = phydev;
> +
> +       return 0;
> +}
> +
> +static int mpc52xx_fec_phy_start(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       int err;
> +
> +       if (!priv->has_phy)
> +               return 0;
> +
> +       err = mpc52xx_fec_init_phy(dev);
> +       if (err) {
> +               dev_err(&dev->dev, "mpc52xx_fec_init_phy failed\n");
> +               return err;
> +       }
> +
> +       /* reset phy - this also wakes it from PDOWN */
> +       phy_write(priv->phydev, MII_BMCR, BMCR_RESET);
> +       phy_start(priv->phydev);
> +
> +       return 0;
> +}
> +
> +static void mpc52xx_fec_phy_stop(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +
> +       if (!priv->has_phy)
> +               return;
> +
> +       phy_disconnect(priv->phydev);
> +       /* power down phy */
> +       phy_stop(priv->phydev);
> +       phy_write(priv->phydev, MII_BMCR, BMCR_PDOWN);
> +}
> +
> +static int mpc52xx_fec_phy_mii_ioctl(struct mpc52xx_fec_priv *priv,
> +               struct mii_ioctl_data *mii_data, int cmd)
> +{
> +       if (!priv->has_phy)
> +               return -ENOTSUPP;
> +
> +       return phy_mii_ioctl(priv->phydev, mii_data, cmd);
> +}
> +
> +static void mpc52xx_fec_phy_hw_init(struct mpc52xx_fec_priv *priv)
> +{
> +       struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> +       if (!priv->has_phy)
> +               return;
> +
> +       out_be32(&fec->mii_speed, priv->phy_speed);
> +}
> +
> +static int mpc52xx_fec_open(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       int err = -EBUSY;
> +
> +       if (request_irq(dev->irq, &mpc52xx_fec_interrupt, IRQF_DISABLED | IRQF_SHARED,
> +                       DRIVER_NAME "_ctrl", dev)) {
> +               dev_err(&dev->dev, "ctrl interrupt request failed\n");
> +               goto out;
> +       }
> +       if (request_irq(priv->r_irq, &mpc52xx_fec_rx_interrupt, IRQF_DISABLED,
> +                       DRIVER_NAME "_rx", dev)) {
> +               dev_err(&dev->dev, "rx interrupt request failed\n");
> +               goto free_ctrl_irq;
> +       }
> +       if (request_irq(priv->t_irq, &mpc52xx_fec_tx_interrupt, IRQF_DISABLED,
> +                       DRIVER_NAME "_tx", dev)) {
> +               dev_err(&dev->dev, "tx interrupt request failed\n");
> +               goto free_2irqs;
> +       }
> +
> +       bcom_fec_rx_reset(priv->rx_dmatsk);
> +       bcom_fec_tx_reset(priv->tx_dmatsk);
> +
> +       err = mpc52xx_fec_alloc_rx_buffers(priv->rx_dmatsk);
> +       if (err) {
> +               dev_err(&dev->dev, "mpc52xx_fec_alloc_rx_buffers failed\n");
> +               goto free_irqs;
> +       }
> +
> +       err = mpc52xx_fec_phy_start(dev);
> +       if (err)
> +               goto free_skbs;
> +
> +       bcom_enable(priv->rx_dmatsk);
> +       bcom_enable(priv->tx_dmatsk);
> +
> +       mpc52xx_fec_start(dev);
> +
> +       netif_start_queue(dev);
> +
> +       return 0;
> +
> + free_skbs:
> +       mpc52xx_fec_free_rx_buffers(priv->rx_dmatsk);
> +
> + free_irqs:
> +       free_irq(priv->t_irq, dev);
> + free_2irqs:
> +       free_irq(priv->r_irq, dev);
> + free_ctrl_irq:
> +       free_irq(dev->irq, dev);
> + out:
> +
> +       return err;
> +}
> +
> +static int mpc52xx_fec_close(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +
> +       netif_stop_queue(dev);
> +
> +       mpc52xx_fec_stop(dev);
> +
> +       mpc52xx_fec_free_rx_buffers(priv->rx_dmatsk);
> +
> +       free_irq(dev->irq, dev);
> +       free_irq(priv->r_irq, dev);
> +       free_irq(priv->t_irq, dev);
> +
> +       mpc52xx_fec_phy_stop(dev);
> +
> +       return 0;
> +}
> +
> +/* This will only be invoked if your driver is _not_ in XOFF state.
> + * What this means is that you need not check it, and that this
> + * invariant will hold if you make sure that the netif_*_queue()
> + * calls are done at the proper times.
> + */
> +static int mpc52xx_fec_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct bcom_fec_bd *bd;
> +
> +       if (bcom_queue_full(priv->tx_dmatsk)) {
> +               if (net_ratelimit())
> +                       dev_err(&dev->dev, "transmit queue overrun\n");
> +               return 1;
> +       }
> +
> +       spin_lock_irq(&priv->lock);
> +       dev->trans_start = jiffies;
> +
> +       bd = (struct bcom_fec_bd *)
> +               bcom_prepare_next_buffer(priv->tx_dmatsk);
> +
> +       bd->status = skb->len | BCOM_FEC_TX_BD_TFD | BCOM_FEC_TX_BD_TC;
> +       bd->skb_pa = virt_to_phys(skb->data);
> +
> +       bcom_submit_next_buffer(priv->tx_dmatsk, skb);
> +
> +       if (bcom_queue_full(priv->tx_dmatsk)) {
> +               priv->tx_full = 1;
> +               netif_stop_queue(dev);
> +       }
> +
> +       spin_unlock_irq(&priv->lock);
> +
> +       return 0;
> +}
> +
> +/* This handles BestComm transmit task interrupts
> + */
> +static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id)
> +{
> +       struct net_device *dev = dev_id;
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +
> +       spin_lock(&priv->lock);
> +
> +       while (bcom_buffer_done(priv->tx_dmatsk)) {
> +               struct sk_buff *skb;
> +               skb = bcom_retrieve_buffer(priv->tx_dmatsk, NULL, NULL);
> +
> +               priv->tx_full = 0;
> +               dev_kfree_skb_irq(skb);
> +       }
> +
> +       if (netif_queue_stopped(dev) && !priv->tx_full)
> +               netif_wake_queue(dev);
> +
> +       spin_unlock(&priv->lock);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id)
> +{
> +       struct net_device *dev = dev_id;
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +
> +       while (bcom_buffer_done(priv->rx_dmatsk)) {
> +               struct sk_buff *skb;
> +               struct sk_buff *rskb;
> +               struct bcom_fec_bd *bd;
> +               u32 status;
> +
> +               rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status, NULL);
> +
> +               /* Test for errors in received frame */
> +               if (status & BCOM_FEC_RX_BD_ERRORS) {
> +                       /* Drop packet and reuse the buffer */
> +                       bd = (struct bcom_fec_bd *)
> +                               bcom_prepare_next_buffer(priv->rx_dmatsk);
> +
> +                       bd->status = FEC_RX_BUFFER_SIZE;
> +                       bd->skb_pa = virt_to_phys(rskb->data);
> +
> +                       bcom_submit_next_buffer(priv->rx_dmatsk, rskb);
> +
> +                       priv->stats.rx_dropped++;
> +
> +                       continue;
> +               }
> +
> +               /* skbs are allocated on open, so now we allocate a new one,
> +                * and remove the old (with the packet) */
> +               skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
> +               if (skb) {
> +                       /* Process the received skb */
> +                       int length = status & BCOM_FEC_RX_BD_LEN_MASK;
> +
> +                       skb_put(rskb, length - 4);      /* length without CRC32 */
> +
> +                       rskb->dev = dev;
> +                       rskb->protocol = eth_type_trans(rskb, dev);
> +
> +                       netif_rx(rskb);
> +                       dev->last_rx = jiffies;
> +               } else {
> +                       /* Can't get a new one : reuse the same & drop pkt */
> +                       dev_notice(&dev->dev, "Memory squeeze, dropping packet.\n");
> +                       priv->stats.rx_dropped++;
> +
> +                       skb = rskb;
> +               }
> +
> +               bd = (struct bcom_fec_bd *)
> +                       bcom_prepare_next_buffer(priv->rx_dmatsk);
> +
> +               bd->status = FEC_RX_BUFFER_SIZE;
> +               bd->skb_pa = virt_to_phys(skb->data);
> +
> +               bcom_submit_next_buffer(priv->rx_dmatsk, skb);
> +       }
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id)
> +{
> +       struct net_device *dev = dev_id;
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct mpc52xx_fec __iomem *fec = priv->fec;
> +       u32 ievent;
> +
> +       ievent = in_be32(&fec->ievent);
> +
> +       ievent &= ~FEC_IEVENT_MII;      /* mii is handled separately */
> +       if (!ievent)
> +               return IRQ_NONE;
> +
> +       out_be32(&fec->ievent, ievent);         /* clear pending events */
> +
> +       if (ievent & ~(FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
> +               if (ievent & ~FEC_IEVENT_TFINT)
> +                       dev_dbg(&dev->dev, "ievent: %08x\n", ievent);
> +               return IRQ_HANDLED;
> +       }
> +
> +       if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR))
> +               dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n");
> +       if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
> +               dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n");
> +
> +       mpc52xx_fec_reset(dev);
> +
> +       netif_wake_queue(dev);
> +       return IRQ_HANDLED;
> +}
> +
> +/*
> + * Get the current statistics.
> + * This may be called with the card open or closed.
> + */
> +static struct net_device_stats *mpc52xx_fec_get_stats(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct net_device_stats *stats = &priv->stats;
> +       struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> +       stats->rx_bytes = in_be32(&fec->rmon_r_octets);
> +       stats->rx_packets = in_be32(&fec->rmon_r_packets);
> +       stats->rx_errors = in_be32(&fec->rmon_r_crc_align) +
> +               in_be32(&fec->rmon_r_undersize) +
> +               in_be32(&fec->rmon_r_oversize) +
> +               in_be32(&fec->rmon_r_frag) +
> +               in_be32(&fec->rmon_r_jab);
> +
> +       stats->tx_bytes = in_be32(&fec->rmon_t_octets);
> +       stats->tx_packets = in_be32(&fec->rmon_t_packets);
> +       stats->tx_errors = in_be32(&fec->rmon_t_crc_align) +
> +               in_be32(&fec->rmon_t_undersize) +
> +               in_be32(&fec->rmon_t_oversize) +
> +               in_be32(&fec->rmon_t_frag) +
> +               in_be32(&fec->rmon_t_jab);
> +
> +       stats->multicast = in_be32(&fec->rmon_r_mc_pkt);
> +       stats->collisions = in_be32(&fec->rmon_t_col);
> +
> +       /* detailed rx_errors: */
> +       stats->rx_length_errors = in_be32(&fec->rmon_r_undersize)
> +                                       + in_be32(&fec->rmon_r_oversize)
> +                                       + in_be32(&fec->rmon_r_frag)
> +                                       + in_be32(&fec->rmon_r_jab);
> +       stats->rx_over_errors = in_be32(&fec->r_macerr);
> +       stats->rx_crc_errors = in_be32(&fec->ieee_r_crc);
> +       stats->rx_frame_errors = in_be32(&fec->ieee_r_align);
> +       stats->rx_fifo_errors = in_be32(&fec->rmon_r_drop);
> +       stats->rx_missed_errors = in_be32(&fec->rmon_r_drop);
> +
> +       /* detailed tx_errors: */
> +       stats->tx_aborted_errors = 0;
> +       stats->tx_carrier_errors = in_be32(&fec->ieee_t_cserr);
> +       stats->tx_fifo_errors = in_be32(&fec->rmon_t_drop);
> +       stats->tx_heartbeat_errors = in_be32(&fec->ieee_t_sqe);
> +       stats->tx_window_errors = in_be32(&fec->ieee_t_lcol);
> +
> +       return stats;
> +}
> +
> +/*
> + * Read MIB counters in order to reset them,
> + * then zero all the stats fields in memory
> + */
> +static void mpc52xx_fec_reset_stats(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> +       out_be32(&fec->mib_control, FEC_MIB_DISABLE);
> +       memset_io(&fec->rmon_t_drop, 0, (__force u32)&fec->reserved10 -
> +                       (__force u32)&fec->rmon_t_drop);
> +       out_be32(&fec->mib_control, 0);
> +
> +       memset(&priv->stats, 0, sizeof(priv->stats));
> +}
> +
> +/*
> + * Set or clear the multicast filter for this adaptor.
> + */
> +static void mpc52xx_fec_set_multicast_list(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct mpc52xx_fec __iomem *fec = priv->fec;
> +       u32 rx_control;
> +
> +       rx_control = in_be32(&fec->r_cntrl);
> +
> +       if (dev->flags & IFF_PROMISC) {
> +               rx_control |= FEC_RCNTRL_PROM;
> +               out_be32(&fec->r_cntrl, rx_control);
> +       } else {
> +               rx_control &= ~FEC_RCNTRL_PROM;
> +               out_be32(&fec->r_cntrl, rx_control);
> +
> +               if (dev->flags & IFF_ALLMULTI) {
> +                       out_be32(&fec->gaddr1, 0xffffffff);
> +                       out_be32(&fec->gaddr2, 0xffffffff);
> +               } else {
> +                       u32 crc;
> +                       int i;
> +                       struct dev_mc_list *dmi;
> +                       u32 gaddr1 = 0x00000000;
> +                       u32 gaddr2 = 0x00000000;
> +
> +                       dmi = dev->mc_list;
> +                       for (i=0; i<dev->mc_count; i++) {
> +                               crc = ether_crc_le(6, dmi->dmi_addr) >> 26;
> +                               if (crc >= 32)
> +                                       gaddr1 |= 1 << (crc-32);
> +                               else
> +                                       gaddr2 |= 1 << crc;
> +                               dmi = dmi->next;
> +                       }
> +                       out_be32(&fec->gaddr1, gaddr1);
> +                       out_be32(&fec->gaddr2, gaddr2);
> +               }
> +       }
> +}
> +
> +/**
> + * mpc52xx_fec_hw_init
> + * @dev: network device
> + *
> + * Setup various hardware setting, only needed once on start
> + */
> +static void mpc52xx_fec_hw_init(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct mpc52xx_fec __iomem *fec = priv->fec;
> +       int i;
> +
> +       /* Whack a reset.  We should wait for this. */
> +       out_be32(&fec->ecntrl, FEC_ECNTRL_RESET);
> +       for (i = 0; i < FEC_RESET_DELAY; ++i) {
> +               if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0)
> +                       break;
> +               udelay(1);
> +       }
> +       if (i == FEC_RESET_DELAY)
> +               dev_err(&dev->dev, "FEC Reset timeout!\n");
> +
> +       /* set pause to 0x20 frames */
> +       out_be32(&fec->op_pause, FEC_OP_PAUSE_OPCODE | 0x20);
> +
> +       /* high service request will be deasserted when there's < 7 bytes in fifo
> +        * low service request will be deasserted when there's < 4*7 bytes in fifo
> +        */
> +       out_be32(&fec->rfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7);
> +       out_be32(&fec->tfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7);
> +
> +       /* alarm when <= x bytes in FIFO */
> +       out_be32(&fec->rfifo_alarm, 0x0000030c);
> +       out_be32(&fec->tfifo_alarm, 0x00000100);
> +
> +       /* begin transmittion when 256 bytes are in FIFO (or EOF or FIFO full) */
> +       out_be32(&fec->x_wmrk, FEC_FIFO_WMRK_256B);
> +
> +       /* enable crc generation */
> +       out_be32(&fec->xmit_fsm, FEC_XMIT_FSM_APPEND_CRC | FEC_XMIT_FSM_ENABLE_CRC);
> +       out_be32(&fec->iaddr1, 0x00000000);     /* No individual filter */
> +       out_be32(&fec->iaddr2, 0x00000000);     /* No individual filter */
> +
> +       /* set phy speed.
> +        * this can't be done in phy driver, since it needs to be called
> +        * before fec stuff (even on resume) */
> +       mpc52xx_fec_phy_hw_init(priv);
> +}
> +
> +/**
> + * mpc52xx_fec_start
> + * @dev: network device
> + *
> + * This function is called to start or restart the FEC during a link
> + * change.  This happens on fifo errors or when switching between half
> + * and full duplex.
> + */
> +static void mpc52xx_fec_start(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct mpc52xx_fec __iomem *fec = priv->fec;
> +       u32 rcntrl;
> +       u32 tcntrl;
> +       u32 tmp;
> +
> +       /* clear sticky error bits */
> +       tmp = FEC_FIFO_STATUS_ERR | FEC_FIFO_STATUS_UF | FEC_FIFO_STATUS_OF;
> +       out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status) & tmp);
> +       out_be32(&fec->tfifo_status, in_be32(&fec->tfifo_status) & tmp);
> +
> +       /* FIFOs will reset on mpc52xx_fec_enable */
> +       out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_ENABLE_IS_RESET);
> +
> +       /* Set station address. */
> +       mpc52xx_fec_set_paddr(dev, dev->dev_addr);
> +
> +       mpc52xx_fec_set_multicast_list(dev);
> +
> +       /* set max frame len, enable flow control, select mii mode */
> +       rcntrl = FEC_RX_BUFFER_SIZE << 16;      /* max frame length */
> +       rcntrl |= FEC_RCNTRL_FCE;
> +
> +       if (priv->has_phy)
> +               rcntrl |= FEC_RCNTRL_MII_MODE;
> +
> +       if (priv->duplex == DUPLEX_FULL)
> +               tcntrl = FEC_TCNTRL_FDEN;       /* FD enable */
> +       else {
> +               rcntrl |= FEC_RCNTRL_DRT;       /* disable Rx on Tx (HD) */
> +               tcntrl = 0;
> +       }
> +       out_be32(&fec->r_cntrl, rcntrl);
> +       out_be32(&fec->x_cntrl, tcntrl);
> +
> +       /* Clear any outstanding interrupt. */
> +       out_be32(&fec->ievent, 0xffffffff);
> +
> +       /* Enable interrupts we wish to service. */
> +       out_be32(&fec->imask, FEC_IMASK_ENABLE);
> +
> +       /* And last, enable the transmit and receive processing. */
> +       out_be32(&fec->ecntrl, FEC_ECNTRL_ETHER_EN);
> +       out_be32(&fec->r_des_active, 0x01000000);
> +
> +       priv->tx_full = 0;
> +}
> +
> +/**
> + * mpc52xx_fec_stop
> + * @dev: network device
> + *
> + * stop all activity on fec and empty dma buffers
> + */
> +static void mpc52xx_fec_stop(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct mpc52xx_fec __iomem *fec = priv->fec;
> +       unsigned long timeout;
> +
> +       /* disable all interrupts */
> +       out_be32(&fec->imask, 0);
> +
> +       /* Disable the rx task. */
> +       bcom_disable(priv->rx_dmatsk);
> +
> +       /* Wait for tx queue to drain, but only if we're in process context */
> +       if (!in_interrupt()) {
> +               timeout = jiffies + msecs_to_jiffies(2000);
> +               while (time_before(jiffies, timeout) &&
> +                               !bcom_queue_empty(priv->tx_dmatsk))
> +                       msleep(100);
> +
> +               if (time_after_eq(jiffies, timeout))
> +                       dev_err(&dev->dev, "queues didn't drain\n");
> +#if 1
> +               if (time_after_eq(jiffies, timeout)) {
> +                       dev_err(&dev->dev, "  tx: index: %i, outdex: %i\n",
> +                                       priv->tx_dmatsk->index,
> +                                       priv->tx_dmatsk->outdex);
> +                       dev_err(&dev->dev, "  rx: index: %i, outdex: %i\n",
> +                                       priv->rx_dmatsk->index,
> +                                       priv->rx_dmatsk->outdex);
> +               }
> +#endif
> +       }
> +
> +       bcom_disable(priv->tx_dmatsk);
> +
> +       /* Stop FEC */
> +       out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN);
> +
> +       return;
> +}
> +
> +/* reset fec and bestcomm tasks */
> +static void mpc52xx_fec_reset(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> +       mpc52xx_fec_stop(dev);
> +
> +       out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status));
> +       out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_RESET_FIFO);
> +
> +       mpc52xx_fec_free_rx_buffers(priv->rx_dmatsk);
> +
> +       mpc52xx_fec_hw_init(dev);
> +
> +       phy_stop(priv->phydev);
> +       phy_write(priv->phydev, MII_BMCR, BMCR_RESET);
> +       phy_start(priv->phydev);
> +
> +       bcom_fec_rx_reset(priv->rx_dmatsk);
> +       bcom_fec_tx_reset(priv->tx_dmatsk);
> +
> +       mpc52xx_fec_alloc_rx_buffers(priv->rx_dmatsk);
> +
> +       bcom_enable(priv->rx_dmatsk);
> +       bcom_enable(priv->tx_dmatsk);
> +
> +       mpc52xx_fec_start(dev);
> +}
> +
> +
> +/* ethtool interface */
> +static void mpc52xx_fec_get_drvinfo(struct net_device *dev,
> +               struct ethtool_drvinfo *info)
> +{
> +       strcpy(info->driver, DRIVER_NAME);
> +}
> +
> +static int mpc52xx_fec_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       return phy_ethtool_gset(priv->phydev, cmd);
> +}
> +
> +static int mpc52xx_fec_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       return phy_ethtool_sset(priv->phydev, cmd);
> +}
> +
> +static u32 mpc52xx_fec_get_msglevel(struct net_device *dev)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       return priv->msg_enable;
> +}
> +
> +static void mpc52xx_fec_set_msglevel(struct net_device *dev, u32 level)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +       priv->msg_enable = level;
> +}
> +
> +static const struct ethtool_ops mpc52xx_fec_ethtool_ops = {
> +       .get_drvinfo = mpc52xx_fec_get_drvinfo,
> +       .get_settings = mpc52xx_fec_get_settings,
> +       .set_settings = mpc52xx_fec_set_settings,
> +       .get_link = ethtool_op_get_link,
> +       .get_msglevel = mpc52xx_fec_get_msglevel,
> +       .set_msglevel = mpc52xx_fec_set_msglevel,
> +};
> +
> +
> +static int mpc52xx_fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
> +{
> +       struct mpc52xx_fec_priv *priv = netdev_priv(dev);
> +
> +       return mpc52xx_fec_phy_mii_ioctl(priv, if_mii(rq), cmd);
> +}
> +
> +/* ======================================================================== */
> +/* OF Driver                                                                */
> +/* ======================================================================== */
> +
> +static int __devinit
> +mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
> +{
> +       int rv;
> +       struct net_device *ndev;
> +       struct mpc52xx_fec_priv *priv = NULL;
> +       struct resource mem;
> +       const phandle *ph;
> +
> +       phys_addr_t rx_fifo;
> +       phys_addr_t tx_fifo;
> +
> +       /* Get the ether ndev & it's private zone */
> +       ndev = alloc_etherdev(sizeof(struct mpc52xx_fec_priv));
> +       if (!ndev)
> +               return -ENOMEM;
> +
> +       priv = netdev_priv(ndev);
> +
> +       /* Reserve FEC control zone */
> +       rv = of_address_to_resource(op->node, 0, &mem);
> +       if (rv) {
> +               printk(KERN_ERR DRIVER_NAME ": "
> +                               "Error while parsing device node resource\n" );
> +               return rv;
> +       }
> +       if ((mem.end - mem.start + 1) != sizeof(struct mpc52xx_fec)) {
> +               printk(KERN_ERR DRIVER_NAME
> +                       " - invalid resource size (%lx != %x), check mpc52xx_devices.c\n",
> +                       (unsigned long)(mem.end - mem.start + 1), sizeof(struct mpc52xx_fec));
> +               return -EINVAL;
> +       }
> +
> +       if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec), DRIVER_NAME))
> +               return -EBUSY;
> +
> +       /* Init ether ndev with what we have */
> +       ndev->open              = mpc52xx_fec_open;
> +       ndev->stop              = mpc52xx_fec_close;
> +       ndev->hard_start_xmit   = mpc52xx_fec_hard_start_xmit;
> +       ndev->do_ioctl          = mpc52xx_fec_ioctl;
> +       ndev->ethtool_ops       = &mpc52xx_fec_ethtool_ops;
> +       ndev->get_stats         = mpc52xx_fec_get_stats;
> +       ndev->set_mac_address   = mpc52xx_fec_set_mac_address;
> +       ndev->set_multicast_list = mpc52xx_fec_set_multicast_list;
> +       ndev->tx_timeout        = mpc52xx_fec_tx_timeout;
> +       ndev->watchdog_timeo    = FEC_WATCHDOG_TIMEOUT;
> +       ndev->flags &= ~IFF_RUNNING;
> +       ndev->base_addr         = mem.start;
> +
> +       priv->t_irq = priv->r_irq = ndev->irq = NO_IRQ; /* IRQ are free for now */
> +
> +       spin_lock_init(&priv->lock);
> +
> +       /* ioremap the zones */
> +       priv->fec = ioremap(mem.start, sizeof(struct mpc52xx_fec));
> +
> +       if (!priv->fec) {
> +               rv = -ENOMEM;
> +               goto probe_error;
> +       }
> +
> +       /* Bestcomm init */
> +       rx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, rfifo_data);
> +       tx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, tfifo_data);
> +
> +       priv->rx_dmatsk = bcom_fec_rx_init(FEC_RX_NUM_BD, rx_fifo, FEC_RX_BUFFER_SIZE);
> +       priv->tx_dmatsk = bcom_fec_tx_init(FEC_TX_NUM_BD, tx_fifo);
> +
> +       if (!priv->rx_dmatsk || !priv->tx_dmatsk) {
> +               printk(KERN_ERR DRIVER_NAME ": Can not init SDMA tasks\n" );
> +               rv = -ENOMEM;
> +               goto probe_error;
> +       }
> +
> +       /* Get the IRQ we need one by one */
> +               /* Control */
> +       ndev->irq = irq_of_parse_and_map(op->node, 0);
> +
> +               /* RX */
> +       priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk);
> +
> +               /* TX */
> +       priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk);
> +
> +       /* MAC address init */
> +       if (!is_zero_ether_addr(mpc52xx_fec_mac_addr))
> +               memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6);
> +       else
> +               mpc52xx_fec_get_paddr(ndev, ndev->dev_addr);
> +
> +       priv->msg_enable = (NETIF_MSG_IFUP << 1) - 1;
> +       priv->duplex = DUPLEX_FULL;
> +
> +       /* is the phy present in device tree? */
> +       ph = of_get_property(op->node, "phy-handle", NULL);
> +       if (ph) {
> +               const unsigned int *prop;
> +               struct device_node *phy_dn;
> +               priv->has_phy = 1;
> +
> +               phy_dn = of_find_node_by_phandle(*ph);
> +               prop = of_get_property(phy_dn, "reg", NULL);
> +               priv->phy_addr = *prop;
> +
> +               of_node_put(phy_dn);
> +
> +               /* Phy speed */
> +               priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1;
> +       } else {
> +               dev_info(&ndev->dev, "can't find \"phy-handle\" in device"
> +                               " tree, using 7-wire mode\n");
> +       }
> +
> +       /* Hardware init */
> +       mpc52xx_fec_hw_init(ndev);
> +
> +       mpc52xx_fec_reset_stats(ndev);
> +
> +       /* Register the new network device */
> +       rv = register_netdev(ndev);
> +       if (rv < 0)
> +               goto probe_error;
> +
> +       /* We're done ! */
> +       dev_set_drvdata(&op->dev, ndev);
> +
> +       return 0;
> +
> +
> +       /* Error handling - free everything that might be allocated */
> +probe_error:
> +
> +       irq_dispose_mapping(ndev->irq);
> +
> +       if (priv->rx_dmatsk)
> +               bcom_fec_rx_release(priv->rx_dmatsk);
> +       if (priv->tx_dmatsk)
> +               bcom_fec_tx_release(priv->tx_dmatsk);
> +
> +       if (priv->fec)
> +               iounmap(priv->fec);
> +
> +       release_mem_region(mem.start, sizeof(struct mpc52xx_fec));
> +
> +       free_netdev(ndev);
> +
> +       return rv;
> +}
> +
> +static int
> +mpc52xx_fec_remove(struct of_device *op)
> +{
> +       struct net_device *ndev;
> +       struct mpc52xx_fec_priv *priv;
> +
> +       ndev = dev_get_drvdata(&op->dev);
> +       if (!ndev)
> +               return 0;
> +       priv = netdev_priv(ndev);
> +
> +       unregister_netdev(ndev);
> +
> +       irq_dispose_mapping(ndev->irq);
> +
> +       bcom_fec_rx_release(priv->rx_dmatsk);
> +       bcom_fec_tx_release(priv->tx_dmatsk);
> +
> +       iounmap(priv->fec);
> +
> +       release_mem_region(ndev->base_addr, sizeof(struct mpc52xx_fec));
> +
> +       free_netdev(ndev);
> +
> +       dev_set_drvdata(&op->dev, NULL);
> +       return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state)
> +{
> +       struct net_device *dev = dev_get_drvdata(&op->dev);
> +
> +       if (netif_running(dev))
> +               mpc52xx_fec_close(dev);
> +
> +       return 0;
> +}
> +
> +static int mpc52xx_fec_of_resume(struct of_device *op)
> +{
> +       struct net_device *dev = dev_get_drvdata(&op->dev);
> +
> +       mpc52xx_fec_hw_init(dev);
> +       mpc52xx_fec_reset_stats(dev);
> +
> +       if (netif_running(dev))
> +               mpc52xx_fec_open(dev);
> +
> +       return 0;
> +}
> +#endif
> +
> +static struct of_device_id mpc52xx_fec_match[] = {
> +       {
> +               .type           = "network",
> +               .compatible     = "mpc5200-fec",
> +       },
> +       { }
> +};
> +
> +MODULE_DEVICE_TABLE(of, mpc52xx_fec_match);
> +
> +static struct of_platform_driver mpc52xx_fec_driver = {
> +       .owner          = THIS_MODULE,
> +       .name           = DRIVER_NAME,
> +       .match_table    = mpc52xx_fec_match,
> +       .probe          = mpc52xx_fec_probe,
> +       .remove         = mpc52xx_fec_remove,
> +#ifdef CONFIG_PM
> +       .suspend        = mpc52xx_fec_of_suspend,
> +       .resume         = mpc52xx_fec_of_resume,
> +#endif
> +};
> +
> +
> +/* ======================================================================== */
> +/* Module                                                                   */
> +/* ======================================================================== */
> +
> +static int __init
> +mpc52xx_fec_init(void)
> +{
> +#ifdef CONFIG_FEC_MPC52xx_MDIO
> +       int ret;
> +       ret = of_register_platform_driver(&mpc52xx_fec_mdio_driver);
> +       if (ret) {
> +               printk(KERN_ERR DRIVER_NAME ": failed to register mdio driver\n");
> +               return ret;
> +       }
> +#endif
> +       return of_register_platform_driver(&mpc52xx_fec_driver);
> +}
> +
> +static void __exit
> +mpc52xx_fec_exit(void)
> +{
> +       of_unregister_platform_driver(&mpc52xx_fec_driver);
> +#ifdef CONFIG_FEC_MPC52xx_MDIO
> +       of_unregister_platform_driver(&mpc52xx_fec_mdio_driver);
> +#endif
> +}
> +
> +
> +module_init(mpc52xx_fec_init);
> +module_exit(mpc52xx_fec_exit);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Dale Farnsworth");
> +MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC");
> Index: linux.git/drivers/net/fec_mpc52xx.h
> ===================================================================
> --- /dev/null
> +++ linux.git/drivers/net/fec_mpc52xx.h
> @@ -0,0 +1,315 @@
> +/*
> + * drivers/drivers/net/fec_mpc52xx/fec.h
> + *
> + * Driver for the MPC5200 Fast Ethernet Controller
> + *
> + * Author: Dale Farnsworth <dfarnsworth@mvista.com>
> + *
> + * 2003-2004 (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 __DRIVERS_NET_MPC52XX_FEC_H__
> +#define __DRIVERS_NET_MPC52XX_FEC_H__
> +
> +#include <linux/phy.h>
> +
> +/* Tunable constant */
> +/* FEC_RX_BUFFER_SIZE includes 4 bytes for CRC32 */
> +#define FEC_RX_BUFFER_SIZE     1522    /* max receive packet size */
> +#define FEC_RX_NUM_BD          256
> +#define FEC_TX_NUM_BD          64
> +
> +#define FEC_RESET_DELAY                50      /* uS */
> +
> +#define FEC_WATCHDOG_TIMEOUT   ((400*HZ)/1000)
> +
> +struct mpc52xx_fec_priv {
> +       int duplex;
> +       int tx_full;
> +       int r_irq;
> +       int t_irq;
> +       struct mpc52xx_fec __iomem *fec;
> +       struct bcom_task *rx_dmatsk;
> +       struct bcom_task *tx_dmatsk;
> +       spinlock_t lock;
> +       struct net_device_stats stats;
> +       int msg_enable;
> +
> +       int has_phy;
> +       unsigned int phy_speed;
> +       unsigned int phy_addr;
> +       struct phy_device *phydev;
> +       enum phy_state link;
> +       int speed;
> +};
> +
> +
> +/* ======================================================================== */
> +/* Hardware register sets & bits                                            */
> +/* ======================================================================== */
> +
> +struct mpc52xx_fec {
> +       u32 fec_id;                     /* FEC + 0x000 */
> +       u32 ievent;                     /* FEC + 0x004 */
> +       u32 imask;                      /* FEC + 0x008 */
> +
> +       u32 reserved0[1];               /* FEC + 0x00C */
> +       u32 r_des_active;               /* FEC + 0x010 */
> +       u32 x_des_active;               /* FEC + 0x014 */
> +       u32 r_des_active_cl;            /* FEC + 0x018 */
> +       u32 x_des_active_cl;            /* FEC + 0x01C */
> +       u32 ivent_set;                  /* FEC + 0x020 */
> +       u32 ecntrl;                     /* FEC + 0x024 */
> +
> +       u32 reserved1[6];               /* FEC + 0x028-03C */
> +       u32 mii_data;                   /* FEC + 0x040 */
> +       u32 mii_speed;                  /* FEC + 0x044 */
> +       u32 mii_status;                 /* FEC + 0x048 */
> +
> +       u32 reserved2[5];               /* FEC + 0x04C-05C */
> +       u32 mib_data;                   /* FEC + 0x060 */
> +       u32 mib_control;                /* FEC + 0x064 */
> +
> +       u32 reserved3[6];               /* FEC + 0x068-7C */
> +       u32 r_activate;                 /* FEC + 0x080 */
> +       u32 r_cntrl;                    /* FEC + 0x084 */
> +       u32 r_hash;                     /* FEC + 0x088 */
> +       u32 r_data;                     /* FEC + 0x08C */
> +       u32 ar_done;                    /* FEC + 0x090 */
> +       u32 r_test;                     /* FEC + 0x094 */
> +       u32 r_mib;                      /* FEC + 0x098 */
> +       u32 r_da_low;                   /* FEC + 0x09C */
> +       u32 r_da_high;                  /* FEC + 0x0A0 */
> +
> +       u32 reserved4[7];               /* FEC + 0x0A4-0BC */
> +       u32 x_activate;                 /* FEC + 0x0C0 */
> +       u32 x_cntrl;                    /* FEC + 0x0C4 */
> +       u32 backoff;                    /* FEC + 0x0C8 */
> +       u32 x_data;                     /* FEC + 0x0CC */
> +       u32 x_status;                   /* FEC + 0x0D0 */
> +       u32 x_mib;                      /* FEC + 0x0D4 */
> +       u32 x_test;                     /* FEC + 0x0D8 */
> +       u32 fdxfc_da1;                  /* FEC + 0x0DC */
> +       u32 fdxfc_da2;                  /* FEC + 0x0E0 */
> +       u32 paddr1;                     /* FEC + 0x0E4 */
> +       u32 paddr2;                     /* FEC + 0x0E8 */
> +       u32 op_pause;                   /* FEC + 0x0EC */
> +
> +       u32 reserved5[4];               /* FEC + 0x0F0-0FC */
> +       u32 instr_reg;                  /* FEC + 0x100 */
> +       u32 context_reg;                /* FEC + 0x104 */
> +       u32 test_cntrl;                 /* FEC + 0x108 */
> +       u32 acc_reg;                    /* FEC + 0x10C */
> +       u32 ones;                       /* FEC + 0x110 */
> +       u32 zeros;                      /* FEC + 0x114 */
> +       u32 iaddr1;                     /* FEC + 0x118 */
> +       u32 iaddr2;                     /* FEC + 0x11C */
> +       u32 gaddr1;                     /* FEC + 0x120 */
> +       u32 gaddr2;                     /* FEC + 0x124 */
> +       u32 random;                     /* FEC + 0x128 */
> +       u32 rand1;                      /* FEC + 0x12C */
> +       u32 tmp;                        /* FEC + 0x130 */
> +
> +       u32 reserved6[3];               /* FEC + 0x134-13C */
> +       u32 fifo_id;                    /* FEC + 0x140 */
> +       u32 x_wmrk;                     /* FEC + 0x144 */
> +       u32 fcntrl;                     /* FEC + 0x148 */
> +       u32 r_bound;                    /* FEC + 0x14C */
> +       u32 r_fstart;                   /* FEC + 0x150 */
> +       u32 r_count;                    /* FEC + 0x154 */
> +       u32 r_lag;                      /* FEC + 0x158 */
> +       u32 r_read;                     /* FEC + 0x15C */
> +       u32 r_write;                    /* FEC + 0x160 */
> +       u32 x_count;                    /* FEC + 0x164 */
> +       u32 x_lag;                      /* FEC + 0x168 */
> +       u32 x_retry;                    /* FEC + 0x16C */
> +       u32 x_write;                    /* FEC + 0x170 */
> +       u32 x_read;                     /* FEC + 0x174 */
> +
> +       u32 reserved7[2];               /* FEC + 0x178-17C */
> +       u32 fm_cntrl;                   /* FEC + 0x180 */
> +       u32 rfifo_data;                 /* FEC + 0x184 */
> +       u32 rfifo_status;               /* FEC + 0x188 */
> +       u32 rfifo_cntrl;                /* FEC + 0x18C */
> +       u32 rfifo_lrf_ptr;              /* FEC + 0x190 */
> +       u32 rfifo_lwf_ptr;              /* FEC + 0x194 */
> +       u32 rfifo_alarm;                /* FEC + 0x198 */
> +       u32 rfifo_rdptr;                /* FEC + 0x19C */
> +       u32 rfifo_wrptr;                /* FEC + 0x1A0 */
> +       u32 tfifo_data;                 /* FEC + 0x1A4 */
> +       u32 tfifo_status;               /* FEC + 0x1A8 */
> +       u32 tfifo_cntrl;                /* FEC + 0x1AC */
> +       u32 tfifo_lrf_ptr;              /* FEC + 0x1B0 */
> +       u32 tfifo_lwf_ptr;              /* FEC + 0x1B4 */
> +       u32 tfifo_alarm;                /* FEC + 0x1B8 */
> +       u32 tfifo_rdptr;                /* FEC + 0x1BC */
> +       u32 tfifo_wrptr;                /* FEC + 0x1C0 */
> +
> +       u32 reset_cntrl;                /* FEC + 0x1C4 */
> +       u32 xmit_fsm;                   /* FEC + 0x1C8 */
> +
> +       u32 reserved8[3];               /* FEC + 0x1CC-1D4 */
> +       u32 rdes_data0;                 /* FEC + 0x1D8 */
> +       u32 rdes_data1;                 /* FEC + 0x1DC */
> +       u32 r_length;                   /* FEC + 0x1E0 */
> +       u32 x_length;                   /* FEC + 0x1E4 */
> +       u32 x_addr;                     /* FEC + 0x1E8 */
> +       u32 cdes_data;                  /* FEC + 0x1EC */
> +       u32 status;                     /* FEC + 0x1F0 */
> +       u32 dma_control;                /* FEC + 0x1F4 */
> +       u32 des_cmnd;                   /* FEC + 0x1F8 */
> +       u32 data;                       /* FEC + 0x1FC */
> +
> +       u32 rmon_t_drop;                /* FEC + 0x200 */
> +       u32 rmon_t_packets;             /* FEC + 0x204 */
> +       u32 rmon_t_bc_pkt;              /* FEC + 0x208 */
> +       u32 rmon_t_mc_pkt;              /* FEC + 0x20C */
> +       u32 rmon_t_crc_align;           /* FEC + 0x210 */
> +       u32 rmon_t_undersize;           /* FEC + 0x214 */
> +       u32 rmon_t_oversize;            /* FEC + 0x218 */
> +       u32 rmon_t_frag;                /* FEC + 0x21C */
> +       u32 rmon_t_jab;                 /* FEC + 0x220 */
> +       u32 rmon_t_col;                 /* FEC + 0x224 */
> +       u32 rmon_t_p64;                 /* FEC + 0x228 */
> +       u32 rmon_t_p65to127;            /* FEC + 0x22C */
> +       u32 rmon_t_p128to255;           /* FEC + 0x230 */
> +       u32 rmon_t_p256to511;           /* FEC + 0x234 */
> +       u32 rmon_t_p512to1023;          /* FEC + 0x238 */
> +       u32 rmon_t_p1024to2047;         /* FEC + 0x23C */
> +       u32 rmon_t_p_gte2048;           /* FEC + 0x240 */
> +       u32 rmon_t_octets;              /* FEC + 0x244 */
> +       u32 ieee_t_drop;                /* FEC + 0x248 */
> +       u32 ieee_t_frame_ok;            /* FEC + 0x24C */
> +       u32 ieee_t_1col;                /* FEC + 0x250 */
> +       u32 ieee_t_mcol;                /* FEC + 0x254 */
> +       u32 ieee_t_def;                 /* FEC + 0x258 */
> +       u32 ieee_t_lcol;                /* FEC + 0x25C */
> +       u32 ieee_t_excol;               /* FEC + 0x260 */
> +       u32 ieee_t_macerr;              /* FEC + 0x264 */
> +       u32 ieee_t_cserr;               /* FEC + 0x268 */
> +       u32 ieee_t_sqe;                 /* FEC + 0x26C */
> +       u32 t_fdxfc;                    /* FEC + 0x270 */
> +       u32 ieee_t_octets_ok;           /* FEC + 0x274 */
> +
> +       u32 reserved9[2];               /* FEC + 0x278-27C */
> +       u32 rmon_r_drop;                /* FEC + 0x280 */
> +       u32 rmon_r_packets;             /* FEC + 0x284 */
> +       u32 rmon_r_bc_pkt;              /* FEC + 0x288 */
> +       u32 rmon_r_mc_pkt;              /* FEC + 0x28C */
> +       u32 rmon_r_crc_align;           /* FEC + 0x290 */
> +       u32 rmon_r_undersize;           /* FEC + 0x294 */
> +       u32 rmon_r_oversize;            /* FEC + 0x298 */
> +       u32 rmon_r_frag;                /* FEC + 0x29C */
> +       u32 rmon_r_jab;                 /* FEC + 0x2A0 */
> +
> +       u32 rmon_r_resvd_0;             /* FEC + 0x2A4 */
> +
> +       u32 rmon_r_p64;                 /* FEC + 0x2A8 */
> +       u32 rmon_r_p65to127;            /* FEC + 0x2AC */
> +       u32 rmon_r_p128to255;           /* FEC + 0x2B0 */
> +       u32 rmon_r_p256to511;           /* FEC + 0x2B4 */
> +       u32 rmon_r_p512to1023;          /* FEC + 0x2B8 */
> +       u32 rmon_r_p1024to2047;         /* FEC + 0x2BC */
> +       u32 rmon_r_p_gte2048;           /* FEC + 0x2C0 */
> +       u32 rmon_r_octets;              /* FEC + 0x2C4 */
> +       u32 ieee_r_drop;                /* FEC + 0x2C8 */
> +       u32 ieee_r_frame_ok;            /* FEC + 0x2CC */
> +       u32 ieee_r_crc;                 /* FEC + 0x2D0 */
> +       u32 ieee_r_align;               /* FEC + 0x2D4 */
> +       u32 r_macerr;                   /* FEC + 0x2D8 */
> +       u32 r_fdxfc;                    /* FEC + 0x2DC */
> +       u32 ieee_r_octets_ok;           /* FEC + 0x2E0 */
> +
> +       u32 reserved10[7];              /* FEC + 0x2E4-2FC */
> +
> +       u32 reserved11[64];             /* FEC + 0x300-3FF */
> +};
> +
> +#define        FEC_MIB_DISABLE                 0x80000000
> +
> +#define        FEC_IEVENT_HBERR                0x80000000
> +#define        FEC_IEVENT_BABR                 0x40000000
> +#define        FEC_IEVENT_BABT                 0x20000000
> +#define        FEC_IEVENT_GRA                  0x10000000
> +#define        FEC_IEVENT_TFINT                0x08000000
> +#define        FEC_IEVENT_MII                  0x00800000
> +#define        FEC_IEVENT_LATE_COL             0x00200000
> +#define        FEC_IEVENT_COL_RETRY_LIM        0x00100000
> +#define        FEC_IEVENT_XFIFO_UN             0x00080000
> +#define        FEC_IEVENT_XFIFO_ERROR          0x00040000
> +#define        FEC_IEVENT_RFIFO_ERROR          0x00020000
> +
> +#define        FEC_IMASK_HBERR                 0x80000000
> +#define        FEC_IMASK_BABR                  0x40000000
> +#define        FEC_IMASK_BABT                  0x20000000
> +#define        FEC_IMASK_GRA                   0x10000000
> +#define        FEC_IMASK_MII                   0x00800000
> +#define        FEC_IMASK_LATE_COL              0x00200000
> +#define        FEC_IMASK_COL_RETRY_LIM         0x00100000
> +#define        FEC_IMASK_XFIFO_UN              0x00080000
> +#define        FEC_IMASK_XFIFO_ERROR           0x00040000
> +#define        FEC_IMASK_RFIFO_ERROR           0x00020000
> +
> +/* all but MII, which is enabled separately */
> +#define FEC_IMASK_ENABLE       (FEC_IMASK_HBERR | FEC_IMASK_BABR | \
> +               FEC_IMASK_BABT | FEC_IMASK_GRA | FEC_IMASK_LATE_COL | \
> +               FEC_IMASK_COL_RETRY_LIM | FEC_IMASK_XFIFO_UN | \
> +               FEC_IMASK_XFIFO_ERROR | FEC_IMASK_RFIFO_ERROR)
> +
> +#define        FEC_RCNTRL_MAX_FL_SHIFT         16
> +#define        FEC_RCNTRL_LOOP                 0x01
> +#define        FEC_RCNTRL_DRT                  0x02
> +#define        FEC_RCNTRL_MII_MODE             0x04
> +#define        FEC_RCNTRL_PROM                 0x08
> +#define        FEC_RCNTRL_BC_REJ               0x10
> +#define        FEC_RCNTRL_FCE                  0x20
> +
> +#define        FEC_TCNTRL_GTS                  0x00000001
> +#define        FEC_TCNTRL_HBC                  0x00000002
> +#define        FEC_TCNTRL_FDEN                 0x00000004
> +#define        FEC_TCNTRL_TFC_PAUSE            0x00000008
> +#define        FEC_TCNTRL_RFC_PAUSE            0x00000010
> +
> +#define        FEC_ECNTRL_RESET                0x00000001
> +#define        FEC_ECNTRL_ETHER_EN             0x00000002
> +
> +#define FEC_MII_DATA_ST                        0x40000000      /* Start frame */
> +#define FEC_MII_DATA_OP_RD             0x20000000      /* Perform read */
> +#define FEC_MII_DATA_OP_WR             0x10000000      /* Perform write */
> +#define FEC_MII_DATA_PA_MSK            0x0f800000      /* PHY Address mask */
> +#define FEC_MII_DATA_RA_MSK            0x007c0000      /* PHY Register mask */
> +#define FEC_MII_DATA_TA                        0x00020000      /* Turnaround */
> +#define FEC_MII_DATA_DATAMSK           0x0000ffff      /* PHY data mask */
> +
> +#define FEC_MII_READ_FRAME     (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA)
> +#define FEC_MII_WRITE_FRAME    (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR | FEC_MII_DATA_TA)
> +
> +#define FEC_MII_DATA_RA_SHIFT          0x12            /* MII reg addr bits */
> +#define FEC_MII_DATA_PA_SHIFT          0x17            /* MII PHY addr bits */
> +
> +#define FEC_PADDR2_TYPE                        0x8808
> +
> +#define FEC_OP_PAUSE_OPCODE            0x00010000
> +
> +#define FEC_FIFO_WMRK_256B             0x3
> +
> +#define FEC_FIFO_STATUS_ERR            0x00400000
> +#define FEC_FIFO_STATUS_UF             0x00200000
> +#define FEC_FIFO_STATUS_OF             0x00100000
> +
> +#define FEC_FIFO_CNTRL_FRAME           0x08000000
> +#define FEC_FIFO_CNTRL_LTG_7           0x07000000
> +
> +#define FEC_RESET_CNTRL_RESET_FIFO     0x02000000
> +#define FEC_RESET_CNTRL_ENABLE_IS_RESET        0x01000000
> +
> +#define FEC_XMIT_FSM_APPEND_CRC                0x02000000
> +#define FEC_XMIT_FSM_ENABLE_CRC                0x01000000
> +
> +
> +extern struct of_platform_driver mpc52xx_fec_mdio_driver;
> +
> +#endif /* __DRIVERS_NET_MPC52XX_FEC_H__ */
> Index: linux.git/drivers/net/fec_mpc52xx_phy.c
> ===================================================================
> --- /dev/null
> +++ linux.git/drivers/net/fec_mpc52xx_phy.c
> @@ -0,0 +1,198 @@
> +/*
> + * Driver for the MPC5200 Fast Ethernet Controller - MDIO bus driver
> + *
> + * Copyright (C) 2007  Domen Puncer, Telargo, 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 <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/netdevice.h>
> +#include <linux/phy.h>
> +#include <linux/of_platform.h>
> +#include <asm/io.h>
> +#include <asm/mpc52xx.h>
> +#include "fec_mpc52xx.h"
> +
> +struct mpc52xx_fec_mdio_priv {
> +       struct mpc52xx_fec __iomem *regs;
> +};
> +
> +static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg)
> +{
> +       struct mpc52xx_fec_mdio_priv *priv = bus->priv;
> +       struct mpc52xx_fec __iomem *fec;
> +       int tries = 100;
> +       u32 request = FEC_MII_READ_FRAME;
> +
> +       fec = priv->regs;
> +       out_be32(&fec->ievent, FEC_IEVENT_MII);
> +
> +       request |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
> +       request |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
> +
> +       out_be32(&priv->regs->mii_data, request);
> +
> +       /* wait for it to finish, this takes about 23 us on lite5200b */
> +       while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries)
> +               udelay(5);
> +
> +       if (tries == 0)
> +               return -ETIMEDOUT;
> +
> +       return in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK;
> +}
> +
> +static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 data)
> +{
> +       struct mpc52xx_fec_mdio_priv *priv = bus->priv;
> +       struct mpc52xx_fec __iomem *fec;
> +       u32 value = data;
> +       int tries = 100;
> +
> +       fec = priv->regs;
> +       out_be32(&fec->ievent, FEC_IEVENT_MII);
> +
> +       value |= FEC_MII_WRITE_FRAME;
> +       value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
> +       value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
> +
> +       out_be32(&priv->regs->mii_data, value);
> +
> +       /* wait for request to finish */
> +       while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries)
> +               udelay(5);
> +
> +       if (tries == 0)
> +               return -ETIMEDOUT;
> +
> +       return 0;
> +}
> +
> +static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_id *match)
> +{
> +       struct device *dev = &of->dev;
> +       struct device_node *np = of->node;
> +       struct device_node *child = NULL;
> +       struct mii_bus *bus;
> +       struct mpc52xx_fec_mdio_priv *priv;
> +       struct resource res = {};
> +       int err;
> +       int i;
> +
> +       bus = kzalloc(sizeof(*bus), GFP_KERNEL);
> +       if (bus == NULL)
> +               return -ENOMEM;
> +       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +       if (priv == NULL) {
> +               err = -ENOMEM;
> +               goto out_free;
> +       }
> +
> +       bus->name = "mpc52xx MII bus";
> +       bus->read = mpc52xx_fec_mdio_read;
> +       bus->write = mpc52xx_fec_mdio_write;
> +
> +       /* setup irqs */
> +       bus->irq = kmalloc(sizeof(bus->irq[0]) * PHY_MAX_ADDR, GFP_KERNEL);
> +       if (bus->irq == NULL) {
> +               err = -ENOMEM;
> +               goto out_free;
> +       }
> +       for (i=0; i<PHY_MAX_ADDR; i++)
> +               bus->irq[i] = PHY_POLL;
> +
> +       while ((child = of_get_next_child(np, child)) != NULL) {
> +               int irq = irq_of_parse_and_map(child, 0);
> +               if (irq != NO_IRQ) {
> +                       const u32 *id = of_get_property(child, "reg", NULL);
> +                       bus->irq[*id] = irq;
> +               }
> +       }
> +
> +       /* setup registers */
> +       err = of_address_to_resource(np, 0, &res);
> +       if (err)
> +               goto out_free;
> +       priv->regs = ioremap(res.start, res.end - res.start + 1);
> +       if (priv->regs == NULL) {
> +               err = -ENOMEM;
> +               goto out_free;
> +       }
> +
> +       bus->id = res.start;
> +       bus->priv = priv;
> +
> +       bus->dev = dev;
> +       dev_set_drvdata(dev, bus);
> +
> +       /* set MII speed */
> +       out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1);
> +
> +       /* enable MII interrupt */
> +       out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII);
> +
> +       err = mdiobus_register(bus);
> +       if (err)
> +               goto out_unmap;
> +
> +       return 0;
> +
> + out_unmap:
> +       iounmap(priv->regs);
> + out_free:
> +       for (i=0; i<PHY_MAX_ADDR; i++)
> +               if (bus->irq[i] != PHY_POLL)
> +                       irq_dispose_mapping(bus->irq[i]);
> +       kfree(bus->irq);
> +       kfree(priv);
> +       kfree(bus);
> +
> +       return err;
> +}
> +
> +static int mpc52xx_fec_mdio_remove(struct of_device *of)
> +{
> +       struct device *dev = &of->dev;
> +       struct mii_bus *bus = dev_get_drvdata(dev);
> +       struct mpc52xx_fec_mdio_priv *priv = bus->priv;
> +       int i;
> +
> +       mdiobus_unregister(bus);
> +       dev_set_drvdata(dev, NULL);
> +
> +       iounmap(priv->regs);
> +       for (i=0; i<PHY_MAX_ADDR; i++)
> +               if (bus->irq[i])
> +                       irq_dispose_mapping(bus->irq[i]);
> +       kfree(priv);
> +       kfree(bus->irq);
> +       kfree(bus);
> +
> +       return 0;
> +}
> +
> +
> +static struct of_device_id mpc52xx_fec_mdio_match[] = {
> +       {
> +               .type = "mdio",
> +               .compatible = "mpc5200b-fec-phy",
> +       },
> +       {},
> +};
> +
> +struct of_platform_driver mpc52xx_fec_mdio_driver = {
> +       .name = "mpc5200b-fec-phy",
> +       .probe = mpc52xx_fec_mdio_probe,
> +       .remove = mpc52xx_fec_mdio_remove,
> +       .match_table = mpc52xx_fec_mdio_match,
> +};
> +
> +/* let fec driver call it, since this has to be registered before it */
> +EXPORT_SYMBOL_GPL(mpc52xx_fec_mdio_driver);
> +
> +
> +MODULE_LICENSE("Dual BSD/GPL");
>


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

^ permalink raw reply

* Re: [PATCH v2 2/4] [POWERPC] Update device tree binding for mpc5200 gpt
From: Grant Likely @ 2007-10-21 17:25 UTC (permalink / raw)
  To: Marian Balakowicz; +Cc: linuxppc-dev
In-Reply-To: <fa686aa40710210954v3337e82cnf14a487427ecfccc@mail.gmail.com>

On 10/21/07, Grant Likely <grant.likely@secretlab.ca> wrote:
> On 10/18/07, Marian Balakowicz <m8@semihalf.com> wrote:
> > Add 'fsl,' prefix to 'compatible' property for gpt nodes.
> > Add 'fsl,' prefix to empty, GPT0 specific 'has-wdt' property.
>
> Patch doesn't apply; mpc5200_wdt.c watchdog driver is not in the
> kernel.  I'll pick up the dts change, but you'll need to coordinate w/
> Domen to get the needed changes into his driver before it's picked for
> mainline.

Oops, it is there; drivers/char/watchdog has been moved to
drivers/watchdog, so the patch didn't apply.  I'll fix this up.

Cheers,
g.

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

^ permalink raw reply

* Re: [PATCH] mpc5200: /dev/watchdog driver for GPT0
From: Grant Likely @ 2007-10-21 17:24 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded
In-Reply-To: <20071021171436.GA1466@nd47.coderock.org>

On 10/21/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> On 21/10/07 10:55 -0600, Grant Likely wrote:
> > On 6/13/07, Kumar Gala <galak@kernel.crashing.org> wrote:
> > >
> > > On Jun 12, 2007, at 3:59 AM, Domen Puncer wrote:
> > >
> > > > Driver for internal mpc5200 watchdog on general purpose timer 0.
> > > > For IPB clock of 132 MHz the maximum timeout is about 32 seconds.
> > > >
> > > >
> > > > Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
> > >
> > > Should really be submitted to the watchdog maintainer if you want
> > > this in the kernel
> >
> > Domen, are you going to respin this patch and submit it to the
> > watchdog maintainer?
>
> Uhm... checked drivers/char/watchdog/ lately? ;-)

Hmmm, I checked it just before I wrote that email...  I missed that
drivers/char/watchdog has been moved to drivers/watchdog which is why
I couldn't find the driver.  :-)

Oops,
g.

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

^ permalink raw reply

* Re: [PATCH] mpc5200: /dev/watchdog driver for GPT0
From: Domen Puncer @ 2007-10-21 17:14 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-embedded
In-Reply-To: <fa686aa40710210955v14de2e78g88bf8c0d74482176@mail.gmail.com>

On 21/10/07 10:55 -0600, Grant Likely wrote:
> On 6/13/07, Kumar Gala <galak@kernel.crashing.org> wrote:
> >
> > On Jun 12, 2007, at 3:59 AM, Domen Puncer wrote:
> >
> > > Driver for internal mpc5200 watchdog on general purpose timer 0.
> > > For IPB clock of 132 MHz the maximum timeout is about 32 seconds.
> > >
> > >
> > > Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
> >
> > Should really be submitted to the watchdog maintainer if you want
> > this in the kernel
> 
> Domen, are you going to respin this patch and submit it to the
> watchdog maintainer?

Uhm... checked drivers/char/watchdog/ lately? ;-)


	Domen

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

-- 
Domen Puncer | Research & Development
.............................................................................................
Telargo d.o.o. | Zagrebška cesta 20 | 2000 Maribor | Slovenia
.............................................................................................
www.telargo.com

^ permalink raw reply

* Re: [PATCH] mpc5200: /dev/watchdog driver for GPT0
From: Grant Likely @ 2007-10-21 16:55 UTC (permalink / raw)
  To: Kumar Gala; +Cc: Domen Puncer, linuxppc-embedded
In-Reply-To: <ECDF5931-F264-4083-B4F0-C8CA1976195A@kernel.crashing.org>

On 6/13/07, Kumar Gala <galak@kernel.crashing.org> wrote:
>
> On Jun 12, 2007, at 3:59 AM, Domen Puncer wrote:
>
> > Driver for internal mpc5200 watchdog on general purpose timer 0.
> > For IPB clock of 132 MHz the maximum timeout is about 32 seconds.
> >
> >
> > Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
>
> Should really be submitted to the watchdog maintainer if you want
> this in the kernel

Domen, are you going to respin this patch and submit it to the
watchdog maintainer?

Cheers,
g.

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

^ permalink raw reply

* Re: [PATCH v2 2/4] [POWERPC] Update device tree binding for mpc5200 gpt
From: Grant Likely @ 2007-10-21 16:54 UTC (permalink / raw)
  To: Marian Balakowicz; +Cc: linuxppc-dev
In-Reply-To: <20071018184424.3584.77643.stgit@hekate.izotz.org>

On 10/18/07, Marian Balakowicz <m8@semihalf.com> wrote:
> Add 'fsl,' prefix to 'compatible' property for gpt nodes.
> Add 'fsl,' prefix to empty, GPT0 specific 'has-wdt' property.

Patch doesn't apply; mpc5200_wdt.c watchdog driver is not in the
kernel.  I'll pick up the dts change, but you'll need to coordinate w/
Domen to get the needed changes into his driver before it's picked for
mainline.

Cheers,
g.

>
> Signed-off-by: Marian Balakowicz <m8@semihalf.com>
> ---
>
>  .../powerpc/mpc52xx-device-tree-bindings.txt       |    4 ++-
>  arch/powerpc/boot/dts/lite5200.dts                 |   26 +++++++-------------
>  arch/powerpc/boot/dts/lite5200b.dts                |   26 +++++++-------------
>  drivers/char/watchdog/mpc5200_wdt.c                |    3 ++
>  4 files changed, 23 insertions(+), 36 deletions(-)
>
>
> diff --git a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
> index e59fcbb..fedf7ef 100644
> --- a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
> +++ b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
> @@ -185,7 +185,7 @@ bestcomm@<addr>     dma-controller          mpc5200-bestcomm 5200 pic also requires
>  Recommended soc5200 child nodes; populate as needed for your board
>  name           device_type     compatible        Description
>  ----           -----------     ----------        -----------
> -gpt@<addr>     gpt             mpc5200-gpt       General purpose timers
> +gpt@<addr>     gpt             fsl,mpc5200-gpt   General purpose timers
>  rtc@<addr>     rtc             mpc5200-rtc       Real time clock
>  mscan@<addr>   mscan           mpc5200-mscan     CAN bus controller
>  pci@<addr>     pci             mpc5200-pci       PCI bridge
> @@ -213,7 +213,7 @@ cell-index  int             When multiple devices are present, is the
>  5) General Purpose Timer nodes (child of soc5200 node)
>  On the mpc5200 and 5200b, GPT0 has a watchdog timer function.  If the board
>  design supports the internal wdt, then the device node for GPT0 should
> -include the empty property 'has-wdt'.
> +include the empty property 'fsl,has-wdt'.
>
>  6) PSC nodes (child of soc5200 node)
>  PSC nodes can define the optional 'port-number' property to force assignment
> diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
> index bc45f5f..6731763 100644
> --- a/arch/powerpc/boot/dts/lite5200.dts
> +++ b/arch/powerpc/boot/dts/lite5200.dts
> @@ -70,18 +70,16 @@
>                 };
>
>                 gpt@600 {       // General Purpose Timer
> -                       compatible = "mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200-gpt";
>                         cell-index = <0>;
>                         reg = <600 10>;
>                         interrupts = <1 9 0>;
>                         interrupt-parent = <&mpc5200_pic>;
> -                       has-wdt;
> +                       fsl,has-wdt;
>                 };
>
>                 gpt@610 {       // General Purpose Timer
> -                       compatible = "mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200-gpt";
>                         cell-index = <1>;
>                         reg = <610 10>;
>                         interrupts = <1 a 0>;
> @@ -89,8 +87,7 @@
>                 };
>
>                 gpt@620 {       // General Purpose Timer
> -                       compatible = "mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200-gpt";
>                         cell-index = <2>;
>                         reg = <620 10>;
>                         interrupts = <1 b 0>;
> @@ -98,8 +95,7 @@
>                 };
>
>                 gpt@630 {       // General Purpose Timer
> -                       compatible = "mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200-gpt";
>                         cell-index = <3>;
>                         reg = <630 10>;
>                         interrupts = <1 c 0>;
> @@ -107,8 +103,7 @@
>                 };
>
>                 gpt@640 {       // General Purpose Timer
> -                       compatible = "mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200-gpt";
>                         cell-index = <4>;
>                         reg = <640 10>;
>                         interrupts = <1 d 0>;
> @@ -116,8 +111,7 @@
>                 };
>
>                 gpt@650 {       // General Purpose Timer
> -                       compatible = "mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200-gpt";
>                         cell-index = <5>;
>                         reg = <650 10>;
>                         interrupts = <1 e 0>;
> @@ -125,8 +119,7 @@
>                 };
>
>                 gpt@660 {       // General Purpose Timer
> -                       compatible = "mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200-gpt";
>                         cell-index = <6>;
>                         reg = <660 10>;
>                         interrupts = <1 f 0>;
> @@ -134,8 +127,7 @@
>                 };
>
>                 gpt@670 {       // General Purpose Timer
> -                       compatible = "mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200-gpt";
>                         cell-index = <7>;
>                         reg = <670 10>;
>                         interrupts = <1 10 0>;
> diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
> index 6582c9a..b540388 100644
> --- a/arch/powerpc/boot/dts/lite5200b.dts
> +++ b/arch/powerpc/boot/dts/lite5200b.dts
> @@ -70,18 +70,16 @@
>                 };
>
>                 gpt@600 {       // General Purpose Timer
> -                       compatible = "mpc5200b-gpt","mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
>                         cell-index = <0>;
>                         reg = <600 10>;
>                         interrupts = <1 9 0>;
>                         interrupt-parent = <&mpc5200_pic>;
> -                       has-wdt;
> +                       fsl,has-wdt;
>                 };
>
>                 gpt@610 {       // General Purpose Timer
> -                       compatible = "mpc5200b-gpt","mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
>                         cell-index = <1>;
>                         reg = <610 10>;
>                         interrupts = <1 a 0>;
> @@ -89,8 +87,7 @@
>                 };
>
>                 gpt@620 {       // General Purpose Timer
> -                       compatible = "mpc5200b-gpt","mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
>                         cell-index = <2>;
>                         reg = <620 10>;
>                         interrupts = <1 b 0>;
> @@ -98,8 +95,7 @@
>                 };
>
>                 gpt@630 {       // General Purpose Timer
> -                       compatible = "mpc5200b-gpt","mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
>                         cell-index = <3>;
>                         reg = <630 10>;
>                         interrupts = <1 c 0>;
> @@ -107,8 +103,7 @@
>                 };
>
>                 gpt@640 {       // General Purpose Timer
> -                       compatible = "mpc5200b-gpt","mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
>                         cell-index = <4>;
>                         reg = <640 10>;
>                         interrupts = <1 d 0>;
> @@ -116,8 +111,7 @@
>                 };
>
>                 gpt@650 {       // General Purpose Timer
> -                       compatible = "mpc5200b-gpt","mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
>                         cell-index = <5>;
>                         reg = <650 10>;
>                         interrupts = <1 e 0>;
> @@ -125,8 +119,7 @@
>                 };
>
>                 gpt@660 {       // General Purpose Timer
> -                       compatible = "mpc5200b-gpt","mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
>                         cell-index = <6>;
>                         reg = <660 10>;
>                         interrupts = <1 f 0>;
> @@ -134,8 +127,7 @@
>                 };
>
>                 gpt@670 {       // General Purpose Timer
> -                       compatible = "mpc5200b-gpt","mpc5200-gpt";
> -                       device_type = "gpt";
> +                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
>                         cell-index = <7>;
>                         reg = <670 10>;
>                         interrupts = <1 10 0>;
> diff --git a/drivers/char/watchdog/mpc5200_wdt.c b/drivers/char/watchdog/mpc5200_wdt.c
> index 9cfb975..11f6a11 100644
> --- a/drivers/char/watchdog/mpc5200_wdt.c
> +++ b/drivers/char/watchdog/mpc5200_wdt.c
> @@ -176,6 +176,8 @@ static int mpc5200_wdt_probe(struct of_device *op, const struct of_device_id *ma
>
>         has_wdt = of_get_property(op->node, "has-wdt", NULL);
>         if (!has_wdt)
> +               has_wdt = of_get_property(op->node, "fsl,has-wdt", NULL);
> +       if (!has_wdt)
>                 return -ENODEV;
>
>         wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
> @@ -254,6 +256,7 @@ static int mpc5200_wdt_shutdown(struct of_device *op)
>
>  static struct of_device_id mpc5200_wdt_match[] = {
>         { .compatible = "mpc5200-gpt", },
> +       { .compatible = "fsl,mpc5200-gpt", },
>         {},
>  };
>  static struct of_platform_driver mpc5200_wdt_driver = {
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>


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

^ permalink raw reply

* Re: Device trees and audio codecs
From: Jon Smirl @ 2007-10-21 14:01 UTC (permalink / raw)
  To: Timur Tabi; +Cc: PowerPC dev list
In-Reply-To: <471B550F.3090907@freescale.com>

On 10/21/07, Timur Tabi <timur@freescale.com> wrote:
> > For development purposes I'm using an Efika as a target platform. It
> > is easy enough to load the i2s driver using the device tree. I can add
> > entries to the i2s node to trigger loading of the generic sta9766
> > codec driver. How do I trigger loading the Efika specific fabric
> > driver?
>
> You don't need a device tree entry to trigger loading a driver.  You can just
> load the driver and initialize it in its __init function.
>
> However, in this case, you might want to do what I'm doing -- putting a probe
> function in the fabric driver for the i2s device (which gets its own node
> under the SOC node), and then in that probe function search for all the other
> nodes that you need.

Doing it that way will make the kernel specific to the target device.
Currently I can load the same mpc5200 kernel on several different
target devices since the platform specific code is triggered in the
probe machine phase.

I tried making the fabric driver into a platform driver instead of an
openfirmware driver, but the mpc5200 code is not initializing platform
drivers correctly.

I could insert calls into arch/powerpc/platforms/52xx/whatever to load
the specific asoc fabric, but doing that is a mess. There must be a
way to trigger loading of machine specific drivers

> Since the Apple audio drivers are not ASoC drivers, I suggest we don't pay
> attention to what they do.

Those Apple drivers are very similar to asoc drivers. They could
easily be folded into the asoc code.


-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply

* mpc 860 boot linux2.6.23 problem
From: keng_629 @ 2007-10-21 13:43 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <200710190724253750363@126.com>

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


the problem has solved ,it is the serial cpm dug,but i don't know where it is.
i used the denx linux tree,it works fine,thank you for you help.
thank you




keng_629
2007-10-19



发件人: Scott Wood
发送时间: 2007-10-18 01:32:05
收件人: Dan Malek
抄送: linuxppc-embedded@ozlabs.org
主题: Re: mpc 860 boot linux2.6.23 problem

Dan  Malek  wrote:
>  
>  On  Oct  17,  2007,  at  11:31  AM,  Scott  Wood  wrote:
>  
> >  I  just  pulled  Wolfgang's  latest  u-boot  tree,  and  I  don't  see  any  fdt  
> >  or  ft_  calls  in  cpu/mpc8xx,  nor  in  any  8xx  board  that  I  recognize.
>  
>  The  STx  XTc  885  is  supported  and  was  used  for
>  a  majority  of  the  FT  development  in  u-boot.    I
>  just  built  it  a  few  months  ago,  it  worked  fine,  so
>  if  it  isn't  working  today  the  changes  should  be
>  minimal  to  bring  it  up  to  date.

OK,  that  wasn't  a  board  I  recognized.  :-P

Still,  most  8xx  boards  are  not  yet  converted  AFAICT.    Not  that  it'd  be  
hard  to  do  so,  but  it  might  be  a  bit  misleading  to  say  "upgrade  u-boot  
and  get  device  tree  support".  :-)

-Scott
_______________________________________________
Linuxppc-embedded  mailing  list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

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

^ permalink raw reply

* Re: Device trees and audio codecs
From: Timur Tabi @ 2007-10-21 13:33 UTC (permalink / raw)
  To: Jon Smirl; +Cc: PowerPC dev list
In-Reply-To: <9e4733910710200833x5d1c55b5l2cd400f77c13ec87@mail.gmail.com>

Jon Smirl wrote:
> I'm working on ALSA ASoC support for a codec chip on my mpc5200 based
> target hardware. How should the codec be represented in the device
> tree?

I'm also working on an ASoC driver, but for the 8610.  I have a similar problem.

> Under ASoC the device drivers for the codec chips are platform
> independent.  In the current ASoC model there are three device
> drivers: i2s (or spi, etc), the generic codec, and a platform specific
> 'fabric' driver.  Some codecs are linked to both i2c and i2s.

Annoying, isn't it? :-)

You can use phandles to cross-reference nodes.  I suggest putting the codec 
node under the i2s node (and containing I2S-specific information), and then 
putting another codec node under the i2c node (this is a new layout proposed 
by Scott Wood), and use a phandle to let the i2s-codec node point to the 
i2c-codec node.

> The fabric driver corresponds to the 'layout-id' in the Apple model.
> It tells how to configure the generic codec driver for the specific
> configuration needed by the actual platform hardware.
> 
> For development purposes I'm using an Efika as a target platform. It
> is easy enough to load the i2s driver using the device tree. I can add
> entries to the i2s node to trigger loading of the generic sta9766
> codec driver. How do I trigger loading the Efika specific fabric
> driver?

You don't need a device tree entry to trigger loading a driver.  You can just 
load the driver and initialize it in its __init function.

However, in this case, you might want to do what I'm doing -- putting a probe 
function in the fabric driver for the i2s device (which gets its own node 
under the SOC node), and then in that probe function search for all the other 
nodes that you need.

> My target hardware has a codec that is linked to both i2s and i2c. How
> should it be represented?
> 
> Apple has three entries. One for i2s, one for the codec, and one for
> soundchip. What is the soundchip entry, does it correspond to real
> hardware?

Since the Apple audio drivers are not ASoC drivers, I suggest we don't pay 
attention to what they do.

-- 
Timur Tabi
Linux Kernel Developer @ Freescale

^ permalink raw reply


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