LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] pasemi_dma: Driver for PA Semi PWRficient on-chip DMA engine
From: Olof Johansson @ 2008-03-11 14:25 UTC (permalink / raw)
  To: Andrew Morton
  Cc: hskinnemoen, shannon.nelson, linux-kernel, linuxppc-dev,
	pasemi-linux, dan.j.williams
In-Reply-To: <20080311000619.ba39311f.akpm@linux-foundation.org>

On Tue, Mar 11, 2008 at 12:06:19AM -0700, Andrew Morton wrote:
> On Thu, 6 Mar 2008 17:39:00 -0600 Olof Johansson <olof@lixom.net> wrote:
> 
> > pasemi_dma: Driver for PA Semi PWRficient on-chip DMA engine
> >     
> > First cut at a dma copy offload driver for PA Semi PWRficient. It uses the
> > platform-specific functions to allocate channels, etc.
> 
> Applied this on Paul's latest and powerpc allmodconfig goes boom.

It's dependent on my latest pull request of pasemi.git for-2.6.26 that
Paul hasn't pulled/pushed yet.

> drivers/dma/pasemi_dma.c: In function `pasemi_dma_alloc_chan_resources':
> drivers/dma/pasemi_dma.c:152: error: `PAS_DMA_TXCHAN_CFG_TY_COPY' undeclared (first use in this function)
> drivers/dma/pasemi_dma.c:152: error: (Each undeclared identifier is reported only once
> drivers/dma/pasemi_dma.c:152: error: for each function it appears in.)
> drivers/dma/pasemi_dma.c:154: error: `PAS_DMA_TXCHAN_CFG_LPDQ' undeclared (first use in this function)
> drivers/dma/pasemi_dma.c:155: error: `PAS_DMA_TXCHAN_CFG_LPSQ' undeclared (first use in this function)
> drivers/dma/pasemi_dma.c: In function `pasemi_dma_probe':
> drivers/dma/pasemi_dma.c:394: error: structure has no member named `device_dependency_added'

.. and that one is caused by recent changes in async_tx.git. I was
waiting on other review comments from the DMA maintainers before
resubmitting; timer has expired though and I'll do it anyway today.

> Also this driver from git-md-accel is pretty sick:
> 
> 
> drivers/dma/fsldma.c:439: warning: comparison of distinct pointer types lacks a cast
> drivers/dma/fsldma.c: In function `fsl_chan_xfer_ld_queue':
> drivers/dma/fsldma.c:584: warning: long long unsigned int format, dma_addr_t arg (arg 4)
> drivers/dma/fsldma.c: In function `fsl_dma_chan_do_interrupt':
> drivers/dma/fsldma.c:661: warning: unsigned int format, different type arg (arg 5)
> drivers/dma/fsldma.c:677: warning: long long unsigned int format, dma_addr_t arg (arg 4)
> drivers/dma/fsldma.c:677: warning: long long unsigned int format, dma_addr_t arg (arg 5)
> drivers/dma/fsldma.c:694: warning: unsigned int format, different type arg (arg 4)
> drivers/dma/fsldma.c: In function `fsl_dma_self_test':
> drivers/dma/fsldma.c:833: warning: int format, different type arg (arg 5)
> drivers/dma/fsldma.c: In function `of_fsl_dma_probe':
> drivers/dma/fsldma.c:1003: warning: unsigned int format, different type arg (arg 5)
> drivers/dma/fsldma.c: At top level:
> drivers/dma/fsldma.c:723: warning: 'fsl_dma_callback_test' defined but not used

Yeah, Zhang Wei posted a patch for that on lkml yesterday.


-Olof

^ permalink raw reply

* Help needed to describe a custom bus in the device tree
From: Laurent Pinchart @ 2008-03-11 14:27 UTC (permalink / raw)
  To: linuxppc-dev

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

Hi everybody,

the migration process from ARCH=ppc to ARCH=powerpc is easier than I thought 
in some parts, but a few devices are still giving me headaches. This should 
hopefully be one of my last major requests for help (I'm sure most of you 
will be happy to see traffic on this list going down when I'll be done :-))

I'm having trouble describing a custom bus named MS bus (completely unrelated 
to a well-known software company) in the device tree. The hardware is 
MPC8248-based and has the following hardware topology.

MPC8248 <-- localbus --> FPGA <-- ms bus --> Custom peripherals

The bus interrupt controller, serial access (SPI) controller and status 
registers are accessed through memory-mapped registers in the FPGA. Parallel 
access to the MS bus is handled transparently by the FPGA which handles 
address mapping.

The FPGA is mapped on the locabus at address 0xf4000000. Bus control registers 
are at 0xf4002000 - 0xf4003000. The parallel bus memory window on the 
localbus is located at 0xf5000000.

My current dts draft describes that topology as follows (unrelated devices on 
the local bus such as flash memory are removed for clarity).

localbus@f0010100 {
	compatible = "fsl,pq2-localbus";
	#address-cells = <2>;
	#size-cells = <1>;
	reg = <f0010100 40>;

	ranges = <0 0 40000000 01000000
		  2 0 f2000000 00100000
		  3 0 f3000000 00100000
		  4 0 f4000000 00100000
		  5 0 f5000000 00100000>;

	fpga@4,0 {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <4 0 0 00010000>;

		msbus-arbitrer@2000 {
			compatible = "tbox,cp11-msbus-arbitrer";
			reg = <2000 4>;
		};

		msbus_pic: interrupt-controller@2100 {
			compatible = "tbox,cp11-msbus-pic";
			reg = <2100 8>;
			interrupts = <17 2>;
			interrupt-parent = <&cpm_pic>;
			#interrupt-cells = <1>;
			interrupt-controller;
		};

		msbus-spi@2200 {
			compatible = "tbox,cp11-msbus-spi";
			reg = <2200 100>;
			interrupts = <18 8>;
			interrupt-parent = <&cpm_pic>;
		};

		sdhc@5000 {
			compatible = "tbox,sdhci";
			reg = <5000 1000>;
			interrupts = <16 8>;
			interrupt-parent = <&cpm_pic>;
		};
	};

	msbus@5,0 {
		compatible = "tbox,cp11-msbus";
		#address-cells = <1>;
		#size-cells = <1>;
		#interrupt-cells = <1>;
		reg = <5 0 0 00000400>;
		interrupt-parent = <&msbus_pic>;
	};
};

The device tree reflects the physical topology but makes driver access to the 
bus quite complex. An OF platform device driver matching on compatible 
= "tbox,cp11-msbus" will not have the bus FPGA registers described in its 
device node.

Having a look at the various device trees included in the kernel sources, it 
seems platforms with a PCI bus experience a similar problem. To solve it the 
PCI bus node address and registers describe the configuration registers, and 
the memory window to access PCI devices is described by the ranges property. 
Applying that to my custom bus would lead to the following tree.

localbus@f0010100 {
	compatible = "fsl,pq2-localbus";
	#address-cells = <2>;
	#size-cells = <1>;
	reg = <f0010100 40>;

	ranges = <0 0 40000000 01000000
		  2 0 f2000000 00100000
		  3 0 f3000000 00100000
		  4 0 f4000000 00100000
		  4 1 f4002000 00000100
		  5 0 f5000000 00100000>;

	fpga@4,0 {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <4 0 0 00010000>;

		msbus_pic: interrupt-controller@2100 {
			compatible = "tbox,cp11-msbus-pic";
			reg = <2100 8>;
			interrupts = <17 2>;
			interrupt-parent = <&cpm_pic>;
			#interrupt-cells = <1>;
			interrupt-controller;
		};

		msbus-spi@2200 {
			compatible = "tbox,cp11-msbus-spi";
			reg = <2200 100>;
			interrupts = <18 8>;
			interrupt-parent = <&cpm_pic>;
		};

		sdhc@5000 {
			compatible = "tbox,sdhci";
			reg = <5000 1000>;
			interrupts = <16 8>;
			interrupt-parent = <&cpm_pic>;
		};
	};

	msbus@4,1 {
		compatible = "tbox,cp11-msbus";
		#address-cells = <1>;
		#size-cells = <1>;
		#interrupt-cells = <1>;
		reg = <4 1 4>;
		interrupt-parent = <&msbus_pic>;
		ranges = <5 0 0 00000400>;
	};
};

Is this correct ? Is that the best way to describe my custom bus in the device 
tree ? How would the relationships between the bus and its PIC and SPI 
controller be handled in the drivers ? I also don't understand how interrupt 
mappings are supposed to be handled. PCI busses have two CPM interrupt lines, 
one for the PCI PIC and one for the PCI bus, with the PCI bus having the CPM 
PIC as its interrupt controller. My bus PIC uses a single interrupt line. Is 
there some documentation explaining how PICs and interrupt mappings should be 
described ?

Thanks in advance for any help you can provide.

Best regards,

-- 
Laurent Pinchart
CSE Semaphore Belgium

Chaussée de Bruxelles, 732A
B-1410 Waterloo
Belgium

T +32 (2) 387 42 59
F +32 (2) 387 42 75

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

^ permalink raw reply

* bootstrap loader + gzip 1.3.5 --> huge image!?
From: Robert Zach @ 2008-03-11 14:37 UTC (permalink / raw)
  To: linuxppc-embedded

hi list!

I am using the xilinx git tree with the included bootstrap loader.
Everthing works fine when i use binutils-2.16.1-gcc-3.4.6-uClibc-0.9.29.

But when useing binutils-2.18.50-gcc-4.2.0-uClibc-0.9.29  (generated 
with buildroot) i get the following problem:

At the end of the kernel build process the vmlinux image gets compressed 
(for the bootstrap loader).
something like:
gzip -f -9 < arch/ppc/boot/images/vmlinux.bin > 
arch/ppc/boot/images/vmlinux.gz.$$
when i compiled the kernel with binutils-2.16.1-gcc-3.4.6-uClibc-0.9.29 
the resulting image size is smaller then the original and everything 
works (the bootstrap loader uncompresses, the kernel boots, ..)

But when using the binutils-2.18.50-gcc-4.2.0-uClibc-0.9.29 
cross-toolchain i get the following:
du arch/ppc/boot/images/vmlinux.bin
1264    arch/ppc/boot/images/vmlinux.bin
gzip -f -9 < arch/ppc/boot/images/vmlinux.bin > 
arch/ppc/boot/images/vmlinux.gz.$$
du arch/ppc/boot/images/vmlinux.gz.$$
3640    arch/ppc/boot/images/vmlinux.gz

The resulting huge zImage.elf file does not work (the bootstraploader 
stops somewhere early).
Its the same for all other toolchains i tryed using binutils > 2.16.

what does gzip do?
I use the following version
gzip --version
gzip 1.3.5
(2002-09-30)
Copyright 2002 Free Software Foundation
Copyright 1992-1993 Jean-loup Gailly

Does anybody know this problem?
any suggestions for a solution.

thanks in advanced!
greets!
robert

^ permalink raw reply

* RE: OF compatible MTD platform RAM driver ?
From: Rune Torgersen @ 2008-03-11 15:00 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev, linux-mtd, ben
In-Reply-To: <20080311004545.GI11559@localhost.localdomain>

David Gibson wrote:
> On Mon, Mar 10, 2008 at 12:00:22PM -0500, Rune Torgersen wrote:
>> We ran ito the same issue.
>> We did option 3, as it was efinetly the easiest,
>=20
> I think this is the best option in principle.
>=20
>> here is the sram entry in our dts:
>=20
> Except that your implementation of it is not good.
>=20
> You're relying on the old obsolete flash binding with the "probe-type"
> field.  The solution should be adapted to the new approach which uses
> values in the "compatible" field to indicate various sorts of flash
> device.

Yea, I know. But it was the easiest way of doing it at the time we did
our port....
In a timecrunch, easier is sometimes better than correct. :)

^ permalink raw reply

* of_serial vs legacy serial support with powerpc arch on 405
From: John Linn @ 2008-03-11 15:04 UTC (permalink / raw)
  To: linuxppc-dev

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

I've searched and found some threads, but it's still not clear to me.
I'm working on 405 with powerpc and trying to get UART550 working.

 

I know that I need speed, freq, and reg-shift properties in the device
tree and I have found patches for of_serial.c.

 

I still don't understand when to use of_serial.c (SERIAL_OF_PLATFORM) vs
the legacy support for serial ports.  Is there any docs that I'm not
finding that I should read?

 

I don't see a way to configure in the legacy support, but I'm using
SERIAL_OF and having problems. I don't see the console getting enabled
even though it found the serial port driver.

 

Thanks,

John

 


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

^ permalink raw reply

* RE: Add some documentation for the dts formta
From: Yoder Stuart @ 2008-03-11 15:34 UTC (permalink / raw)
  To: David Gibson, Loeliger Jon; +Cc: linuxppc-dev
In-Reply-To: <20080310234714.GB11559@localhost.localdomain>


Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>=20

> -----Original Message-----
> From: David Gibson [mailto:david@gibson.dropbear.id.au]=20
> Sent: Monday, March 10, 2008 6:47 PM
> To: Loeliger Jon
> Cc: Yoder Stuart; linuxppc-dev@ozlabs.org
> Subject: dtc: Add some documentation for the dts formta
>=20
> This patch adds a dts-format.txt in the Documentation directory, with
> an introduction to the dtc source format.  Note that this
> documentation is also going into the upcoming ePAPR specification.
>=20
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>=20
> ---
>  Documentation/dts-format.txt |  110=20
> +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 110 insertions(+)
>=20
> I wrote this documentation based on an earlier draft from Stuart
> Yoder.  Stuart, can you please reply with a Signed-off-by line?
>=20
> Index: dtc/Documentation/dts-format.txt
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ dtc/Documentation/dts-format.txt	2008-03-11=20
> 10:42:17.000000000 +1100
> @@ -0,0 +1,110 @@
> +Device Tree Source Format (version 1)
> =
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> +
> +The Device Tree Source (DTS) format is a textual representation of a
> +device tree in a form that can be processed by dtc into a binary
> +device tree in the form expected by the kernel.  The=20
> description below
> +is not a formal syntax definition of DTS, but describes the basic
> +constructs used to represent device trees.
> +
> +Node and property definitions
> +-----------------------------
> +
> +Device tree nodes are defined with a node name and unit address with
> +braces marking the start and end of the node definition.  They may be
> +preceded by a label.
> +
> +	[label:] node-name[@unit-address] {
> +		[properties definitions]
> +		[child nodes]
> +	}
> +
> +Nodes may contain property definitions and/or child node
> +definitions. If both are present, properties must come before child
> +nodes.
> +
> +Property definitions are name value pairs in the form:
> +	[label:] property-name =3D value;
> +except for properties with empty (zero length) value which have the
> +form:
> +	[label:] property-name;
> +
> +Property values may be defined as an array of 32-bit integer=20
> cells, as
> +NUL-terminated strings, as bytestrings or a combination of these.
> +
> +* Arrays of cells are represented by angle brackets surrounding a
> +  space separated list of C-style integers
> +
> +	e.g. interrupts =3D <17 0xc>;
> +
> +* A 64-bit value is represented with two 32-bit cells.
> +
> +	e.g. clock-frequency =3D <0x00000001 0x00000000>;
> +
> +* A NUL-terminated string value is represented using double quotes
> +  (the property value is considered to include the terminating NUL
> +  character).
> +
> +	e.g. compatible =3D "simple-bus";
> +
> +* A bytestring is enclosed in square brackets [] with each byte
> +  represented by two hexadecimal digits.  Spaces between=20
> each byte are
> +  optional.
> +
> +	e.g. local-mac-address =3D [00 00 12 34 56 78]; or equivalently
> +	     local-mac-address =3D [000012345678];
> +
> +* Values may have several comma-separated components, which are
> +  concatenated together.
> +	e.g. compatible =3D "ns16550", "ns8250";
> +	     example =3D <0xf00f0000 19>, "a strange property format";
> +
> +* In a cell array a reference to another node will be=20
> expanded to that
> +  node's phandle.  References may by '&' followed by a node's label:
> +	e.g. interrupt-parent =3D < &mpic >;
> +  or they may be '&' followed by a node's full path in braces:
> +	e.g. interrupt-parent =3D < &{/soc/interrupt-controller@40000} >;
> +
> +* Outside a cell array, a reference to another node will be expanded
> +  to that node's full path.
> +	e.g. ethernet0 =3D &EMAC0;
> +
> +* Labels may also appear before or after any component of a property
> +  value, or between cells of a cell array, or between bytes of a
> +  bytestring.
> +	e.g. reg =3D reglabel: <0 sizelabel: 0x1000000>;
> +	e.g. prop =3D [ab cd ef byte4: 00 ff fe];
> +	e.g. str =3D start: "string value" end: ;
> +
> +
> +File layout
> +-----------
> +
> +Version 1 DTS files have the overall layout:
> +	/dts-v1/;
> +
> +	[memory reservations]
> +
> +	/ {
> +		[property definitions]
> +		[child nodes]
> +	};
> +
> +* The "/dts-v1/;" must be present to identify the file as a version 1
> +  DTS (dts files without this tag will be treated by dtc as being in
> +  the obsolete "version 0", which uses a different format=20
> for integers
> +  amongst other small but incompatible changes).
> +
> +* Memory reservations define an entry for the device tree blob's
> +  memory reservation table.  They have the form:
> +	e.g. /memreserve/ <address> <length>;
> +  Where <address> and <length> are 64-bit C-style integers.
> +
> +* The / { ... }; section defines the root node of the device tree.
> +
> +* C style (/* ... */) and C++ style (// ...) comments are supported.
> +
> +
> +
> +	-- David Gibson <david@gibson.dropbear.id.au>
> +	-- Yoder Stuart <stuart.yoder@freescale.com>
>=20
>=20
> --=20
> David Gibson			| I'll have my music baroque,=20
> and my code
> david AT gibson.dropbear.id.au	| minimalist, thank=20
> you.  NOT _the_ _other_
> 				| _way_ _around_!
> http://www.ozlabs.org/~dgibson
>=20

^ permalink raw reply

* Re: bootstrap loader + gzip 1.3.5 --> huge image!?
From: rza1 @ 2008-03-11 15:45 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <47D6992B.6060208@so-logic.net>

I just recognized that gzip does his job right.
But objcopy of all binutils > 2.16.1 has problems during binary copy:
powerpc-linux-objcopy -O binary vmlinux arch/ppc/boot/images/vmlinux.bin

The vmlinux file does look good (what i can see with vi) but the 
generated vmlinux.bin file is strange. Windows machines say that the 
vmlinux.bin file is > then 3GByte, but linux says 1,5Mbyte. But, I can't 
open it with vi...

Anywhay i think binutils > 2.16.1 has some problems with ppc.

Does anyone else use buildroot for ppc405 platform and solved the 
problems with actual binutils versions?
cheers!
robert

Robert Zach wrote:
> hi list!
>
> I am using the xilinx git tree with the included bootstrap loader.
> Everthing works fine when i use binutils-2.16.1-gcc-3.4.6-uClibc-0.9.29.
>
> But when useing binutils-2.18.50-gcc-4.2.0-uClibc-0.9.29  (generated 
> with buildroot) i get the following problem:
>
> At the end of the kernel build process the vmlinux image gets 
> compressed (for the bootstrap loader).
> something like:
> gzip -f -9 < arch/ppc/boot/images/vmlinux.bin > 
> arch/ppc/boot/images/vmlinux.gz.$$
> when i compiled the kernel with 
> binutils-2.16.1-gcc-3.4.6-uClibc-0.9.29 the resulting image size is 
> smaller then the original and everything works (the bootstrap loader 
> uncompresses, the kernel boots, ..)
>
> But when using the binutils-2.18.50-gcc-4.2.0-uClibc-0.9.29 
> cross-toolchain i get the following:
> du arch/ppc/boot/images/vmlinux.bin
> 1264    arch/ppc/boot/images/vmlinux.bin
> gzip -f -9 < arch/ppc/boot/images/vmlinux.bin > 
> arch/ppc/boot/images/vmlinux.gz.$$
> du arch/ppc/boot/images/vmlinux.gz.$$
> 3640    arch/ppc/boot/images/vmlinux.gz
>
> The resulting huge zImage.elf file does not work (the bootstraploader 
> stops somewhere early).
> Its the same for all other toolchains i tryed using binutils > 2.16.
>
> what does gzip do?
> I use the following version
> gzip --version
> gzip 1.3.5
> (2002-09-30)
> Copyright 2002 Free Software Foundation
> Copyright 1992-1993 Jean-loup Gailly
>
> Does anybody know this problem?
> any suggestions for a solution.
>
> thanks in advanced!
> greets!
> robert
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply

* Re: issue about CONFIG_PPC_MMU and CONFIG_SMP define
From: Becky Bruce @ 2008-03-11 15:53 UTC (permalink / raw)
  To: jie han; +Cc: linuxppc-embedded@ozlabs.org
In-Reply-To: <604678.57629.qm@web15104.mail.cnb.yahoo.com>

On Mar 10, 2008, at 3:15 PM, jie han wrote:

> Hi guys,
>
> I want to simulate compile mutli-core using sequoia(IBM/AMCC 44x  
> processor) source code under kernel arch/powerpc directory.I want  
> to define CONFIG_SMP, I sould define CONFIG_STD_MMU at first,but  
> AMCC 44x don't need to config CONFIG_STD_MMU.Is CONFIG_STD_MMU just  
> for freescale chip? How can I do next? Thanks ahead for your help,

STD_MMU is for all powerpc cpus with a non-BookE MMU.  That includes  
all the 64-bit parts from IBM to date, pasemi's parts, and 32-bit  
parts from IBM & Freescale like the 6xx, 7xx, 7xxx, e600 e300, etc.   
You cannot set this for 44x, because it is a BookE part.

BTW, there's no real relationship between STD_MMU and SMP.  It was  
just a convenient way to restrict the SMP config option in the  
kernel, since all the Linux configs that currently support SMP are  
STD_MMU. We will have BookE configs in the future that do support  
SMP, at which point arch/powerpc/platforms/Kconfig.cputype will be  
changed to allow SMP to be set for those configs.

You can't enable SMP on 44x right now.  It's not supported.

Cheers,
B

^ permalink raw reply

* [PATCH] Ported Xilinx GPIO driver to OpenFirmware.
From: Magnus Hjorth @ 2008-03-11 16:12 UTC (permalink / raw)
  To: git; +Cc: linuxppc-embedded

From: Magnus Hjorth <mh@omnisys.se>

 Added of_device structure and init code.=20
 Basic functionality tested (LED:s on/off).
 Added code to validate channel number in ioctl.

Signed-off-by: Magnus Hjorth <mh@omnisys.se>
---

 Patch against Xilinx GIT tree (commit 7fb2b...)
 Did this as a learning exercise. Hope it gets through Outlook in one =
piece :)
 Cheers /Magnus

diff --git a/drivers/char/xilinx_gpio/adapter.c =
b/drivers/char/xilinx_gpio/adapter.c
index ecd2897..6fdf7aa 100644
--- a/drivers/char/xilinx_gpio/adapter.c
+++ b/drivers/char/xilinx_gpio/adapter.c
@@ -43,15 +43,22 @@
 #include <asm/irq.h>
 #include <linux/interrupt.h>
=20
+#ifdef CONFIG_OF
+// For open firmware.
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#endif
+
 #define BUFSIZE		200
 #define MIN(x,y) (x < y ? x : y)
=20
-
 struct xgpio_instance {
 	struct list_head link;
 	unsigned long base_phys;	/* GPIO base address - physical */
 	unsigned long remap_size;
-	u32 device_id;
+	u32 device_id;		/* Dev ID for platform devices, 0 for OF devices */
+	void *of_id;		/* of_dev pointer for OF devices, NULL for plat devices =
*/
+	int is_dual;
 	wait_queue_head_t wait;
 	unsigned int head, tail, count;
 	__u64 buf[BUFSIZE];	/* 32xChan1, 32xChan2 */
@@ -125,8 +132,7 @@ static struct xgpio_instance *xgpio_getinst(unsigned =
int minor)
 			up_read(&inst_list_sem);
 			if (XGpio_IsReady(&inst->gpio)) {
 				return inst;
-			}
-			else {
+			} else {
 				return NULL;
 			}
 		}
@@ -147,6 +153,10 @@ static int xgpio_ioctl(struct inode *inode, struct =
file *file,
 	if (copy_from_user(&ioctl_data, (void *) arg, sizeof(ioctl_data)))
 		return -EFAULT;
=20
+	/* Validate channel number */
+	if (ioctl_data.chan !=3D 1 && (ioctl_data.chan !=3D 2 || =
!inst->is_dual))
+		return -EINVAL;
+
 	switch (cmd) {
 	case XGPIO_IN:
 		/*
@@ -216,6 +226,7 @@ static int xgpio_ioctl(struct inode *inode, struct =
file *file,
 		return -ENOIOCTLCMD;
=20
 	}
+
 	return 0;
 }
=20
@@ -237,7 +248,6 @@ static unsigned int prev(unsigned int ptr)
 	return ptr;
 }
=20
-
 static ssize_t xgpio_read(struct file *file, char *buf,
 			  size_t count, loff_t * ppos)
 {
@@ -278,7 +288,6 @@ static ssize_t xgpio_read(struct file *file, char =
*buf,
 	return 0;
 }
=20
-
 static irqreturn_t xgpio_interrupt(int irq, void *dev_id)
 {
 	struct xgpio_instance *inst =3D dev_id;
@@ -287,7 +296,6 @@ static irqreturn_t xgpio_interrupt(int irq, void =
*dev_id)
 		inst->gpio.IsDual ? XIo_In32(inst->gpio.BaseAddress + 0x08) : 0;
 	__u32 int_status =3D XIo_In32(inst->gpio.BaseAddress + 0x120);
=20
-
 	if (inst->buf[prev(inst->tail)] !=3D
 	    (((__u64) val_1) | ((__u64) (val_2) << 32)))
 		if (next(inst->tail) !=3D inst->head) {
@@ -303,7 +311,6 @@ static irqreturn_t xgpio_interrupt(int irq, void =
*dev_id)
 	return IRQ_HANDLED;
 }
=20
-
 /*
  * We get to all of the GPIOs through one minor number.  Here's the
  * miscdevice that gets registered for that minor number.
@@ -335,45 +342,33 @@ char *names[] =3D {
=20
 static int minor =3D XGPIO_MINOR;
=20
-static int xgpio_probe(struct device *dev)
+static int xgpio_probe_main(struct device *dev, int dev_id, void =
*of_dev_id,
+			    int is_dual,
+			    struct resource *irq_res, struct resource *regs_res)
 {
 	XGpio_Config xgpio_config;
 	struct xgpio_instance *xgpio_inst;
 	struct miscdevice *miscdev =3D 0;
-	struct platform_device *pdev =3D to_platform_device(dev);
-	struct resource *irq_res, *regs_res;
 	void *v_addr;
 	int retval;
=20
-	if (!dev)
-		return -EINVAL;
-
 	memset(&xgpio_config, 0, sizeof(XGpio_Config));
 	xgpio_inst =3D kmalloc(sizeof(struct xgpio_instance), GFP_KERNEL);
 	if (!xgpio_inst) {
 		printk(KERN_ERR
 		       "%s #%d: Couldn't allocate device private record\n",
-		       miscdev->name, pdev->id);
+		       miscdev->name, dev_id);
 		return -ENOMEM;
 	}
 	memset(xgpio_inst, 0, sizeof(struct xgpio_instance));
=20
-	/* Map the control registers in */
-	regs_res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!regs_res || (regs_res->end - regs_res->start + 1 < 8)) {
-		printk(KERN_ERR "%s #%d: Couldn't get registers resource\n",
-		       miscdev->name, pdev->id);
-		retval =3D -EFAULT;
-		goto failed1;
-	}
-
 	xgpio_inst->remap_size =3D regs_res->end - regs_res->start + 1;
 	if (!request_mem_region(regs_res->start, xgpio_inst->remap_size,
 				DRIVER_NAME)) {
 		printk(KERN_ERR "Couldn't lock memory region at 0x%08lX\n",
 		       (unsigned long) regs_res->start);
 		retval =3D -EBUSY;
-		goto failed2;
+		goto failed1;
 	}
=20
 	v_addr =3D ioremap(regs_res->start, xgpio_inst->remap_size);
@@ -381,21 +376,22 @@ static int xgpio_probe(struct device *dev)
 		printk(KERN_ERR "Couldn't ioremap memory at 0x%08lX\n",
 		       (unsigned long) regs_res->start);
 		retval =3D -EFAULT;
-		goto failed3;
+		goto failed2;
 	}
=20
 	xgpio_inst->base_phys =3D regs_res->start;
 	/* The 1st GPIO channel uses */
-	xgpio_inst->device_id =3D pdev->id;
-	xgpio_config.DeviceId =3D pdev->id;
-	xgpio_config.IsDual =3D
-		((unsigned) (dev->platform_data) & XGPIO_IS_DUAL) ? 1 : 0;
+	xgpio_inst->device_id =3D dev_id;
+	xgpio_inst->of_id =3D of_dev_id;
+	xgpio_inst->is_dual =3D is_dual ? 1 : 0;
+	xgpio_config.DeviceId =3D dev_id;
+	xgpio_config.IsDual =3D is_dual ? 1 : 0;
=20
 	/* Tell the Xilinx code to bring this GPIO interface up. */
 	if (XGpio_CfgInitialize(&xgpio_inst->gpio, &xgpio_config,
 				(u32) v_addr) !=3D XST_SUCCESS) {
 		printk(KERN_ERR "%s #%d: Could not initialize instance.\n",
-		       miscdev->name, pdev->id);
+		       miscdev->name, dev_id);
 		retval =3D -ENODEV;
 		goto failed3;
 	}
@@ -407,7 +403,7 @@ static int xgpio_probe(struct device *dev)
 	if (!miscdev) {
 		printk(KERN_ERR
 		       "%s #%d: Couldn't allocate device private record\n",
-		       "xgpio", pdev->id);
+		       "xgpio", dev_id);
 		return -ENOMEM;
 	}
=20
@@ -419,7 +415,7 @@ static int xgpio_probe(struct device *dev)
 	if (retval !=3D 0) {
 		up_write(&inst_list_sem);
 		printk(KERN_ERR "%s #%d: Could not register miscdev.\n",
-		       miscdev->name, pdev->id);
+		       miscdev->name, dev_id);
 		goto failed3;
 	}
=20
@@ -427,7 +423,6 @@ static int xgpio_probe(struct device *dev)
=20
 	minor++;
=20
-	irq_res =3D platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (irq_res) {
 		if (request_irq(irq_res->start,
 				xgpio_interrupt, 0, "XGPIO", xgpio_inst))
@@ -471,24 +466,45 @@ static int xgpio_probe(struct device *dev)
 	return retval;
 }
=20
-static int xgpio_remove(struct device *dev)
+static int xgpio_probe(struct device *dev)
 {
-	struct list_head *entry;
-	struct xgpio_instance *xgpio_inst =3D NULL;
 	struct platform_device *pdev =3D to_platform_device(dev);
+	struct resource *irq_res, *regs_res;
+	int is_dual;
=20
 	if (!dev)
 		return -EINVAL;
=20
+	/* Map the control registers in */
+	regs_res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs_res || (regs_res->end - regs_res->start + 1 < 8)) {
+		dev_err(dev, "couldn't get registers resource\n");
+		return -EFAULT;
+	}
+
+	irq_res =3D platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+	is_dual =3D ((unsigned)(dev->platform_data) & XGPIO_IS_DUAL);
+
+	return xgpio_probe_main(dev, pdev->id, NULL, is_dual, irq_res,
+				regs_res);
+}
+
+static int xgpio_remove_main(struct device *dev, int dev_id, void =
*of_dev_id)
+{
+	struct list_head *entry;
+	struct xgpio_instance *xgpio_inst =3D NULL;
+	struct platform_device *pdev =3D to_platform_device(dev);
+
 	/* Set xgpio_inst based on pdev->id match */
=20
 	down_read(&inst_list_sem);
 	list_for_each(entry, &inst_list) {
 		xgpio_inst =3D list_entry(entry, struct xgpio_instance, link);
-		if (pdev->id =3D=3D xgpio_inst->device_id) {
+		if (pdev->id =3D=3D xgpio_inst->device_id &&
+		    of_dev_id =3D=3D xgpio_inst->of_id) {
 			break;
-		}
-		else {
+		} else {
 			xgpio_inst =3D NULL;
 		}
 	}
@@ -515,6 +531,16 @@ static int xgpio_remove(struct device *dev)
 	return 0;		/* success */
 }
=20
+static int xgpio_remove(struct device *dev)
+{
+	struct platform_device *pdev =3D to_platform_device(dev);
+
+	if (!dev)
+		return -EINVAL;
+
+	return xgpio_remove_main(dev, pdev->id, NULL);
+}
+
 static struct device_driver xgpio_driver =3D {
 	.name =3D DRIVER_NAME,
 	.bus =3D &platform_bus_type,
@@ -523,13 +549,77 @@ static struct device_driver xgpio_driver =3D {
 	.remove =3D xgpio_remove
 };
=20
+#ifdef CONFIG_OF
+
+static int __devinit xgpio_of_probe(struct of_device *ofdev,
+				    const struct of_device_id *match)
+{
+	struct resource r_irq_struct, r_mem_struct;
+	struct resource *r_irq;
+	int rc;
+	int l;
+	const u32 *p;
+	int is_dual;
+
+	rc =3D of_address_to_resource(ofdev->node, 0, &r_mem_struct);
+	if (rc) {
+		dev_warn(&ofdev->dev, "invalid address\n");
+		return rc;
+	}
+
+	rc =3D of_irq_to_resource(ofdev->node, 0, &r_irq_struct);
+	if (rc =3D=3D NO_IRQ)
+		r_irq =3D NULL;
+	else
+		r_irq =3D &r_irq_struct;
+
+	p =3D of_get_property(ofdev->node, "xlnx,is-dual", &l);
+	if (p =3D=3D NULL || l !=3D sizeof(*p)) {
+		dev_warn(&ofdev->dev, "Property not found: xlnx,is-dual\n");
+		is_dual =3D 0;
+	} else
+		is_dual =3D *p;
+
+	return xgpio_probe_main(&ofdev->dev, 0, ofdev, is_dual, r_irq,
+				&r_mem_struct);
+}
+
+static int __devexit xgpio_of_remove(struct of_device *ofdev)
+{
+	if (!ofdev)
+		return -EINVAL;
+
+	return xgpio_remove_main(&ofdev->dev, 0, ofdev);
+}
+
+static struct of_device_id xgpio_of_match[] =3D {
+	{.compatible =3D "xlnx,xps-gpio-1.00.a"},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, xgpio_of_match);
+
+static struct of_platform_driver xgpio_of_driver =3D {
+	.name =3D DRIVER_NAME,
+	.match_table =3D xgpio_of_match,
+	.probe =3D xgpio_of_probe,
+	.remove =3D __devexit_p(xgpio_of_remove),
+};
+
+#endif
+
 static int __init xgpio_init(void)
 {
+	int s;
 	/*
 	 * No kernel boot options used,
 	 * so we just need to register the driver
 	 */
-	return driver_register(&xgpio_driver);
+	s =3D driver_register(&xgpio_driver);
+#ifdef CONFIG_OF
+	s |=3D of_register_platform_driver(&xgpio_of_driver);
+#endif
+	return s;
 }
=20
 static void __exit xgpio_cleanup(void)
--=20
1.5.4.4


--

Magnus Hjorth, M.Sc.
Omnisys Instruments AB
Gruvgatan 8
SE-421 30  V=E4stra Fr=F6lunda, SWEDEN
Phone: +46 31 734 34 09
Fax: +46 31 734 34 29
http://www.omnisys.se

^ permalink raw reply related

* Re: [PATCH 3/8] pseries: phyp dump: use sysfs to release reserved mem
From: Dale Farnsworth @ 2008-03-11 16:44 UTC (permalink / raw)
  To: Linuxppc-dev
In-Reply-To: <18390.9137.626123.104628@cargo.ozlabs.ibm.com>

Paul wrote:
> Manish Ahuja writes:
> > +		dump_header = of_get_property(rtas, "ibm,kernel-dump",
> > +								&header_len);
> 
> This is a somewhat weird-looking way of coping with too-long lines.

Yes, but not too surprising, since it precisely follows the recommendation
(and the example) in Chapter 2 of Documentation/CodingStyle.  :)

-Dale

^ permalink raw reply

* Re: [PATCH] pasemi_dma: Driver for PA Semi PWRficient on-chip DMAengine
From: Dan Williams @ 2008-03-11 17:04 UTC (permalink / raw)
  To: Olof Johansson
  Cc: linuxppc-dev, pasemi-linux, Nelson, Shannon, linux-kernel,
	hskinnemoen
In-Reply-To: <20080306233900.GA3969@lixom.net>

On Thu, 2008-03-06 at 16:39 -0700, Olof Johansson wrote:
> pasemi_dma: Driver for PA Semi PWRficient on-chip DMA engine
>    
> First cut at a dma copy offload driver for PA Semi PWRficient. It uses the
> platform-specific functions to allocate channels, etc.
> 
> Signed-off-by: Olof Johansson <olof@lixom.net>
> 
> 
> ---
> 
> This has some dependencies on other patches currently queued up in the
> powerpc git trees for 2.6.26. I'd appreciate reviews and acked-bys, but
> it might be easiest to just merge it up the powerpc path due to the
> dependencies.
> 
Apologies for not getting to this sooner.

I notice that the driver does not handle callbacks in its descriptor
cleanup path.  This could be ok if your intent is only to support the
net_dma style polled operations, but this will not work for the
raid-offload async_tx case.  I think the solution is for async_tx to
ignore channels without the DMA_INTERRUPT capability.

> +static void pasemi_dma_clean(struct pasemi_dma_chan *chan)
> +{
> +       int old, new, i;
> +       unsigned long flags;
> +       struct pasemi_dma_desc *desc;
> +       spin_lock_irqsave(&chan->desc_lock, flags);

Is spin_lock_bh() insufficient here?

...that's all that jumps out at the moment.

Regards,
Dan

^ permalink raw reply

* [PATCH 1/2] [POWERPC] fsl_soc: add support for "fsl, soc" compatible matching
From: Anton Vorontsov @ 2008-03-11 17:10 UTC (permalink / raw)
  To: linuxppc-dev

As we've seen, fsl,immr isn't good name for the generic purposes,
because some SOCs use ccsr term. So, for generic matching, "fsl,soc"
is used, whereas "fsl,immr" and "fsl,ccsr" is used for more specific
matching.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 Documentation/powerpc/booting-without-of.txt |   20 +++++------
 arch/powerpc/sysdev/fsl_soc.c                |   51 +++++++++++++++-----------
 2 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 7b4e8a7..be41a5c 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -32,7 +32,7 @@ Table of Contents
       c) The /cpus/* nodes
       d) the /memory node(s)
       e) The /chosen node
-      f) the /soc<SOCname> node
+      f) the /soc node
 
   IV - "dtc", the device tree compiler
 
@@ -961,20 +961,17 @@ compatibility.
   under /chosen called interrupt-controller which had a phandle value
   that pointed to the main interrupt controller)
 
-  f) the /soc<SOCname> node
+  f) the /soc node
 
   This node is used to represent a system-on-a-chip (SOC) and must be
   present if the processor is a SOC. The top-level soc node contains
-  information that is global to all devices on the SOC. The node name
-  should contain a unit address for the SOC, which is the base address
-  of the memory-mapped register set for the SOC. The name of an soc
-  node should start with "soc", and the remainder of the name should
-  represent the part number for the soc.  For example, the MPC8540's
-  soc node would be called "soc8540".
+  information that is global to all devices on the SOC. The name of an
+  soc node should be "soc".
 
   Required properties:
 
-    - device_type : Should be "soc"
+    - compatible : Should be "<cpu>-<immr or ccsr>", "fsl,<immr or ccsr>",
+      "fsl,soc", "simple-bus".
     - ranges : Should be defined as specified in 1) to describe the
       translation of SOC addresses for memory mapped SOC registers.
     - bus-frequency: Contains the bus frequency for the SOC node.
@@ -2913,11 +2910,12 @@ Note that the #address-cells and #size-cells for the SoC node
 in this example have been explicitly listed; these are likely
 not necessary as they are usually the same as the root node.
 
-	soc8540@e0000000 {
+	soc@e0000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		#interrupt-cells = <2>;
-		device_type = "soc";
+		compatible = "fsl,mpc8540-ccsr", "fsl,ccsr", "fsl,soc",
+			     "simple-bus";
 		ranges = <00000000 e0000000 00100000>
 		reg = <e0000000 00003000>;
 		bus-frequency = <0>;
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 2c5388c..7ad9bce 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -48,27 +48,31 @@ static phys_addr_t immrbase = -1;
 phys_addr_t get_immrbase(void)
 {
 	struct device_node *soc;
+	int size;
+	u32 naddr;
+	const u32 *prop;
 
 	if (immrbase != -1)
 		return immrbase;
 
-	soc = of_find_node_by_type(NULL, "soc");
-	if (soc) {
-		int size;
-		u32 naddr;
-		const u32 *prop = of_get_property(soc, "#address-cells", &size);
+	soc = of_find_compatible_node(NULL, NULL, "fsl,soc");
+	if (!soc) {
+		soc = of_find_node_by_type(NULL, "soc");
+		if (!soc)
+			return immrbase;
+	}
 
-		if (prop && size == 4)
-			naddr = *prop;
-		else
-			naddr = 2;
+	prop = of_get_property(soc, "#address-cells", &size);
+	if (prop && size == 4)
+		naddr = *prop;
+	else
+		naddr = 2;
 
-		prop = of_get_property(soc, "ranges", &size);
-		if (prop)
-			immrbase = of_translate_address(soc, prop + naddr);
+	prop = of_get_property(soc, "ranges", &size);
+	if (prop)
+		immrbase = of_translate_address(soc, prop + naddr);
 
-		of_node_put(soc);
-	}
+	of_node_put(soc);
 
 	return immrbase;
 }
@@ -528,11 +532,13 @@ static int __init mpc83xx_wdt_init(void)
 		goto nodev;
 	}
 
-	soc = of_find_node_by_type(NULL, "soc");
-
+	soc = of_find_compatible_node(NULL, NULL, "fsl,soc");
 	if (!soc) {
-		ret = -ENODEV;
-		goto nosoc;
+		soc = of_find_node_by_type(NULL, "soc");
+		if (!soc) {
+			ret = -ENODEV;
+			goto nosoc;
+		}
 	}
 
 	freq = of_get_property(soc, "bus-frequency", NULL);
@@ -1375,9 +1381,12 @@ int __init fsl_spi_init(struct spi_board_info *board_infos,
 		const u32 *freq;
 		int size;
 
-		np = of_find_node_by_type(NULL, "soc");
-		if (!np)
-			return -ENODEV;
+		np = of_find_compatible_node(NULL, NULL, "fsl,soc");
+		if (!np) {
+			np = of_find_node_by_type(NULL, "soc");
+			if (!np)
+				return -ENODEV;
+		}
 
 		freq = of_get_property(np, "clock-frequency", &size);
 		if (!freq || size != sizeof(*freq) || *freq == 0) {
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH 2/2] [POWERPC] UCC nodes cleanup
From: Anton Vorontsov @ 2008-03-11 17:10 UTC (permalink / raw)
  To: linuxppc-dev

- get rid of `model = "UCC"' in the ucc nodes
  It isn't used anywhere, so remove it. If we'll ever need something
  like this, we'll use compatible property instead.
- replace cell-index and device-id properties by fsl,ucc.

Drivers are modified for backward compatibility's sake.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 Documentation/powerpc/booting-without-of.txt |    6 ++----
 arch/powerpc/boot/dts/mpc832x_mds.dts        |   11 +++--------
 arch/powerpc/boot/dts/mpc832x_rdb.dts        |    8 ++------
 arch/powerpc/boot/dts/mpc836x_mds.dts        |    8 ++------
 arch/powerpc/boot/dts/mpc8568mds.dts         |   12 ++++--------
 drivers/net/ucc_geth.c                       |    8 +++++++-
 drivers/net/ucc_geth_mii.c                   |   11 ++++++++---
 drivers/serial/ucc_uart.c                    |   16 ++++++++++++----
 8 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index be41a5c..8ae57f2 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1619,8 +1619,7 @@ platforms are moved over to use the flattened-device-tree model.
    - device_type : should be "network", "hldc", "uart", "transparent"
      "bisync", "atm", or "serial".
    - compatible : could be "ucc_geth" or "fsl_atm" and so on.
-   - model : should be "UCC".
-   - device-id : the ucc number(1-8), corresponding to UCCx in UM.
+   - fsl,ucc : the ucc number(1-8), corresponding to UCCx in UM.
    - reg : Offset and length of the register set for the device
    - interrupts : <a b> where a is the interrupt number and b is a
      field that represents an encoding of the sense and level
@@ -1677,8 +1676,7 @@ platforms are moved over to use the flattened-device-tree model.
 	ucc@2000 {
 		device_type = "network";
 		compatible = "ucc_geth";
-		model = "UCC";
-		device-id = <1>;
+		fsl,ucc = <1>;
 		reg = <2000 200>;
 		interrupts = <a0 0>;
 		interrupt-parent = <700>;
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index 9bb4083..689e708 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -255,9 +255,7 @@
 		enet0: ucc@2200 {
 			device_type = "network";
 			compatible = "ucc_geth";
-			model = "UCC";
-			cell-index = <3>;
-			device-id = <3>;
+			fsl,ucc = <3>;
 			reg = <0x2200 0x200>;
 			interrupts = <34>;
 			interrupt-parent = <&qeic>;
@@ -271,9 +269,7 @@
 		enet1: ucc@3200 {
 			device_type = "network";
 			compatible = "ucc_geth";
-			model = "UCC";
-			cell-index = <4>;
-			device-id = <4>;
+			fsl,ucc = <4>;
 			reg = <0x3200 0x200>;
 			interrupts = <35>;
 			interrupt-parent = <&qeic>;
@@ -287,8 +283,7 @@
 		ucc@2400 {
 			device_type = "serial";
 			compatible = "ucc_uart";
-			model = "UCC";
-			device-id = <5>;	/* The UCC number, 1-7*/
+			fsl,ucc = <5>;		/* The UCC number, 1-7*/
 			port-number = <0>;	/* Which ttyQEx device */
 			soft-uart;		/* We need Soft-UART */
 			reg = <0x2400 0x200>;
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
index 94f93d2..76e57ee 100644
--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -208,9 +208,7 @@
 		enet0: ucc@3000 {
 			device_type = "network";
 			compatible = "ucc_geth";
-			model = "UCC";
-			cell-index = <2>;
-			device-id = <2>;
+			fsl,ucc = <2>;
 			reg = <0x3000 0x200>;
 			interrupts = <33>;
 			interrupt-parent = <&qeic>;
@@ -224,9 +222,7 @@
 		enet1: ucc@2200 {
 			device_type = "network";
 			compatible = "ucc_geth";
-			model = "UCC";
-			cell-index = <3>;
-			device-id = <3>;
+			fsl,ucc = <3>;
 			reg = <0x2200 0x200>;
 			interrupts = <34>;
 			interrupt-parent = <&qeic>;
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index 55f03e8..e369749 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -257,9 +257,7 @@
 		enet0: ucc@2000 {
 			device_type = "network";
 			compatible = "ucc_geth";
-			model = "UCC";
-			cell-index = <1>;
-			device-id = <1>;
+			fsl,ucc = <1>;
 			reg = <0x2000 0x200>;
 			interrupts = <32>;
 			interrupt-parent = <&qeic>;
@@ -274,9 +272,7 @@
 		enet1: ucc@3000 {
 			device_type = "network";
 			compatible = "ucc_geth";
-			model = "UCC";
-			cell-index = <2>;
-			device-id = <2>;
+			fsl,ucc = <2>;
 			reg = <0x3000 0x200>;
 			interrupts = <33>;
 			interrupt-parent = <&qeic>;
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 97bc048..884fe45 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -142,7 +142,7 @@
 		};
 
 		enet0: ethernet@24000 {
-			cell-index = <0>;
+			fsl,ucc = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -154,7 +154,7 @@
 		};
 
 		enet1: ethernet@25000 {
-			cell-index = <1>;
+			fsl,ucc = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -324,9 +324,7 @@
 		enet2: ucc@2000 {
 			device_type = "network";
 			compatible = "ucc_geth";
-			model = "UCC";
-			cell-index = <1>;
-			device-id = <1>;
+			fsl,ucc = <1>;
 			reg = <2000 200>;
 			interrupts = <20>;
 			interrupt-parent = <&qeic>;
@@ -341,9 +339,7 @@
 		enet3: ucc@3000 {
 			device_type = "network";
 			compatible = "ucc_geth";
-			model = "UCC";
-			cell-index = <2>;
-			device-id = <2>;
+			fsl,ucc = <2>;
 			reg = <3000 200>;
 			interrupts = <21>;
 			interrupt-parent = <&qeic>;
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index fba0811..aa6566e 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3852,7 +3852,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
 
 	ugeth_vdbg("%s: IN", __FUNCTION__);
 
-	prop = of_get_property(np, "device-id", NULL);
+	prop = of_get_property(np, "fsl,ucc", NULL);
+	if (!prop) {
+		prop = of_get_property(np, "device-id", NULL);
+		if (!prop)
+			return -ENODEV;
+	}
+
 	ucc_num = *prop - 1;
 	if ((ucc_num < 0) || (ucc_num > 7))
 		return -ENODEV;
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
index c69e654..1d4bfc0 100644
--- a/drivers/net/ucc_geth_mii.c
+++ b/drivers/net/ucc_geth_mii.c
@@ -203,9 +203,14 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma
 		if ((res.start >= tempres.start) &&
 		    (res.end <= tempres.end)) {
 			/* set this UCC to be the MII master */
-			const u32 *id = of_get_property(tempnp, "device-id", NULL);
-			if (id == NULL)
-				goto bus_register_fail;
+			const u32 *id;
+
+			id = of_get_property(tempnp, "fsl,ucc", NULL);
+			if (!id) {
+				id = of_get_property(tempnp, "device-id", NULL);
+				if (!id)
+					goto bus_register_fail;
+			}
 
 			ucc_set_qe_mux_mii_mng(*id - 1);
 
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
index e0994f0..03f49c4 100644
--- a/drivers/serial/ucc_uart.c
+++ b/drivers/serial/ucc_uart.c
@@ -1270,10 +1270,18 @@ static int ucc_uart_probe(struct of_device *ofdev,
 
 	/* Get the UCC number (device ID) */
 	/* UCCs are numbered 1-7 */
-	iprop = of_get_property(np, "device-id", NULL);
-	if (!iprop || (*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
-		dev_err(&ofdev->dev,
-			"missing or invalid UCC specified in device tree\n");
+	iprop = of_get_property(np, "fsl,ucc", NULL);
+	if (!iprop) {
+		iprop = of_get_property(np, "device-id", NULL);
+		if (!iprop) {
+			dev_err(&ofdev->dev, "UCC is unspecified in "
+				"device tree\n");
+			return -EINVAL;
+		}
+	}
+
+	if ((*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
+		dev_err(&ofdev->dev, "no support for UCC%u\n", *iprop);
 		kfree(qe_port);
 		return -ENODEV;
 	}
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH 0/8] A bit of new code and sparse cleanups along the way
From: Anton Vorontsov @ 2008-03-11 17:21 UTC (permalink / raw)
  To: linuxppc-dev

Hi all,

Please consider these patches for the 2.6.26.


Thanks,

-- 
Anton Vorontsov
email: cboumailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply

* [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines
From: Anton Vorontsov @ 2008-03-11 17:23 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Scott Wood, linux-mtd
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>

This is needed to support other localbus peripherals, such as
NAND on FSL UPM.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---

Would be great if someone from the MTD community will ack this patch
to go through powerpc trees.

Thanks,

 drivers/mtd/nand/fsl_elbc_nand.c |  219 ++-----------------------------------
 include/asm-powerpc/fsl_lbc.h    |  223 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 235 insertions(+), 207 deletions(-)
 create mode 100644 include/asm-powerpc/fsl_lbc.h

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index b025dfe..378b7aa 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -36,207 +36,12 @@
 #include <linux/mtd/partitions.h>
 
 #include <asm/io.h>
-
+#include <asm/fsl_lbc.h>
 
 #define MAX_BANKS 8
 #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
 #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
 
-struct elbc_bank {
-	__be32 br;             /**< Base Register  */
-#define BR_BA           0xFFFF8000
-#define BR_BA_SHIFT             15
-#define BR_PS           0x00001800
-#define BR_PS_SHIFT             11
-#define BR_PS_8         0x00000800  /* Port Size 8 bit */
-#define BR_PS_16        0x00001000  /* Port Size 16 bit */
-#define BR_PS_32        0x00001800  /* Port Size 32 bit */
-#define BR_DECC         0x00000600
-#define BR_DECC_SHIFT            9
-#define BR_DECC_OFF     0x00000000  /* HW ECC checking and generation off */
-#define BR_DECC_CHK     0x00000200  /* HW ECC checking on, generation off */
-#define BR_DECC_CHK_GEN 0x00000400  /* HW ECC checking and generation on */
-#define BR_WP           0x00000100
-#define BR_WP_SHIFT              8
-#define BR_MSEL         0x000000E0
-#define BR_MSEL_SHIFT            5
-#define BR_MS_GPCM      0x00000000  /* GPCM */
-#define BR_MS_FCM       0x00000020  /* FCM */
-#define BR_MS_SDRAM     0x00000060  /* SDRAM */
-#define BR_MS_UPMA      0x00000080  /* UPMA */
-#define BR_MS_UPMB      0x000000A0  /* UPMB */
-#define BR_MS_UPMC      0x000000C0  /* UPMC */
-#define BR_V            0x00000001
-#define BR_V_SHIFT               0
-#define BR_RES          ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
-
-	__be32 or;             /**< Base Register  */
-#define OR0 0x5004
-#define OR1 0x500C
-#define OR2 0x5014
-#define OR3 0x501C
-#define OR4 0x5024
-#define OR5 0x502C
-#define OR6 0x5034
-#define OR7 0x503C
-
-#define OR_FCM_AM               0xFFFF8000
-#define OR_FCM_AM_SHIFT                 15
-#define OR_FCM_BCTLD            0x00001000
-#define OR_FCM_BCTLD_SHIFT              12
-#define OR_FCM_PGS              0x00000400
-#define OR_FCM_PGS_SHIFT                10
-#define OR_FCM_CSCT             0x00000200
-#define OR_FCM_CSCT_SHIFT                9
-#define OR_FCM_CST              0x00000100
-#define OR_FCM_CST_SHIFT                 8
-#define OR_FCM_CHT              0x00000080
-#define OR_FCM_CHT_SHIFT                 7
-#define OR_FCM_SCY              0x00000070
-#define OR_FCM_SCY_SHIFT                 4
-#define OR_FCM_SCY_1            0x00000010
-#define OR_FCM_SCY_2            0x00000020
-#define OR_FCM_SCY_3            0x00000030
-#define OR_FCM_SCY_4            0x00000040
-#define OR_FCM_SCY_5            0x00000050
-#define OR_FCM_SCY_6            0x00000060
-#define OR_FCM_SCY_7            0x00000070
-#define OR_FCM_RST              0x00000008
-#define OR_FCM_RST_SHIFT                 3
-#define OR_FCM_TRLX             0x00000004
-#define OR_FCM_TRLX_SHIFT                2
-#define OR_FCM_EHTR             0x00000002
-#define OR_FCM_EHTR_SHIFT                1
-};
-
-struct elbc_regs {
-	struct elbc_bank bank[8];
-	u8 res0[0x28];
-	__be32 mar;             /**< UPM Address Register */
-	u8 res1[0x4];
-	__be32 mamr;            /**< UPMA Mode Register */
-	__be32 mbmr;            /**< UPMB Mode Register */
-	__be32 mcmr;            /**< UPMC Mode Register */
-	u8 res2[0x8];
-	__be32 mrtpr;           /**< Memory Refresh Timer Prescaler Register */
-	__be32 mdr;             /**< UPM Data Register */
-	u8 res3[0x4];
-	__be32 lsor;            /**< Special Operation Initiation Register */
-	__be32 lsdmr;           /**< SDRAM Mode Register */
-	u8 res4[0x8];
-	__be32 lurt;            /**< UPM Refresh Timer */
-	__be32 lsrt;            /**< SDRAM Refresh Timer */
-	u8 res5[0x8];
-	__be32 ltesr;           /**< Transfer Error Status Register */
-#define LTESR_BM   0x80000000
-#define LTESR_FCT  0x40000000
-#define LTESR_PAR  0x20000000
-#define LTESR_WP   0x04000000
-#define LTESR_ATMW 0x00800000
-#define LTESR_ATMR 0x00400000
-#define LTESR_CS   0x00080000
-#define LTESR_CC   0x00000001
-#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
-	__be32 ltedr;           /**< Transfer Error Disable Register */
-	__be32 lteir;           /**< Transfer Error Interrupt Register */
-	__be32 lteatr;          /**< Transfer Error Attributes Register */
-	__be32 ltear;           /**< Transfer Error Address Register */
-	u8 res6[0xC];
-	__be32 lbcr;            /**< Configuration Register */
-#define LBCR_LDIS  0x80000000
-#define LBCR_LDIS_SHIFT    31
-#define LBCR_BCTLC 0x00C00000
-#define LBCR_BCTLC_SHIFT   22
-#define LBCR_AHD   0x00200000
-#define LBCR_LPBSE 0x00020000
-#define LBCR_LPBSE_SHIFT   17
-#define LBCR_EPAR  0x00010000
-#define LBCR_EPAR_SHIFT    16
-#define LBCR_BMT   0x0000FF00
-#define LBCR_BMT_SHIFT      8
-#define LBCR_INIT  0x00040000
-	__be32 lcrr;            /**< Clock Ratio Register */
-#define LCRR_DBYP    0x80000000
-#define LCRR_DBYP_SHIFT      31
-#define LCRR_BUFCMDC 0x30000000
-#define LCRR_BUFCMDC_SHIFT   28
-#define LCRR_ECL     0x03000000
-#define LCRR_ECL_SHIFT       24
-#define LCRR_EADC    0x00030000
-#define LCRR_EADC_SHIFT      16
-#define LCRR_CLKDIV  0x0000000F
-#define LCRR_CLKDIV_SHIFT     0
-	u8 res7[0x8];
-	__be32 fmr;             /**< Flash Mode Register */
-#define FMR_CWTO     0x0000F000
-#define FMR_CWTO_SHIFT       12
-#define FMR_BOOT     0x00000800
-#define FMR_ECCM     0x00000100
-#define FMR_AL       0x00000030
-#define FMR_AL_SHIFT          4
-#define FMR_OP       0x00000003
-#define FMR_OP_SHIFT          0
-	__be32 fir;             /**< Flash Instruction Register */
-#define FIR_OP0      0xF0000000
-#define FIR_OP0_SHIFT        28
-#define FIR_OP1      0x0F000000
-#define FIR_OP1_SHIFT        24
-#define FIR_OP2      0x00F00000
-#define FIR_OP2_SHIFT        20
-#define FIR_OP3      0x000F0000
-#define FIR_OP3_SHIFT        16
-#define FIR_OP4      0x0000F000
-#define FIR_OP4_SHIFT        12
-#define FIR_OP5      0x00000F00
-#define FIR_OP5_SHIFT         8
-#define FIR_OP6      0x000000F0
-#define FIR_OP6_SHIFT         4
-#define FIR_OP7      0x0000000F
-#define FIR_OP7_SHIFT         0
-#define FIR_OP_NOP   0x0	/* No operation and end of sequence */
-#define FIR_OP_CA    0x1        /* Issue current column address */
-#define FIR_OP_PA    0x2        /* Issue current block+page address */
-#define FIR_OP_UA    0x3        /* Issue user defined address */
-#define FIR_OP_CM0   0x4        /* Issue command from FCR[CMD0] */
-#define FIR_OP_CM1   0x5        /* Issue command from FCR[CMD1] */
-#define FIR_OP_CM2   0x6        /* Issue command from FCR[CMD2] */
-#define FIR_OP_CM3   0x7        /* Issue command from FCR[CMD3] */
-#define FIR_OP_WB    0x8        /* Write FBCR bytes from FCM buffer */
-#define FIR_OP_WS    0x9        /* Write 1 or 2 bytes from MDR[AS] */
-#define FIR_OP_RB    0xA        /* Read FBCR bytes to FCM buffer */
-#define FIR_OP_RS    0xB        /* Read 1 or 2 bytes to MDR[AS] */
-#define FIR_OP_CW0   0xC        /* Wait then issue FCR[CMD0] */
-#define FIR_OP_CW1   0xD        /* Wait then issue FCR[CMD1] */
-#define FIR_OP_RBW   0xE        /* Wait then read FBCR bytes */
-#define FIR_OP_RSW   0xE        /* Wait then read 1 or 2 bytes */
-	__be32 fcr;             /**< Flash Command Register */
-#define FCR_CMD0     0xFF000000
-#define FCR_CMD0_SHIFT       24
-#define FCR_CMD1     0x00FF0000
-#define FCR_CMD1_SHIFT       16
-#define FCR_CMD2     0x0000FF00
-#define FCR_CMD2_SHIFT        8
-#define FCR_CMD3     0x000000FF
-#define FCR_CMD3_SHIFT        0
-	__be32 fbar;            /**< Flash Block Address Register */
-#define FBAR_BLK     0x00FFFFFF
-	__be32 fpar;            /**< Flash Page Address Register */
-#define FPAR_SP_PI   0x00007C00
-#define FPAR_SP_PI_SHIFT     10
-#define FPAR_SP_MS   0x00000200
-#define FPAR_SP_CI   0x000001FF
-#define FPAR_SP_CI_SHIFT      0
-#define FPAR_LP_PI   0x0003F000
-#define FPAR_LP_PI_SHIFT     12
-#define FPAR_LP_MS   0x00000800
-#define FPAR_LP_CI   0x000007FF
-#define FPAR_LP_CI_SHIFT      0
-	__be32 fbcr;            /**< Flash Byte Count Register */
-#define FBCR_BC      0x00000FFF
-	u8 res11[0x8];
-	u8 res8[0xF00];
-};
-
 struct fsl_elbc_ctrl;
 
 /* mtd information per set */
@@ -261,7 +66,7 @@ struct fsl_elbc_ctrl {
 
 	/* device info */
 	struct device *dev;
-	struct elbc_regs __iomem *regs;
+	struct fsl_lbc_regs __iomem *regs;
 	int irq;
 	wait_queue_head_t irq_wait;
 	unsigned int irq_status; /* status read from LTESR by irq handler */
@@ -322,7 +127,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 	int buf_num;
 
 	ctrl->page = page_addr;
@@ -363,7 +168,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
 	/* Setup the FMR[OP] to execute without write protection */
 	out_be32(&lbc->fmr, priv->fmr | 3);
@@ -406,7 +211,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
 	if (priv->page_size) {
 		out_be32(&lbc->fir,
@@ -439,7 +244,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
 	ctrl->use_mdr = 0;
 
@@ -775,7 +580,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
 	if (ctrl->status != LTESR_CC)
 		return NAND_STATUS_FAIL;
@@ -807,7 +612,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 	unsigned int al;
 
 	/* calculate FMR Address Length field */
@@ -922,7 +727,7 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
 static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 {
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 	struct nand_chip *chip = &priv->chip;
 
 	dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
@@ -986,7 +791,7 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
                                struct device_node *node)
 {
-	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 	struct fsl_elbc_mtd *priv;
 	struct resource res;
 #ifdef CONFIG_MTD_PARTITIONS
@@ -1083,7 +888,7 @@ err:
 
 static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
 {
-	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
 	/* clear event registers */
 	setbits32(&lbc->ltesr, LTESR_NAND_MASK);
@@ -1128,7 +933,7 @@ static int __devexit fsl_elbc_ctrl_remove(struct of_device *ofdev)
 static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
 {
 	struct fsl_elbc_ctrl *ctrl = data;
-	struct elbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 	__be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
 
 	if (status) {
diff --git a/include/asm-powerpc/fsl_lbc.h b/include/asm-powerpc/fsl_lbc.h
new file mode 100644
index 0000000..13a3c28
--- /dev/null
+++ b/include/asm-powerpc/fsl_lbc.h
@@ -0,0 +1,223 @@
+/* Freescale Local Bus Controller
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor
+ *
+ * Authors: Nick Spence <nick.spence@freescale.com>,
+ *          Scott Wood <scottwood@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_FSL_LBC_H
+#define __ASM_FSL_LBC_H
+
+#include <linux/types.h>
+
+struct fsl_lbc_bank {
+	__be32 br;             /**< Base Register  */
+#define BR_BA           0xFFFF8000
+#define BR_BA_SHIFT             15
+#define BR_PS           0x00001800
+#define BR_PS_SHIFT             11
+#define BR_PS_8         0x00000800  /* Port Size 8 bit */
+#define BR_PS_16        0x00001000  /* Port Size 16 bit */
+#define BR_PS_32        0x00001800  /* Port Size 32 bit */
+#define BR_DECC         0x00000600
+#define BR_DECC_SHIFT            9
+#define BR_DECC_OFF     0x00000000  /* HW ECC checking and generation off */
+#define BR_DECC_CHK     0x00000200  /* HW ECC checking on, generation off */
+#define BR_DECC_CHK_GEN 0x00000400  /* HW ECC checking and generation on */
+#define BR_WP           0x00000100
+#define BR_WP_SHIFT              8
+#define BR_MSEL         0x000000E0
+#define BR_MSEL_SHIFT            5
+#define BR_MS_GPCM      0x00000000  /* GPCM */
+#define BR_MS_FCM       0x00000020  /* FCM */
+#define BR_MS_SDRAM     0x00000060  /* SDRAM */
+#define BR_MS_UPMA      0x00000080  /* UPMA */
+#define BR_MS_UPMB      0x000000A0  /* UPMB */
+#define BR_MS_UPMC      0x000000C0  /* UPMC */
+#define BR_V            0x00000001
+#define BR_V_SHIFT               0
+#define BR_RES          ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
+
+	__be32 or;             /**< Base Register  */
+#define OR0 0x5004
+#define OR1 0x500C
+#define OR2 0x5014
+#define OR3 0x501C
+#define OR4 0x5024
+#define OR5 0x502C
+#define OR6 0x5034
+#define OR7 0x503C
+
+#define OR_FCM_AM               0xFFFF8000
+#define OR_FCM_AM_SHIFT                 15
+#define OR_FCM_BCTLD            0x00001000
+#define OR_FCM_BCTLD_SHIFT              12
+#define OR_FCM_PGS              0x00000400
+#define OR_FCM_PGS_SHIFT                10
+#define OR_FCM_CSCT             0x00000200
+#define OR_FCM_CSCT_SHIFT                9
+#define OR_FCM_CST              0x00000100
+#define OR_FCM_CST_SHIFT                 8
+#define OR_FCM_CHT              0x00000080
+#define OR_FCM_CHT_SHIFT                 7
+#define OR_FCM_SCY              0x00000070
+#define OR_FCM_SCY_SHIFT                 4
+#define OR_FCM_SCY_1            0x00000010
+#define OR_FCM_SCY_2            0x00000020
+#define OR_FCM_SCY_3            0x00000030
+#define OR_FCM_SCY_4            0x00000040
+#define OR_FCM_SCY_5            0x00000050
+#define OR_FCM_SCY_6            0x00000060
+#define OR_FCM_SCY_7            0x00000070
+#define OR_FCM_RST              0x00000008
+#define OR_FCM_RST_SHIFT                 3
+#define OR_FCM_TRLX             0x00000004
+#define OR_FCM_TRLX_SHIFT                2
+#define OR_FCM_EHTR             0x00000002
+#define OR_FCM_EHTR_SHIFT                1
+};
+
+struct fsl_lbc_regs {
+	struct fsl_lbc_bank bank[8];
+	u8 res0[0x28];
+	__be32 mar;             /**< UPM Address Register */
+	u8 res1[0x4];
+	__be32 mamr;            /**< UPMA Mode Register */
+	__be32 mbmr;            /**< UPMB Mode Register */
+	__be32 mcmr;            /**< UPMC Mode Register */
+	u8 res2[0x8];
+	__be32 mrtpr;           /**< Memory Refresh Timer Prescaler Register */
+	__be32 mdr;             /**< UPM Data Register */
+	u8 res3[0x4];
+	__be32 lsor;            /**< Special Operation Initiation Register */
+	__be32 lsdmr;           /**< SDRAM Mode Register */
+	u8 res4[0x8];
+	__be32 lurt;            /**< UPM Refresh Timer */
+	__be32 lsrt;            /**< SDRAM Refresh Timer */
+	u8 res5[0x8];
+	__be32 ltesr;           /**< Transfer Error Status Register */
+#define LTESR_BM   0x80000000
+#define LTESR_FCT  0x40000000
+#define LTESR_PAR  0x20000000
+#define LTESR_WP   0x04000000
+#define LTESR_ATMW 0x00800000
+#define LTESR_ATMR 0x00400000
+#define LTESR_CS   0x00080000
+#define LTESR_CC   0x00000001
+#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+	__be32 ltedr;           /**< Transfer Error Disable Register */
+	__be32 lteir;           /**< Transfer Error Interrupt Register */
+	__be32 lteatr;          /**< Transfer Error Attributes Register */
+	__be32 ltear;           /**< Transfer Error Address Register */
+	u8 res6[0xC];
+	__be32 lbcr;            /**< Configuration Register */
+#define LBCR_LDIS  0x80000000
+#define LBCR_LDIS_SHIFT    31
+#define LBCR_BCTLC 0x00C00000
+#define LBCR_BCTLC_SHIFT   22
+#define LBCR_AHD   0x00200000
+#define LBCR_LPBSE 0x00020000
+#define LBCR_LPBSE_SHIFT   17
+#define LBCR_EPAR  0x00010000
+#define LBCR_EPAR_SHIFT    16
+#define LBCR_BMT   0x0000FF00
+#define LBCR_BMT_SHIFT      8
+#define LBCR_INIT  0x00040000
+	__be32 lcrr;            /**< Clock Ratio Register */
+#define LCRR_DBYP    0x80000000
+#define LCRR_DBYP_SHIFT      31
+#define LCRR_BUFCMDC 0x30000000
+#define LCRR_BUFCMDC_SHIFT   28
+#define LCRR_ECL     0x03000000
+#define LCRR_ECL_SHIFT       24
+#define LCRR_EADC    0x00030000
+#define LCRR_EADC_SHIFT      16
+#define LCRR_CLKDIV  0x0000000F
+#define LCRR_CLKDIV_SHIFT     0
+	u8 res7[0x8];
+	__be32 fmr;             /**< Flash Mode Register */
+#define FMR_CWTO     0x0000F000
+#define FMR_CWTO_SHIFT       12
+#define FMR_BOOT     0x00000800
+#define FMR_ECCM     0x00000100
+#define FMR_AL       0x00000030
+#define FMR_AL_SHIFT          4
+#define FMR_OP       0x00000003
+#define FMR_OP_SHIFT          0
+	__be32 fir;             /**< Flash Instruction Register */
+#define FIR_OP0      0xF0000000
+#define FIR_OP0_SHIFT        28
+#define FIR_OP1      0x0F000000
+#define FIR_OP1_SHIFT        24
+#define FIR_OP2      0x00F00000
+#define FIR_OP2_SHIFT        20
+#define FIR_OP3      0x000F0000
+#define FIR_OP3_SHIFT        16
+#define FIR_OP4      0x0000F000
+#define FIR_OP4_SHIFT        12
+#define FIR_OP5      0x00000F00
+#define FIR_OP5_SHIFT         8
+#define FIR_OP6      0x000000F0
+#define FIR_OP6_SHIFT         4
+#define FIR_OP7      0x0000000F
+#define FIR_OP7_SHIFT         0
+#define FIR_OP_NOP   0x0	/* No operation and end of sequence */
+#define FIR_OP_CA    0x1        /* Issue current column address */
+#define FIR_OP_PA    0x2        /* Issue current block+page address */
+#define FIR_OP_UA    0x3        /* Issue user defined address */
+#define FIR_OP_CM0   0x4        /* Issue command from FCR[CMD0] */
+#define FIR_OP_CM1   0x5        /* Issue command from FCR[CMD1] */
+#define FIR_OP_CM2   0x6        /* Issue command from FCR[CMD2] */
+#define FIR_OP_CM3   0x7        /* Issue command from FCR[CMD3] */
+#define FIR_OP_WB    0x8        /* Write FBCR bytes from FCM buffer */
+#define FIR_OP_WS    0x9        /* Write 1 or 2 bytes from MDR[AS] */
+#define FIR_OP_RB    0xA        /* Read FBCR bytes to FCM buffer */
+#define FIR_OP_RS    0xB        /* Read 1 or 2 bytes to MDR[AS] */
+#define FIR_OP_CW0   0xC        /* Wait then issue FCR[CMD0] */
+#define FIR_OP_CW1   0xD        /* Wait then issue FCR[CMD1] */
+#define FIR_OP_RBW   0xE        /* Wait then read FBCR bytes */
+#define FIR_OP_RSW   0xE        /* Wait then read 1 or 2 bytes */
+	__be32 fcr;             /**< Flash Command Register */
+#define FCR_CMD0     0xFF000000
+#define FCR_CMD0_SHIFT       24
+#define FCR_CMD1     0x00FF0000
+#define FCR_CMD1_SHIFT       16
+#define FCR_CMD2     0x0000FF00
+#define FCR_CMD2_SHIFT        8
+#define FCR_CMD3     0x000000FF
+#define FCR_CMD3_SHIFT        0
+	__be32 fbar;            /**< Flash Block Address Register */
+#define FBAR_BLK     0x00FFFFFF
+	__be32 fpar;            /**< Flash Page Address Register */
+#define FPAR_SP_PI   0x00007C00
+#define FPAR_SP_PI_SHIFT     10
+#define FPAR_SP_MS   0x00000200
+#define FPAR_SP_CI   0x000001FF
+#define FPAR_SP_CI_SHIFT      0
+#define FPAR_LP_PI   0x0003F000
+#define FPAR_LP_PI_SHIFT     12
+#define FPAR_LP_MS   0x00000800
+#define FPAR_LP_CI   0x000007FF
+#define FPAR_LP_CI_SHIFT      0
+	__be32 fbcr;            /**< Flash Byte Count Register */
+#define FBCR_BC      0x00000FFF
+	u8 res11[0x8];
+	u8 res8[0xF00];
+};
+
+#endif /* __ASM_FSL_LBC_H */
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>

These will be used by the FSL UPM NAND driver.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 arch/powerpc/Kconfig          |    5 ++
 arch/powerpc/sysdev/Makefile  |    1 +
 arch/powerpc/sysdev/fsl_lbc.c |   99 +++++++++++++++++++++++++++++++++++++++++
 include/asm-powerpc/fsl_lbc.h |   63 ++++++++++++++++++++++++++
 4 files changed, 168 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/sysdev/fsl_lbc.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ef12db0..9c68592 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -491,6 +491,11 @@ config FSL_PCI
  	bool
 	select PPC_INDIRECT_PCI
 
+config FSL_LBC
+	bool
+	help
+	  Freescale Localbus support
+
 # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
 config MCA
 	bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 15f3e85..62b6ef0 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_U3_DART)		+= dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o
+obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
 obj-$(CONFIG_RAPIDIO)		+= fsl_rio.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
new file mode 100644
index 0000000..b59f2f4
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -0,0 +1,99 @@
+/*
+ * Freescale UPM routines.
+ *
+ * Copyright (c) 2007-2008  MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <asm/fsl_lbc.h>
+
+spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
+
+struct fsl_lbc_regs __iomem *fsl_lbc_regs;
+EXPORT_SYMBOL(fsl_lbc_regs);
+
+static char __initdata *compat_lbc[] = {
+	"fsl,pq2-localbus",
+	"fsl,pq2pro-localbus",
+	"fsl,pq3-localbus",
+	"fsl,elbc",
+};
+
+static int __init fsl_lbc_init(void)
+{
+	struct device_node *lbus;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
+		lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
+		if (lbus)
+			goto found;
+	}
+	return -ENODEV;
+
+found:
+	fsl_lbc_regs = of_iomap(lbus, 0);
+	of_node_put(lbus);
+	if (!fsl_lbc_regs)
+		return -ENOMEM;
+	return 0;
+}
+arch_initcall(fsl_lbc_init);
+
+int fsl_upm_find(u32 base, struct fsl_upm *upm)
+{
+	int i;
+	__be32 br;
+	__be32 or;
+
+	if (!fsl_lbc_regs)
+		return -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
+		br = in_be32(&fsl_lbc_regs->bank[i].br);
+		or = in_be32(&fsl_lbc_regs->bank[i].or);
+
+		if (br & BR_V && (br & or & BR_BA) == base)
+			goto found;
+	}
+
+	return -ENOENT;
+found:
+	switch (br & BR_MSEL) {
+	case BR_MS_UPMA:
+		upm->mxmr = &fsl_lbc_regs->mamr;
+		break;
+	case BR_MS_UPMB:
+		upm->mxmr = &fsl_lbc_regs->mbmr;
+		break;
+	case BR_MS_UPMC:
+		upm->mxmr = &fsl_lbc_regs->mcmr;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (br & BR_PS) {
+	case BR_PS_8:
+		upm->width = 8;
+		break;
+	case BR_PS_16:
+		upm->width = 16;
+		break;
+	case BR_PS_32:
+		upm->width = 32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff --git a/include/asm-powerpc/fsl_lbc.h b/include/asm-powerpc/fsl_lbc.h
index 13a3c28..a6b99a3 100644
--- a/include/asm-powerpc/fsl_lbc.h
+++ b/include/asm-powerpc/fsl_lbc.h
@@ -24,6 +24,8 @@
 #define __ASM_FSL_LBC_H
 
 #include <linux/types.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
 
 struct fsl_lbc_bank {
 	__be32 br;             /**< Base Register  */
@@ -98,6 +100,11 @@ struct fsl_lbc_regs {
 	__be32 mar;             /**< UPM Address Register */
 	u8 res1[0x4];
 	__be32 mamr;            /**< UPMA Mode Register */
+#define MxMR_OP_NO	(0 << 28) /**< normal operation */
+#define MxMR_OP_WA	(1 << 28) /**< write array */
+#define MxMR_OP_RA	(2 << 28) /**< read array */
+#define MxMR_OP_RP	(3 << 28) /**< run pattern */
+#define MxMR_MAD	0x3f      /**< machine address */
 	__be32 mbmr;            /**< UPMB Mode Register */
 	__be32 mcmr;            /**< UPMC Mode Register */
 	u8 res2[0x8];
@@ -220,4 +227,60 @@ struct fsl_lbc_regs {
 	u8 res8[0xF00];
 };
 
+extern struct fsl_lbc_regs __iomem *fsl_lbc_regs;
+extern spinlock_t fsl_lbc_lock;
+
+/*
+ * FSL UPM routines
+ */
+struct fsl_upm {
+	__be32 __iomem *mxmr;
+	int width;
+};
+
+extern int fsl_upm_find(u32 base, struct fsl_upm *upm);
+
+static inline void fsl_upm_start_pattern(struct fsl_upm *upm, u8 pat_offset)
+{
+	clrsetbits_be32(upm->mxmr, MxMR_MAD, MxMR_OP_RP | pat_offset);
+}
+
+static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
+{
+	clrbits32(upm->mxmr, MxMR_OP_RP);
+
+	while (in_be32(upm->mxmr) & MxMR_OP_RP)
+		cpu_relax();
+}
+
+static inline int fsl_upm_run_pattern(struct fsl_upm *upm,
+				      void __iomem *io_base, u32 mar)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fsl_lbc_lock, flags);
+
+	out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
+
+	switch (upm->width) {
+	case 8:
+		out_8(io_base, 0x0);
+		break;
+	case 16:
+		out_be16(io_base, 0x0);
+		break;
+	case 32:
+		out_be32(io_base, 0x0);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	spin_unlock_irqrestore(&fsl_lbc_lock, flags);
+
+	return ret;
+}
+
 #endif /* __ASM_FSL_LBC_H */
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH 3/8] [POWERPC] qe_lib: implement qe_muram_offset
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>

qe_muram_offset is the reverse of the qe_muram_addr, will be
used for the Freescale QE USB Host Controller driver.

This patch also moves qe_muram_addr into the qe.h header, plus
adds __iomem hints to use with sparse.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 arch/powerpc/sysdev/qe_lib/qe.c |    8 +-------
 include/asm-powerpc/immap_qe.h  |    2 +-
 include/asm-powerpc/qe.h        |   11 ++++++++++-
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 6efbd5e..b444b1d 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -55,7 +55,7 @@ struct qe_snum {
 /* We allocate this here because it is used almost exclusively for
  * the communication processor devices.
  */
-struct qe_immap *qe_immr = NULL;
+struct qe_immap __iomem *qe_immr;
 EXPORT_SYMBOL(qe_immr);
 
 static struct qe_snum snums[QE_NUM_OF_SNUM];	/* Dynamically allocated SNUMs */
@@ -415,12 +415,6 @@ void qe_muram_dump(void)
 }
 EXPORT_SYMBOL(qe_muram_dump);
 
-void *qe_muram_addr(unsigned long offset)
-{
-	return (void *)&qe_immr->muram[offset];
-}
-EXPORT_SYMBOL(qe_muram_addr);
-
 /* The maximum number of RISCs we support */
 #define MAX_QE_RISC     2
 
diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h
index 82a4526..924aefb 100644
--- a/include/asm-powerpc/immap_qe.h
+++ b/include/asm-powerpc/immap_qe.h
@@ -468,7 +468,7 @@ struct qe_immap {
 	u8			res18[0xC0000];	/* 0x140000 - 0x200000 */
 } __attribute__ ((packed));
 
-extern struct qe_immap *qe_immr;
+extern struct qe_immap __iomem *qe_immr;
 extern phys_addr_t get_qe_base(void);
 
 static inline unsigned long immrbar_virt_to_phys(void *address)
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index 430dc77..398534c 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -92,7 +92,16 @@ unsigned long qe_muram_alloc(int size, int align);
 int qe_muram_free(unsigned long offset);
 unsigned long qe_muram_alloc_fixed(unsigned long offset, int size);
 void qe_muram_dump(void);
-void *qe_muram_addr(unsigned long offset);
+
+static inline void __iomem *qe_muram_addr(unsigned long offset)
+{
+	return (void __iomem *)&qe_immr->muram[offset];
+}
+
+static inline unsigned long qe_muram_offset(void __iomem *addr)
+{
+	return addr - (void __iomem *)qe_immr->muram;
+}
 
 /* Structure that defines QE firmware binary files.
  *
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH 4/8] [POWERPC] immap_qe.h should include asm/io.h
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>

Headers should include prototypes they use, otherwise build will
break if we use it without explicitly including io.h:

  CC      arch/powerpc/sysdev/qe_lib/gtm.o
In file included from include/asm/qe.h:20,
                 from arch/powerpc/sysdev/qe_lib/gtm.c:18:
include/asm/immap_qe.h: In function ‘immrbar_virt_to_phys’:
include/asm/immap_qe.h:480: error: implicit declaration of function ‘virt_to_phys’
make[2]: *** [arch/powerpc/sysdev/qe_lib/gtm.o] Error 1
make[1]: *** [arch/powerpc/sysdev/qe_lib] Error 2

gtm.c needs qe.h (which includes immap_qe.h) to use qe_get_brg_clk().

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 include/asm-powerpc/immap_qe.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h
index 924aefb..7b6f411 100644
--- a/include/asm-powerpc/immap_qe.h
+++ b/include/asm-powerpc/immap_qe.h
@@ -20,6 +20,7 @@
 #ifdef __KERNEL__
 
 #include <linux/kernel.h>
+#include <asm/io.h>
 
 #define QE_IMMAP_SIZE	(1024 * 1024)	/* 1MB from 1MB+IMMR */
 
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH 5/8] [POWERPC] qe_lib: export qe_get_brg_clk()
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>

qe_get_brg_clk() will be used by the fsl_gtm routines.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 arch/powerpc/sysdev/qe_lib/qe.c |    5 +++--
 include/asm-powerpc/qe.h        |    1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index b444b1d..2061c46 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -156,7 +156,7 @@ EXPORT_SYMBOL(qe_issue_cmd);
  */
 static unsigned int brg_clk = 0;
 
-unsigned int get_brg_clk(void)
+unsigned int qe_get_brg_clk(void)
 {
 	struct device_node *qe;
 	unsigned int size;
@@ -180,6 +180,7 @@ unsigned int get_brg_clk(void)
 
 	return brg_clk;
 }
+EXPORT_SYMBOL(qe_get_brg_clk);
 
 /* Program the BRG to the given sampling rate and multiplier
  *
@@ -197,7 +198,7 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
 	if ((brg < QE_BRG1) || (brg > QE_BRG16))
 		return -EINVAL;
 
-	divisor = get_brg_clk() / (rate * multiplier);
+	divisor = qe_get_brg_clk() / (rate * multiplier);
 
 	if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
 		div16 = QE_BRGC_DIV16;
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index 398534c..c3be6e2 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -85,6 +85,7 @@ extern int par_io_data_set(u8 port, u8 pin, u8 val);
 /* QE internal API */
 int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
 enum qe_clock qe_clock_source(const char *source);
+unsigned int qe_get_brg_clk(void);
 int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
 int qe_get_snum(void);
 void qe_put_snum(u8 snum);
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>

GTM stands for General-purpose Timers Module and able to generate
timer{1,2,3,4} interrupts.

There are several limitations in this support:
1. Cascaded (32 bit) timers unimplemented (1-2, 3-4).
   This is straightforward to implement when needed, two timers should
   be marked as "requested" and configured as appropriate.
2. Super-cascaded (64 bit) timers unimplemented (1-2-3-4).
   This is also straightforward to implement when needed, all timers
   should be marked as "requested" and configured as appropriate.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 Documentation/powerpc/booting-without-of.txt |   27 +++-
 arch/powerpc/Kconfig                         |    5 +
 arch/powerpc/sysdev/Makefile                 |    1 +
 arch/powerpc/sysdev/fsl_gtm.c                |  263 ++++++++++++++++++++++++++
 arch/powerpc/sysdev/qe_lib/Kconfig           |    5 +
 arch/powerpc/sysdev/qe_lib/Makefile          |    1 +
 arch/powerpc/sysdev/qe_lib/gtm.c             |   47 +++++
 include/asm-powerpc/fsl_gtm.h                |  138 ++++++++++++++
 8 files changed, 486 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/sysdev/fsl_gtm.c
 create mode 100644 arch/powerpc/sysdev/qe_lib/gtm.c
 create mode 100644 include/asm-powerpc/fsl_gtm.h

diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 8ae57f2..b506245 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -57,7 +57,8 @@ Table of Contents
       n) 4xx/Axon EMAC ethernet nodes
       o) Xilinx IP cores
       p) Freescale Synchronous Serial Interface
-	  q) USB EHCI controllers
+      q) USB EHCI controllers
+      r) Freescale General-purpose Timers Module
 
   VII - Specifying interrupt information for devices
     1) interrupts property
@@ -2811,6 +2812,30 @@ platforms are moved over to use the flattened-device-tree model.
 		   big-endian;
 	   };
 
+    r) Freescale General-purpose Timers Module
+
+    Required properties:
+      - compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for QE
+                     GTMs).
+      - reg : should contain gtm registers location and length (0x40).
+      - interrupts : should contain four interrupts.
+      - interrupt-parent : interrupt source phandle.
+
+    Example:
+
+    gtm@500 {
+    	compatible = "fsl,gtm";
+    	reg = <0x500 0x40>;
+    	interrupts = <90 8 78 8 84 8 72 8>;
+    	interrupt-parent = <&ipic>;
+    };
+
+    gtm@440 {
+    	compatible = "fsl,qe-gtm", "fsl,gtm";
+    	reg = <0x440 0x40>;
+    	interrupts = <12 13 14 15>;
+    	interrupt-parent = <&qeic>;
+    };
 
    More devices will be defined as this spec matures.
 
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 9c68592..0b27cbd 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -496,6 +496,11 @@ config FSL_LBC
 	help
 	  Freescale Localbus support
 
+config FSL_GTM
+	bool
+	help
+	  Freescale General-purpose Timers support
+
 # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
 config MCA
 	bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 62b6ef0..a7e8da4 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
+obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o
 obj-$(CONFIG_RAPIDIO)		+= fsl_rio.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
new file mode 100644
index 0000000..975fe4e
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -0,0 +1,263 @@
+/*
+ * Freescale General-purpose Timers Module
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ *               Shlomi Gridish <gridish@freescale.com>
+ *               Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ *               Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <asm/fsl_gtm.h>
+
+struct gtm_timer *gtm_get_timer(int width)
+{
+	struct device_node *np;
+	struct gtm *gtm = NULL;
+	int i;
+
+	if (width != 16)
+		return ERR_PTR(-ENOSYS);
+
+	for_each_compatible_node(np, NULL, "fsl,gtm") {
+		if (!np->data) {
+			WARN_ON(1);
+			continue;
+		}
+		gtm = np->data;
+
+		spin_lock_irq(&gtm->lock);
+
+		for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
+			if (!gtm->timers[i].requested) {
+				gtm->timers[i].requested = true;
+				spin_unlock_irq(&gtm->lock);
+				of_node_put(np);
+				return &gtm->timers[i];
+			}
+		}
+
+		spin_unlock_irq(&gtm->lock);
+	}
+
+	if (gtm)
+		return ERR_PTR(-EBUSY);
+	return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL(gtm_get_timer);
+
+void gtm_put_timer(struct gtm_timer *tmr)
+{
+	spin_lock_irq(&tmr->gtm->lock);
+
+	tmr->requested = false;
+
+	spin_unlock_irq(&tmr->gtm->lock);
+}
+EXPORT_SYMBOL(gtm_put_timer);
+
+int gtm_reset_ref_timer_16(struct gtm_timer *tmr, unsigned int hz, u16 ref,
+			   bool ffr)
+{
+	struct gtm *gtm = tmr->gtm;
+	int num = tmr - &gtm->timers[0];
+	unsigned long flags;
+	unsigned int prescaler;
+	u8 iclk = GTMDR_ICLK_ICLK;
+	u8 psr;
+	u8 sps;
+
+	prescaler = gtm->clock / hz;
+
+	/*
+	 * We have two 8 bit prescalers -- primary and secondary (psr, sps),
+	 * plus "slow go" mode (clk / 16). So, total prescale value is
+	 * 16 * (psr + 1) * (sps + 1).
+	 */
+	if (prescaler > 256 * 256 * 16)
+		return -EINVAL;
+
+	if (prescaler > 256 * 256) {
+		iclk = GTMDR_ICLK_SLGO;
+		prescaler /= 16;
+	}
+
+	if (prescaler > 256) {
+		psr = 256 - 1;
+		sps = prescaler / 256 - 1;
+	} else {
+		psr = prescaler - 1;
+		sps = 1 - 1;
+	}
+
+	spin_lock_irqsave(&gtm->lock, flags);
+
+	/*
+	 * Properly reset timers: stop, reset, set up prescalers, reference
+	 * value and clear event register.
+	 */
+	clrsetbits_8(tmr->gtcfr, ~(GTCFR_STP(num) | GTCFR_RST(num)),
+				 GTCFR_STP(num) | GTCFR_RST(num));
+
+	setbits8(tmr->gtcfr, GTCFR_STP(num));
+
+	out_be16(tmr->gtpsr, psr);
+	clrsetbits_be16(tmr->gtmdr, 0xFFFF, iclk | GTMDR_SPS(sps) |
+			GTMDR_ORI | (ffr ? GTMDR_FFR : 0));
+	out_be16(tmr->gtcnr, 0);
+	out_be16(tmr->gtrfr, ref);
+	out_be16(tmr->gtevr, 0xFFFF);
+
+	/* Let it be. */
+	clrbits8(tmr->gtcfr, GTCFR_STP(num));
+
+	spin_unlock_irqrestore(&gtm->lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(gtm_reset_ref_timer_16);
+
+void gtm_stop_timer_16(struct gtm_timer *tmr)
+{
+	struct gtm *gtm = tmr->gtm;
+	int num = tmr - &gtm->timers[0];
+	unsigned long flags;
+
+	spin_lock_irqsave(&gtm->lock, flags);
+
+	setbits8(tmr->gtcfr, GTCFR_STP(num));
+
+	spin_unlock_irqrestore(&gtm->lock, flags);
+}
+EXPORT_SYMBOL(gtm_stop_timer_16);
+
+static void __init gtm_set_shortcuts(struct gtm_timer *timers,
+				     struct gtm_timers_regs __iomem *regs)
+{
+	/*
+	 * Yeah, I don't like this either, but timers' registers a bit messed,
+	 * so we have to provide shortcuts to write timer independent code.
+	 * Alternative option is to create gt*() accessors, but that will be
+	 * even uglier and cryptic.
+	 */
+	timers[0].gtcfr = &regs->gtcfr1;
+	timers[0].gtmdr = &regs->gtmdr1;
+	timers[0].gtpsr = &regs->gtpsr1;
+	timers[0].gtcnr = &regs->gtcnr1;
+	timers[0].gtrfr = &regs->gtrfr1;
+	timers[0].gtevr = &regs->gtevr1;
+
+	timers[1].gtcfr = &regs->gtcfr1;
+	timers[1].gtmdr = &regs->gtmdr2;
+	timers[1].gtpsr = &regs->gtpsr2;
+	timers[1].gtcnr = &regs->gtcnr2;
+	timers[1].gtrfr = &regs->gtrfr2;
+	timers[1].gtevr = &regs->gtevr2;
+
+	timers[2].gtcfr = &regs->gtcfr2;
+	timers[2].gtmdr = &regs->gtmdr3;
+	timers[2].gtpsr = &regs->gtpsr3;
+	timers[2].gtcnr = &regs->gtcnr3;
+	timers[2].gtrfr = &regs->gtrfr3;
+	timers[2].gtevr = &regs->gtevr3;
+
+	timers[3].gtcfr = &regs->gtcfr2;
+	timers[3].gtmdr = &regs->gtmdr4;
+	timers[3].gtpsr = &regs->gtpsr4;
+	timers[3].gtcnr = &regs->gtcnr4;
+	timers[3].gtrfr = &regs->gtrfr4;
+	timers[3].gtevr = &regs->gtevr4;
+}
+
+static int __init gtm_get_clock(struct gtm *gtm, struct device_node *np)
+{
+	struct device_node *parent;
+	const u32 *clock;
+	int size;
+	int ret;
+
+	parent = of_get_parent(np);
+	if (!parent) {
+		pr_err("%s: no parent?\n", np->full_name);
+		return -EINVAL;
+	}
+
+	clock = of_get_property(parent, "clock-frequency", &size);
+	if (!clock || size != sizeof(*clock)) {
+		pr_err("%s: no clock-frequency for %s\n",
+		       np->full_name, parent->full_name);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	ret = 0;
+	gtm->clock = *clock;
+err:
+	of_node_put(parent);
+	return ret;
+}
+
+static int __init gtm_init_gtm(void)
+{
+	struct device_node *np;
+
+	for_each_compatible_node(np, NULL, "fsl,gtm") {
+		int i;
+		struct gtm *gtm;
+
+		gtm = kzalloc(sizeof(*gtm), GFP_KERNEL);
+		if (!gtm) {
+			pr_err("%s: unable to allocate memory\n",
+				np->full_name);
+			continue;
+		}
+
+		spin_lock_init(&gtm->lock);
+
+		if (gtm_get_clock(gtm, np))
+			goto err;
+
+		for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
+			int ret;
+			struct resource irq;
+
+			ret = of_irq_to_resource(np, i, &irq);
+			if (ret == NO_IRQ) {
+				pr_err("%s: not enough interrupts specified\n",
+				       np->full_name);
+				goto err;
+			}
+			gtm->timers[i].irq = irq.start;
+			gtm->timers[i].gtm = gtm;
+		}
+
+		gtm->regs = of_iomap(np, 0);
+		if (!gtm->regs) {
+			pr_err("%s: unable to iomap registers\n",
+			       np->full_name);
+			goto err;
+		}
+
+		gtm_set_shortcuts(gtm->timers, gtm->regs);
+
+		/* We don't want to lose the node and its ->data */
+		of_node_get(np);
+		np->data = gtm;
+
+		continue;
+err:
+		kfree(gtm);
+	}
+	return 0;
+}
+arch_initcall(gtm_init_gtm);
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index adc6621..c1f2849 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -20,3 +20,8 @@ config UCC
 	bool
 	default y if UCC_FAST || UCC_SLOW
 
+config QE_GTM
+	bool
+	default y if FSL_GTM
+	help
+	  QE General-purpose Timers Module support
diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/sysdev/qe_lib/Makefile
index 874fe1a..3297a52 100644
--- a/arch/powerpc/sysdev/qe_lib/Makefile
+++ b/arch/powerpc/sysdev/qe_lib/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_ic.o qe_io.o
 obj-$(CONFIG_UCC)	+= ucc.o
 obj-$(CONFIG_UCC_SLOW)	+= ucc_slow.o
 obj-$(CONFIG_UCC_FAST)	+= ucc_fast.o
+obj-$(CONFIG_QE_GTM)	+= gtm.o
diff --git a/arch/powerpc/sysdev/qe_lib/gtm.c b/arch/powerpc/sysdev/qe_lib/gtm.c
new file mode 100644
index 0000000..2ce9c25
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/gtm.c
@@ -0,0 +1,47 @@
+/*
+ * QE General-purpose Timers Module
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ *               Shlomi Gridish <gridish@freescale.com>
+ *               Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ *               Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <asm/qe.h>
+#include <asm/fsl_gtm.h>
+
+/*
+ * For now we just fixing up the clock -- it's brg-frequency for QE
+ * chips, generic code does not and should not know these details.
+ *
+ * Later we might want to set up BRGs, when QE will actually use
+ * them (there are TIMERCS bits in the CMXGCR register, but today
+ * these bits seem to be no-ops.
+ */
+static int __init qe_init_gtm(void)
+{
+	struct device_node *np;
+
+	for_each_compatible_node(np, NULL, "fsl,qe-gtm") {
+		struct gtm *gtm = np->data;
+
+		if (!gtm) {
+			/* fsl,qe-gtm without fsl,gtm compatible? */
+			WARN_ON(1);
+			continue;
+		}
+
+		gtm->clock = qe_get_brg_clk();
+	}
+
+	return 0;
+}
+arch_initcall(qe_init_gtm);
diff --git a/include/asm-powerpc/fsl_gtm.h b/include/asm-powerpc/fsl_gtm.h
new file mode 100644
index 0000000..bdb9d5a
--- /dev/null
+++ b/include/asm-powerpc/fsl_gtm.h
@@ -0,0 +1,138 @@
+/*
+ * Freescale General-purpose Timers Module
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ *               Shlomi Gridish <gridish@freescale.com>
+ *               Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ *               Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_FSL_GTM_H
+#define __ASM_FSL_GTM_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+
+#define GTCFR_STP(x)		((x) & 1 ? 1 << 5 : 1 << 1)
+#define GTCFR_RST(x)		((x) & 1 ? 1 << 4 : 1 << 0)
+
+#define GTMDR_ICLK_MASK		(3 << 1)
+#define GTMDR_ICLK_ICAS		(0 << 1)
+#define GTMDR_ICLK_ICLK		(1 << 1)
+#define GTMDR_ICLK_SLGO		(2 << 1)
+#define GTMDR_FFR		(1 << 3)
+#define GTMDR_ORI		(1 << 4)
+#define GTMDR_SPS(x)		((x) << 8)
+
+struct gtm_timers_regs {
+	u8	gtcfr1;		/* Timer 1, Timer 2 global config register */
+	u8	res0[0x3];
+	u8	gtcfr2;		/* Timer 3, timer 4 global config register */
+	u8	res1[0xB];
+	__be16	gtmdr1;		/* Timer 1 mode register */
+	__be16	gtmdr2;		/* Timer 2 mode register */
+	__be16	gtrfr1;		/* Timer 1 reference register */
+	__be16	gtrfr2;		/* Timer 2 reference register */
+	__be16	gtcpr1;		/* Timer 1 capture register */
+	__be16	gtcpr2;		/* Timer 2 capture register */
+	__be16	gtcnr1;		/* Timer 1 counter */
+	__be16	gtcnr2;		/* Timer 2 counter */
+	__be16	gtmdr3;		/* Timer 3 mode register */
+	__be16	gtmdr4;		/* Timer 4 mode register */
+	__be16	gtrfr3;		/* Timer 3 reference register */
+	__be16	gtrfr4;		/* Timer 4 reference register */
+	__be16	gtcpr3;		/* Timer 3 capture register */
+	__be16	gtcpr4;		/* Timer 4 capture register */
+	__be16	gtcnr3;		/* Timer 3 counter */
+	__be16	gtcnr4;		/* Timer 4 counter */
+	__be16	gtevr1;		/* Timer 1 event register */
+	__be16	gtevr2;		/* Timer 2 event register */
+	__be16	gtevr3;		/* Timer 3 event register */
+	__be16	gtevr4;		/* Timer 4 event register */
+	__be16	gtpsr1;		/* Timer 1 prescale register */
+	__be16	gtpsr2;		/* Timer 2 prescale register */
+	__be16	gtpsr3;		/* Timer 3 prescale register */
+	__be16	gtpsr4;		/* Timer 4 prescale register */
+	u8 res2[0x40];
+} __attribute__ ((packed));
+
+struct gtm_timer {
+	unsigned int irq;
+
+	struct gtm *gtm;
+	bool requested;
+	u8 __iomem *gtcfr;
+	__be16 __iomem *gtmdr;
+	__be16 __iomem *gtpsr;
+	__be16 __iomem *gtcnr;
+	__be16 __iomem *gtrfr;
+	__be16 __iomem *gtevr;
+};
+
+struct gtm {
+	unsigned int clock;
+	struct gtm_timers_regs __iomem *regs;
+	struct gtm_timer timers[4];
+	spinlock_t lock;
+};
+
+/**
+ * gtm_get_timer - request GTM timer for use with the rest of GTM API
+ * @width:	timer width (only 16 bits wide timers implemented so far)
+ *
+ * This function reserves GTM timer for later use. It returns gtm_timer
+ * structure to use with the rest of GTM API, you should use timer->irq
+ * to manage timer interrupt.
+ */
+extern struct gtm_timer *gtm_get_timer(int width);
+
+/**
+ * gtm_put_timer - release GTM timer
+ * @width:	timer width (only 16 bits wide timers implemented so far)
+ *
+ * This function releases GTM timer sp others might request it.
+ */
+extern void gtm_put_timer(struct gtm_timer *tmr);
+
+/**
+ * gtm_reset_ref_timer_16 - (re)set single (16 bits) timer in reference mode
+ * @tmr:	pointer to the gtm_timer structure obtained from gtm_get_timer
+ * @hz:		timer rate in Hz
+ * @ref:	refernce value
+ * @ffr:	free run flag
+ *
+ * Thus function (re)sets GTM timer so it counts up to the reference value and
+ * fires the interrupt when the value is reached. If ffr flag is set, timer
+ * will also reset itself upon reference value, otherwise it continues to
+ * increment.
+ */
+extern int gtm_reset_ref_timer_16(struct gtm_timer *tmr, unsigned int hz,
+				  u16 ref, bool ffr);
+
+/**
+ * gtm_ack_ref_timer_16 - acknowledge timer event (free-run timers only)
+ * @tmr:	pointer to the gtm_timer structure obtained from gtm_get_timer
+ *
+ * Thus function used to acknowledge timer interrupt event, use it inside the
+ * interrupt handler.
+ */
+static inline void gtm_ack_ref_timer_16(struct gtm_timer *tmr)
+{
+	out_be16(tmr->gtevr, 0xFFFF);
+}
+
+/**
+ * gtm_stop_timer_16 - stop single timer
+ * @tmr:	pointer to the gtm_timer structure obtained from gtm_get_timer
+ *
+ * This function simply stops the GTM timer.
+ */
+extern void gtm_stop_timer_16(struct gtm_timer *tmr);
+
+#endif /* __ASM_FSL_GTM_H */
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH 7/8] [POWERPC] qe_lib: add support for QE USB
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>

I believe QE USB clocks routing is qe_lib authority, so usb.c
created. Also, now cmxgcr needs its own lock.

This patch also fixes QE_USB_RESTART_TX command definition.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 arch/powerpc/sysdev/qe_lib/Kconfig  |    6 ++++
 arch/powerpc/sysdev/qe_lib/Makefile |    1 +
 arch/powerpc/sysdev/qe_lib/ucc.c    |    7 ++--
 arch/powerpc/sysdev/qe_lib/usb.c    |   57 +++++++++++++++++++++++++++++++++++
 include/asm-powerpc/qe.h            |   18 ++++++++++-
 5 files changed, 85 insertions(+), 4 deletions(-)
 create mode 100644 arch/powerpc/sysdev/qe_lib/usb.c

diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index c1f2849..f09dae4 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -25,3 +25,9 @@ config QE_GTM
 	default y if FSL_GTM
 	help
 	  QE General-purpose Timers Module support
+
+config QE_USB
+	bool
+	default y if USB_FHCI_HCD
+	help
+	  QE USB Host Controller support
diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/sysdev/qe_lib/Makefile
index 3297a52..c666a59 100644
--- a/arch/powerpc/sysdev/qe_lib/Makefile
+++ b/arch/powerpc/sysdev/qe_lib/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_UCC)	+= ucc.o
 obj-$(CONFIG_UCC_SLOW)	+= ucc_slow.o
 obj-$(CONFIG_UCC_FAST)	+= ucc_fast.o
 obj-$(CONFIG_QE_GTM)	+= gtm.o
+obj-$(CONFIG_QE_USB)	+= usb.o
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index 0e348d9..d3c7f5a 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -26,7 +26,8 @@
 #include <asm/qe.h>
 #include <asm/ucc.h>
 
-static DEFINE_SPINLOCK(ucc_lock);
+DEFINE_SPINLOCK(cmxgcr_lock);
+EXPORT_SYMBOL(cmxgcr_lock);
 
 int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
 {
@@ -35,10 +36,10 @@ int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
 	if (ucc_num > UCC_MAX_NUM - 1)
 		return -EINVAL;
 
-	spin_lock_irqsave(&ucc_lock, flags);
+	spin_lock_irqsave(&cmxgcr_lock, flags);
 	clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
 		ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
-	spin_unlock_irqrestore(&ucc_lock, flags);
+	spin_unlock_irqrestore(&cmxgcr_lock, flags);
 
 	return 0;
 }
diff --git a/arch/powerpc/sysdev/qe_lib/usb.c b/arch/powerpc/sysdev/qe_lib/usb.c
new file mode 100644
index 0000000..60ce676
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/usb.c
@@ -0,0 +1,57 @@
+/*
+ * QE USB routines
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ *               Shlomi Gridish <gridish@freescale.com>
+ *               Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ *               Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+
+int qe_usb_clock_set(enum qe_clock clk, int rate)
+{
+	struct qe_mux __iomem *mux = &qe_immr->qmx;
+	unsigned long flags;
+	const bool is_brg = clk < QE_CLK1;
+	u32 val;
+
+	switch (clk) {
+	case QE_CLK3:  val = QE_CMXGCR_USBCS_CLK3;  break;
+	case QE_CLK5:  val = QE_CMXGCR_USBCS_CLK5;  break;
+	case QE_CLK7:  val = QE_CMXGCR_USBCS_CLK7;  break;
+	case QE_CLK9:  val = QE_CMXGCR_USBCS_CLK9;  break;
+	case QE_CLK13: val = QE_CMXGCR_USBCS_CLK13; break;
+	case QE_CLK17: val = QE_CMXGCR_USBCS_CLK17; break;
+	case QE_CLK19: val = QE_CMXGCR_USBCS_CLK19; break;
+	case QE_CLK21: val = QE_CMXGCR_USBCS_CLK21; break;
+	case QE_BRG9:  val = QE_CMXGCR_USBCS_BRG9;  break;
+	case QE_BRG10: val = QE_CMXGCR_USBCS_BRG10; break;
+	default:
+		pr_err("%s: requested unknown clock %d\n", __func__, clk);
+		return -EINVAL;
+	}
+
+	if (is_brg)
+		qe_setbrg(clk, rate, 1);
+
+	spin_lock_irqsave(&cmxgcr_lock, flags);
+
+	clrsetbits_be32(&mux->cmxgcr, QE_CMXGCR_USBCS, val);
+
+	spin_unlock_irqrestore(&cmxgcr_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(qe_usb_clock_set);
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index c3be6e2..3276b06 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -16,6 +16,7 @@
 #define _ASM_POWERPC_QE_H
 #ifdef __KERNEL__
 
+#include <linux/spinlock.h>
 #include <asm/immap_qe.h>
 
 #define QE_NUM_OF_SNUM	28
@@ -74,6 +75,8 @@ enum qe_clock {
 	QE_CLK_DUMMY
 };
 
+extern spinlock_t cmxgcr_lock;
+
 /* Export QE common operations */
 extern void qe_reset(void);
 extern int par_io_init(struct device_node *np);
@@ -156,6 +159,9 @@ int qe_upload_firmware(const struct qe_firmware *firmware);
 /* Obtain information on the uploaded firmware */
 struct qe_firmware_info *qe_get_firmware_info(void);
 
+/* QE USB */
+int qe_usb_clock_set(enum qe_clock clk, int rate);
+
 /* Buffer descriptors */
 struct qe_bd {
 	__be16 status;
@@ -254,6 +260,16 @@ enum comm_dir {
 #define QE_CMXGCR_MII_ENET_MNG		0x00007000
 #define QE_CMXGCR_MII_ENET_MNG_SHIFT	12
 #define QE_CMXGCR_USBCS			0x0000000f
+#define QE_CMXGCR_USBCS_CLK3		0x1
+#define QE_CMXGCR_USBCS_CLK5		0x2
+#define QE_CMXGCR_USBCS_CLK7		0x3
+#define QE_CMXGCR_USBCS_CLK9		0x4
+#define QE_CMXGCR_USBCS_CLK13		0x5
+#define QE_CMXGCR_USBCS_CLK17		0x6
+#define QE_CMXGCR_USBCS_CLK19		0x7
+#define QE_CMXGCR_USBCS_CLK21		0x8
+#define QE_CMXGCR_USBCS_BRG9		0x9
+#define QE_CMXGCR_USBCS_BRG10		0xa
 
 /* QE CECR Commands.
 */
@@ -283,7 +299,7 @@ enum comm_dir {
 #define QE_HPAC_START_TX		0x0000060b
 #define QE_HPAC_START_RX		0x0000070b
 #define QE_USB_STOP_TX			0x0000000a
-#define QE_USB_RESTART_TX		0x0000000b
+#define QE_USB_RESTART_TX		0x0000000c
 #define QE_QMC_STOP_TX			0x0000000c
 #define QE_QMC_STOP_RX			0x0000000d
 #define QE_SS7_SU_FIL_RESET		0x0000000e
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH 8/8] [POWERPC] qe_io: fix sparse warnings
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 arch/powerpc/sysdev/qe_lib/qe_io.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index 736c1fc..93916a4 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -22,6 +22,7 @@
 #include <linux/ioport.h>
 
 #include <asm/io.h>
+#include <asm/qe.h>
 #include <asm/prom.h>
 #include <sysdev/fsl_soc.h>
 
@@ -41,7 +42,7 @@ struct port_regs {
 #endif
 };
 
-static struct port_regs *par_io = NULL;
+static struct port_regs __iomem *par_io;
 static int num_par_io_ports = 0;
 
 int par_io_init(struct device_node *np)
@@ -165,7 +166,7 @@ int par_io_of_config(struct device_node *np)
 	}
 
 	ph = of_get_property(np, "pio-handle", NULL);
-	if (ph == 0) {
+	if (ph == NULL) {
 		printk(KERN_ERR "pio-handle not available \n");
 		return -1;
 	}
-- 
1.5.2.2

^ permalink raw reply related

* RE: [PATCH] Ported Xilinx GPIO driver to OpenFirmware.
From: Stephen Neuendorffer @ 2008-03-11 17:35 UTC (permalink / raw)
  To: Magnus Hjorth, git; +Cc: linuxppc-embedded
In-Reply-To: <000001c88392$c38a8c40$4a9fa4c0$@se>


Thanks Magnus!

Generally speaking this looks reasonable.  Some comments:

>  struct xgpio_instance {
>  	struct list_head link;
>  	unsigned long base_phys;	/* GPIO base address - physical
*/
>  	unsigned long remap_size;
> -	u32 device_id;
> +	u32 device_id;		/* Dev ID for platform devices, 0 for OF
devices */
> +	void *of_id;		/* of_dev pointer for OF devices, NULL
for plat devices */

Why have separate ids?  I don't think the of_dev needs to be kept around
here.  This driver seems seems awkwardly written to have a local list of
all the devices, rather than simply attaching the xgpio_instance as the
private data of the file.

For instance, in drivers/char/xilinx_hwicap.c:

static ssize_t
hwicap_read(struct file *file, char __user *buf, size_t count, loff_t
*ppos)
{
	struct hwicap_drvdata *drvdata =3D file->private_data;

and the drvdata is set in open:

static int hwicap_open(struct inode *inode, struct file *file)
{
	struct hwicap_drvdata *drvdata;
	int status;

	drvdata =3D container_of(inode->i_cdev, struct hwicap_drvdata,
cdev);
	...
	file->private_data =3D drvdata;

Which would work if xgpio_instance directly contains the struct
miscdevice.
I think this is a much cleaner pattern (although it took me a while to
figure out the magic that makes it work... )

> +static struct of_device_id xgpio_of_match[] =3D {
> +	{.compatible =3D "xlnx,xps-gpio-1.00.a"},

This should also probably contain the corresponding strings for the
following as well:
      opb_gpio_v1_00_a
      opb_gpio_v2_00_a
      opb_gpio_v3_01_a
      opb_gpio_v3_01_b
	plb_gpio_v1_00_b

This would seem to be a relatively easy driver to clean up (by pulling
it all into one file and converting the other code to the kernel style)
and submit to mainline, if you're interested?

Steve

^ permalink raw reply

* Re: [PATCH] pasemi_dma: Driver for PA Semi PWRficient on-chip DMA engine
From: Andrew Morton @ 2008-03-11 17:53 UTC (permalink / raw)
  To: Olof Johansson
  Cc: hskinnemoen, shannon.nelson, linux-kernel, linuxppc-dev,
	pasemi-linux, dan.j.williams
In-Reply-To: <20080311142545.GA18843@lixom.net>

On Tue, 11 Mar 2008 09:25:45 -0500
Olof Johansson <olof@lixom.net> wrote:

> On Tue, Mar 11, 2008 at 12:06:19AM -0700, Andrew Morton wrote:
> > On Thu, 6 Mar 2008 17:39:00 -0600 Olof Johansson <olof@lixom.net> wrote:
> > 
> > > pasemi_dma: Driver for PA Semi PWRficient on-chip DMA engine
> > >     
> > > First cut at a dma copy offload driver for PA Semi PWRficient. It uses the
> > > platform-specific functions to allocate channels, etc.
> > 
> > Applied this on Paul's latest and powerpc allmodconfig goes boom.
> 
> It's dependent on my latest pull request of pasemi.git for-2.6.26 that
> Paul hasn't pulled/pushed yet.

Maybe we should get that tree into -mm and/or linux-next.

People do test -mm on powerpc.

> > drivers/dma/pasemi_dma.c: In function `pasemi_dma_alloc_chan_resources':
> > drivers/dma/pasemi_dma.c:152: error: `PAS_DMA_TXCHAN_CFG_TY_COPY' undeclared (first use in this function)
> > drivers/dma/pasemi_dma.c:152: error: (Each undeclared identifier is reported only once
> > drivers/dma/pasemi_dma.c:152: error: for each function it appears in.)
> > drivers/dma/pasemi_dma.c:154: error: `PAS_DMA_TXCHAN_CFG_LPDQ' undeclared (first use in this function)
> > drivers/dma/pasemi_dma.c:155: error: `PAS_DMA_TXCHAN_CFG_LPSQ' undeclared (first use in this function)
> > drivers/dma/pasemi_dma.c: In function `pasemi_dma_probe':
> > drivers/dma/pasemi_dma.c:394: error: structure has no member named `device_dependency_added'
> 
> .. and that one is caused by recent changes in async_tx.git. I was
> waiting on other review comments from the DMA maintainers before
> resubmitting; timer has expired though and I'll do it anyway today.

What is async_tx.git?

> > Also this driver from git-md-accel is pretty sick:
> > 
> > 
> > drivers/dma/fsldma.c:439: warning: comparison of distinct pointer types lacks a cast
> > drivers/dma/fsldma.c: In function `fsl_chan_xfer_ld_queue':
> > drivers/dma/fsldma.c:584: warning: long long unsigned int format, dma_addr_t arg (arg 4)
> > drivers/dma/fsldma.c: In function `fsl_dma_chan_do_interrupt':
> > drivers/dma/fsldma.c:661: warning: unsigned int format, different type arg (arg 5)
> > drivers/dma/fsldma.c:677: warning: long long unsigned int format, dma_addr_t arg (arg 4)
> > drivers/dma/fsldma.c:677: warning: long long unsigned int format, dma_addr_t arg (arg 5)
> > drivers/dma/fsldma.c:694: warning: unsigned int format, different type arg (arg 4)
> > drivers/dma/fsldma.c: In function `fsl_dma_self_test':
> > drivers/dma/fsldma.c:833: warning: int format, different type arg (arg 5)
> > drivers/dma/fsldma.c: In function `of_fsl_dma_probe':
> > drivers/dma/fsldma.c:1003: warning: unsigned int format, different type arg (arg 5)
> > drivers/dma/fsldma.c: At top level:
> > drivers/dma/fsldma.c:723: warning: 'fsl_dma_callback_test' defined but not used
> 
> Yeah, Zhang Wei posted a patch for that on lkml yesterday.

OK.

^ permalink raw reply

* wait_event_interruptible does not wake_up
From: Steve Kaiser @ 2008-03-11 18:12 UTC (permalink / raw)
  To: linuxppc-embedded

Can I ask you kernel gurus here for some advice?  I am using Linux 
2.4.25 on an Freescale MPC5200B IceCube development board.

I have some trouble waking a user process sent to sleep with 
wait_event[_interruptible].  99% of the time it works fine, but 
sometimes when I call wake_up(), my user process does not wake up.  I 
can see whats happening by toggling LEDs on the board, and watching with 
an oscilloscope.

<-- 50ms -->
      ______     _____
|___|      |___|       LED1 (low active)
_____  _________  ___
      ||         ||     LED4 (low active)

       ^ user thread is finshed here, and goes back to sleep
      ^ user thread is woke up here
     ^ interrupt tasklet finishes here
^ interrupt tasklet starts here

With some testing and hair pulling, I have discovered exactly when (but 
not why) this failure to wake_up happens.  If I install a 10ms kernel 
timer task, and the task occurs while my hardware interrupt service 
tasklet is happening (I feel maybe exactly when it is calling wake_up 
but not sure), that's when the wake_up always fails.

If I eliminate the asynchronous nature of the hardware interrupt, and 
simulate the hardware interrupt by installing a 10ms kernel timer task, 
using the task to toggling an I/O line that I jumper over to the 
hardware interrupt input, then everything works great.  The wake_up() 
never fails with this synchronous configuration.

Anybody heard of such a thing?  Any advice is very welcome.  Here's more 
details and code if you have a spare moment to read:

My very small user program is put to sleep by a driver with 
wait_event_interruptable() when the user program calls device_write(). 
I want the user program to sleep until my hardware is ready.  The 
hardware will interrupt when ready, every 50ms or so.  The hardware is a 
64k word FIFO memory chip, and the interrupt is it's half-full flag 
(latched with flip flop), but that doesn't matter.

When the driver recognizes the hardware interrupt, it should burst a 
chunk of data out to the hardware FIFO, and then wake the user program. 
  The user program writes a new chunk of data to the driver, and gets 
put to sleep again.  The driver holds the data in kobuf, all ready in 
preparation for the next hardware interrupt.

This all works perfectly well-- 99.99% of the time.  But every once in a 
while, the user process does not awake.  My interrupt tasklet recognized 
the interrupt, did call wake_up() for sure, but the process simply did 
not wake up.  Sometimes the process wakes up an arbitrary time later-- 
hundreds of milliseconds sometimes.  The interrupt service tasklet 
otherwise seems to be working reliably, as on the oscilloscope I can see 
the effects of it clearing a hardware flip-flop perfectly every time, 
and this is the call right before wake-up().

I copy below some of the code which may explain things better.  Maybe my 
error is obvious and dumb and if so, I am happy.  Maybe my approach is 
wrong?

Steve Kaiser


static u32 kobuf[FIFO_DEPTH][2];	// output DAC buffer

static int wrq = 0; 	// user sleeps until hdw fifo is half empty
static DECLARE_WAIT_QUEUE_HEAD(WriteQ);

static void gpio_irq_handler (int, void*, struct pt_regs *);
static void gpio_tasklet_handler( unsigned long );
static DECLARE_TASKLET(gpio_tasklet,gpio_tasklet_handler,0);


/* ----------------------------------------------------------------------
	device_open		device_read		device_ioctl
	device_release		device_write		device_poll
---------------------------------------------------------------------- */
static ssize_t device_write (struct file *filp,
	const char *buff,	// the user buffer to copy from
	size_t count,		// user requested nbytes
	loff_t * f_pos)		// offset in the file
{
size_t len = count;

	// wait for interrupt to make room for data and wake us up
	wrq = 1;  wait_event_interruptible(WriteQ,!wrq);

	// format of user buffer is uint[FIFO_DEPTH][2],
	// where for MPC5200, sizeof(uint) = 4, or 8 bytes per element
	if ( copy_from_user(kobuf,buff,len) )
		return -EFAULT;

return len;
}

/* ----------------------------------------------------------------------
	gpio_irq_handler: called on every gpio interrupt
---------------------------------------------------------------------- */
static void gpio_irq_handler( int irq,
	void *dev_id, struct pt_regs *regs )
{
struct mpc5xxx_gpio *pgpio = (struct mpc5xxx_gpio *)MPC5xxx_GPIO;

	// check GPIO Simple Interrupt Status Register
	if (pgpio->sint_istat & GSI2) {

		// clear only GSI2 Status read-write-clear bit
		// '=' instead oft '|=' to leave other bits unchanged
		pgpio->sint_istat = GSI2;

		// GSI2 Interrupt has occured.  schedule some work
		tasklet_schedule(&gpio_tasklet);
	}
}
static void gpio_tasklet_handler( unsigned long data )
{
unsigned int	i;
unsigned int	*buf;

	// refill hardware output FIFOs, assuming they are half empty
	buf = &kobuf[0][0];
	for ( i = 0; i < FIFO_HALFDEPTH; i++ ) {
		outl(*buf++,ioaddr);		// left
		outl(*buf++,ioaddr + 8);	// right
	}

	// pulse the hardware flip-flop clear pin,
	// allows hardware to assert another irq when fifo is half empty
	hdwrctrl &= ~kHdwrIrqAck;  outl(hdwrctrl,ioaddr + 4);
	hdwrctrl |= kHdwrIrqAck;  outl(hdwrctrl,ioaddr + 4);

	// wake up user program thread
	if ( wrq ) { wrq = 0;  wake_up(&WriteQ); }

}

^ 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