All of lore.kernel.org
 help / color / mirror / Atom feed
* Basic driver devel questions ?
@ 2010-12-01 10:15 Guillaume Dargaud
  2010-12-01 12:19 ` Michael Ellerman
  0 siblings, 1 reply; 29+ messages in thread
From: Guillaume Dargaud @ 2010-12-01 10:15 UTC (permalink / raw)
  To: linuxppc-dev

Hello all,
is it OK if I ask basic driver development questions here ?
Could you recommend a better forum for that maybe ?
Thanks
-- 
Guillaume Dargaud
http://www.gdargaud.net/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Basic driver devel questions ?
  2010-12-01 10:15 Basic driver devel questions ? Guillaume Dargaud
@ 2010-12-01 12:19 ` Michael Ellerman
  2010-12-01 16:35   ` Getting the IRQ number (Was: Basic driver devel questions ?) Guillaume Dargaud
  0 siblings, 1 reply; 29+ messages in thread
From: Michael Ellerman @ 2010-12-01 12:19 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

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

On Wed, 2010-12-01 at 11:15 +0100, Guillaume Dargaud wrote:
> Hello all,
> is it OK if I ask basic driver development questions here ?
> Could you recommend a better forum for that maybe ?

Hi Guillaume,

I guess it depends how basic they are :)

If they're basic _powerpc_ driver questions then this is probably the
right place.

But I'd say just ask and maybe someone will be able to help, or maybe
they'll point you somewhere else.

cheers

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-01 12:19 ` Michael Ellerman
@ 2010-12-01 16:35   ` Guillaume Dargaud
  2010-12-01 18:29     ` Philipp Ittershagen
  2010-12-01 18:41     ` Scott Wood
  0 siblings, 2 replies; 29+ messages in thread
From: Guillaume Dargaud @ 2010-12-01 16:35 UTC (permalink / raw)
  To: linuxppc-dev

> I guess it depends how basic they are :)
> 
> If they're basic _powerpc_ driver questions then this is probably the
> right place.
> 
> But I'd say just ask and maybe someone will be able to help, or maybe
> they'll point you somewhere else.

OK, here goes then: how do I get the IRQ number so that I can install an 
interrupt handler on it ?

In my dts file I have:
		xps_acqui_data_0: xps-acqui-data@c9800000 {
			compatible = "xlnx,xps-acqui-data-3.00.a";
			interrupt-parent = <&xps_intc_0>;
			interrupts = < 0 2 >;
			reg = < 0xc9800000 0x10000 >;
			xlnx,family = "virtex4";
			xlnx,include-dphase-timer = <0x1>;
			xlnx,mplb-awidth = <0x20>;
			xlnx,mplb-clk-period-ps = <0x2710>;
			xlnx,mplb-dwidth = <0x40>;
			xlnx,mplb-native-dwidth = <0x40>;
			xlnx,mplb-p2p = <0x0>;
			xlnx,mplb-smallest-slave = <0x20>;
		} ;

In my minimal driver init, I have:
  first = MKDEV (my_major, my_minor);
  register_chrdev_region(first, count, NAME);
  cdev_init(my_cdev, &fops);
  cdev_add (my_cdev, first, count);
So far so good.

Now how do I connect the dots between the hardware definitions from the dts and 
my driver ?
I have:
# ll /proc/device-tree/plb@0/xps-acqui-data@c9800000/
-r--r--r--    1 root     root          27 Dec  1 16:26 compatible
-r--r--r--    1 root     root           4 Dec  1 16:26 interrupt-parent
-r--r--r--    1 root     root           8 Dec  1 16:26 interrupts
-r--r--r--    1 root     root          15 Dec  1 16:26 name
-r--r--r--    1 root     root           8 Dec  1 16:26 reg
-r--r--r--    1 root     root           8 Dec  1 16:26 xlnx,family
-r--r--r--    1 root     root           4 Dec  1 16:26 xlnx,include-dphase-
timer
-r--r--r--    1 root     root           4 Dec  1 16:26 xlnx,mplb-awidth
-r--r--r--    1 root     root           4 Dec  1 16:26 xlnx,mplb-clk-period-ps
-r--r--r--    1 root     root           4 Dec  1 16:26 xlnx,mplb-dwidth
-r--r--r--    1 root     root           4 Dec  1 16:26 xlnx,mplb-native-dwidth
-r--r--r--    1 root     root           4 Dec  1 16:26 xlnx,mplb-p2p
-r--r--r--    1 root     root           4 Dec  1 16:26 xlnx,mplb-smallest-
slave

But first I'm not sure where to find the IRQ in there, and also I'm not sure if 
reading the filesystem from a module is allowed.

How do I know if this interrupt is shared or not (is it important ?)

Thanks
-- 
Guillaume Dargaud
http://www.gdargaud.net/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-01 16:35   ` Getting the IRQ number (Was: Basic driver devel questions ?) Guillaume Dargaud
@ 2010-12-01 18:29     ` Philipp Ittershagen
  2010-12-01 18:41     ` Scott Wood
  1 sibling, 0 replies; 29+ messages in thread
From: Philipp Ittershagen @ 2010-12-01 18:29 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 12/01/2010 05:35 PM, Guillaume Dargaud wrote:
> Now how do I connect the dots between the hardware definitions from the dts and 
> my driver ?

You can get the interrupt number from the dt by calling
irq_of_parse_and_map(). Be sure to pass the node of your device to this
function.

Then you have to request the interrupt by calling request_irq. This is
where you specify the interrupt handler.

> But first I'm not sure where to find the IRQ in there, and also I'm not sure if 
> reading the filesystem from a module is allowed.

Why do you want to read the file system?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkz2lCEACgkQCG4q0RxCsY4GpgCgiQFRhiF7jjhUdZcUBc4Y5ScJ
E0AAn0VxcCaVexepjrah64ZSS+Xhbed8
=h97e
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-01 16:35   ` Getting the IRQ number (Was: Basic driver devel questions ?) Guillaume Dargaud
  2010-12-01 18:29     ` Philipp Ittershagen
@ 2010-12-01 18:41     ` Scott Wood
  2010-12-02 15:36       ` Guillaume Dargaud
  1 sibling, 1 reply; 29+ messages in thread
From: Scott Wood @ 2010-12-01 18:41 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

On Wed, 1 Dec 2010 17:35:58 +0100
Guillaume Dargaud <dargaud@lpsc.in2p3.fr> wrote:

> OK, here goes then: how do I get the IRQ number so that I can install an 
> interrupt handler on it ?
> 
> In my dts file I have:
> 		xps_acqui_data_0: xps-acqui-data@c9800000 {
> 			compatible = "xlnx,xps-acqui-data-3.00.a";
> 			interrupt-parent = <&xps_intc_0>;
> 			interrupts = < 0 2 >;
> 			reg = < 0xc9800000 0x10000 >;
> 			xlnx,family = "virtex4";
> 			xlnx,include-dphase-timer = <0x1>;
> 			xlnx,mplb-awidth = <0x20>;
> 			xlnx,mplb-clk-period-ps = <0x2710>;
> 			xlnx,mplb-dwidth = <0x40>;
> 			xlnx,mplb-native-dwidth = <0x40>;
> 			xlnx,mplb-p2p = <0x0>;
> 			xlnx,mplb-smallest-slave = <0x20>;
> 		} ;
> 
> In my minimal driver init, I have:
>   first = MKDEV (my_major, my_minor);
>   register_chrdev_region(first, count, NAME);
>   cdev_init(my_cdev, &fops);
>   cdev_add (my_cdev, first, count);
> So far so good.
> 
> Now how do I connect the dots between the hardware definitions from the dts and 
> my driver ?

How was your driver probed?  If you can get a pointer to the device
node, use irq_of_parse_and_map() to get a virtual irq that you can pass
to request_irq().

> But first I'm not sure where to find the IRQ in there, and also I'm not sure if 
> reading the filesystem from a module is allowed.

There's no need; there are much easier ways to access the device tree
from within the kernel.

> How do I know if this interrupt is shared or not (is it important ?)

Can your driver tolerate it being shared?  If so, request it as shared.

-Scott

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-01 18:41     ` Scott Wood
@ 2010-12-02 15:36       ` Guillaume Dargaud
  2010-12-02 16:17         ` Timur Tabi
  0 siblings, 1 reply; 29+ messages in thread
From: Guillaume Dargaud @ 2010-12-02 15:36 UTC (permalink / raw)
  To: linuxppc-dev

> How was your driver probed?  If you can get a pointer to the device
> node, use irq_of_parse_and_map() to get a virtual irq that you can pass
> to request_irq().

Sounds like what I need... But I don't find irq_of_parse_and_map() in LDD 3rd 
ed and very few info in google. Are there some examples of use somewhere ?

> Can your driver tolerate it being shared?  If so, request it as shared.
I think so (not sure).
-- 
Guillaume Dargaud
http://www.gdargaud.net/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-02 15:36       ` Guillaume Dargaud
@ 2010-12-02 16:17         ` Timur Tabi
  2010-12-02 17:47           ` Guillaume Dargaud
  0 siblings, 1 reply; 29+ messages in thread
From: Timur Tabi @ 2010-12-02 16:17 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

On Thu, Dec 2, 2010 at 9:36 AM, Guillaume Dargaud <dargaud@lpsc.in2p3.fr> wrote:

> Sounds like what I need... But I don't find irq_of_parse_and_map() in LDD 3rd
> ed and very few info in google. Are there some examples of use somewhere ?

     grep -r irq_of_parse_and_map *

will give you plenty of examples.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-02 16:17         ` Timur Tabi
@ 2010-12-02 17:47           ` Guillaume Dargaud
  2010-12-02 20:22             ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 29+ messages in thread
From: Guillaume Dargaud @ 2010-12-02 17:47 UTC (permalink / raw)
  To: linuxppc-dev

>      grep -r irq_of_parse_and_map *
> 
> will give you plenty of examples.

OK, learning by example then.

Another basic question: 
what's the difference between of_register_platform_driver() and 
platform_driver_register() ?
I assume I must use the first one if I want to use irq_of_parse_and_map...
-- 
Guillaume Dargaud
http://www.gdargaud.net/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-02 17:47           ` Guillaume Dargaud
@ 2010-12-02 20:22             ` Benjamin Herrenschmidt
  2010-12-03 14:58               ` Guillaume Dargaud
  0 siblings, 1 reply; 29+ messages in thread
From: Benjamin Herrenschmidt @ 2010-12-02 20:22 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

On Thu, 2010-12-02 at 18:47 +0100, Guillaume Dargaud wrote:
> 
> OK, learning by example then.
> 
> Another basic question: 
> what's the difference between of_register_platform_driver() and 
> platform_driver_register() ?
> I assume I must use the first one if I want to use
> irq_of_parse_and_map... 

No. of_platform_drivers are more/less obsolete. Normal platform drivers
can now be associated with a device-tree node just fine.

Cheers,
Ben.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-02 20:22             ` Benjamin Herrenschmidt
@ 2010-12-03 14:58               ` Guillaume Dargaud
  2010-12-03 15:37                 ` Martyn Welch
  2010-12-06  5:29                 ` Michael Ellerman
  0 siblings, 2 replies; 29+ messages in thread
From: Guillaume Dargaud @ 2010-12-03 14:58 UTC (permalink / raw)
  To: linuxppc-dev

> No. of_platform_drivers are more/less obsolete. Normal platform drivers
> can now be associated with a device-tree node just fine.

OK.

If my dts definition is thus:
		xps_acqui_data_0: xps-acqui-data@c9800000 {
			compatible = "xlnx,xps-acqui-data-3.00.a";
			interrupt-parent = <&xps_intc_0>;
			interrupts = < 0 2 >;
			reg = < 0xc9800000 0x10000 >;
			xlnx,family = "virtex4";
			xlnx,include-dphase-timer = <0x1>;
			xlnx,mplb-awidth = <0x20>;
			xlnx,mplb-clk-period-ps = <0x2710>;
			xlnx,mplb-dwidth = <0x40>;
			xlnx,mplb-native-dwidth = <0x40>;
			xlnx,mplb-p2p = <0x0>;
			xlnx,mplb-smallest-slave = <0x20>;
		} ;

What are the names I need to pass to platform_driver_register and 
platform_device_register_simple ? xps_acqui_data_0, xps-acqui-data or xps-
acqui-data-3.00.a ? None seem to call any init functions...

Why is there not a word about the functions platform_*_register in my various 
driver books ? LDD 3rd ed (O'Reilly), Writing LDD (Cooperstein) or LKD 
(Love)... Is it something specific to powerpc and the books are oriented x86 ? 
What's a good source, besides grepping the kernel to no end ?

-- 
Guillaume Dargaud
http://www.gdargaud.net/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-03 14:58               ` Guillaume Dargaud
@ 2010-12-03 15:37                 ` Martyn Welch
  2010-12-06  5:29                 ` Michael Ellerman
  1 sibling, 0 replies; 29+ messages in thread
From: Martyn Welch @ 2010-12-03 15:37 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

On 03/12/10 14:58, Guillaume Dargaud wrote:
> Why is there not a word about the functions platform_*_register in my various 
> driver books ? LDD 3rd ed (O'Reilly), Writing LDD (Cooperstein) or LKD 
> (Love)... Is it something specific to powerpc and the books are oriented x86 ? 
> What's a good source, besides grepping the kernel to no end ?
> 

I have yet to find a Linux Device Driver book that isn't heavily skewed
towards x86. Some of this stuff is either specific to powerpc or
relevant a subset of non-x86 platforms.

I think Google, the linuxppc-dev mailing list, related IRC channel and
lxr.linux.no have been the sources I've mostly used learning about Linux
on powerpc.


-- 
Martyn Welch (Principal Software Engineer)   |   Registered in England and
GE Intelligent Platforms                     |   Wales (3828642) at 100
T +44(0)127322748                            |   Barbirolli Square,
Manchester,
E martyn.welch@ge.com                        |   M2 3AB  VAT:GB 927559189

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-03 14:58               ` Guillaume Dargaud
  2010-12-03 15:37                 ` Martyn Welch
@ 2010-12-06  5:29                 ` Michael Ellerman
  2010-12-06  6:35                   ` Jeremy Kerr
                                     ` (2 more replies)
  1 sibling, 3 replies; 29+ messages in thread
From: Michael Ellerman @ 2010-12-06  5:29 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

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

On Fri, 2010-12-03 at 15:58 +0100, Guillaume Dargaud wrote:
> > No. of_platform_drivers are more/less obsolete. Normal platform drivers
> > can now be associated with a device-tree node just fine.
> 
> OK.
> 
> If my dts definition is thus:
> 		xps_acqui_data_0: xps-acqui-data@c9800000 {
> 			compatible = "xlnx,xps-acqui-data-3.00.a";
> 			interrupt-parent = <&xps_intc_0>;
> 			interrupts = < 0 2 >;
> 			reg = < 0xc9800000 0x10000 >;
> 			xlnx,family = "virtex4";
> 			xlnx,include-dphase-timer = <0x1>;
> 			xlnx,mplb-awidth = <0x20>;
> 			xlnx,mplb-clk-period-ps = <0x2710>;
> 			xlnx,mplb-dwidth = <0x40>;
> 			xlnx,mplb-native-dwidth = <0x40>;
> 			xlnx,mplb-p2p = <0x0>;
> 			xlnx,mplb-smallest-slave = <0x20>;
> 		} ;
> 
> What are the names I need to pass to platform_driver_register and 
> platform_device_register_simple ? xps_acqui_data_0, xps-acqui-data or xps-
> acqui-data-3.00.a ?

None of the above :)  xps_acqui_data_0 is a label, it is only relevant
within the dts source, ie. other nodes may refer to this node by that
label. But the label string is not useful in Linux. The node name
"xps-acqui-data" is visible in Linux, but is generally not used for
discovery, it's just a name. What you do want to use is the full
compatible value, ie. "xlnx,xps-acqui-data-3.00.a".

> Why is there not a word about the functions platform_*_register in my various 
> driver books ? LDD 3rd ed (O'Reilly), Writing LDD (Cooperstein) or LKD 
> (Love)... Is it something specific to powerpc and the books are oriented x86 ? 

Because they're old dead-tree references, that aren't up to date with
the kernel. The LDD website says "LDD3 is current as of the 2.6.10
kernel", that's 25 kernel versions ago! I'm also not aware of any book
that has information on anything other than x86 drivers.

> What's a good source, besides grepping the kernel to no end ?

Nothing really I'm afraid.


So you have a device, it appears in your device tree, and you want to
write a driver for it.

The first issue is that someone needs to create a device for your node,
it doesn't necessarily happen by default. For many platforms this will
all happen "automagically" as long as the device node that describes
your device appears in the right place, but I'll describe it in full
anyway.

In most cases your device will appear below a node that represents a
bus, eg:

	foobus@xyz {
		compatible = "vendor,foobus-v1.m.n", "simple-bus";
		...
		yournode@abc {
			...
		}
	}

If that isn't the case you need to arrange for it somehow [1]. 

Somewhere there needs to be code to probe that bus and create devices on
it. That is usually done in platform code with of_platform_bus_probe(). 

If you don't know what platform you're on, you can look at a boot log
for a line saying "Using <blah> machine description", it will be very
early in the log. "blah" is then the name of the platform you're on, and
you should be able to grep for it in arch/powerpc/platforms.

Once you've found the .c file for your platform, there should be a call
somewhere to of_platform_bus_probe(), with a list of ids, and one of
those ids should match the compatible property of your bus node. In a
lot of cases that is just "simple-bus".

To check a device is being created for your device node, you can look
in /sys/devices. The device names don't match 100% with what's in the
device tree, but the name should be there, so in your case:

# find /sys/devices -name '*xps-acqui-data*'


Assuming that is working you can start on the driver side of things. A
rough template is:

static int foo_driver_probe(struct platform_device *device,
			    const struct of_device_id *device_id)
{
	struct device_node *dn = device->dev.of_node;
	struct foo_device *foo;

	pr_devel("%s: probing %s\n", __func__, dn->full_name);
	
	/* Check you really want to probe this device and everything is OK */

	foo = kzalloc(sizeof(*foo));
	if (!foo)
		return -ENOMEM;

	foo->regs = of_iomap(dn, 0);
	if (!foo->regs)
		goto out;

	foo->irq = irq_of_parse_and_map(dn, 0);
	if (foo->irq == NO_IRQ)
		goto out;

	etc.

	return 0;
}

static const struct of_device_id foo_device_id[] =
{                       
        { .compatible     = "vendor,foo-device" },
        {}
};

static struct platform_driver foo_driver = {
        .probe          = foo_driver_probe,
        .driver = {
                .name = "foo-driver",
                .owner = THIS_MODULE,
                .of_match_table = foo_device_id,
        },          
};

static int __init foo_driver_init(void)
{
        return platform_driver_register(&foo_driver);
}
module_init(foo_driver_init);


I probably missed something there, I haven't compiled it (obviously),
but it's a start. Some of this stuff is in flux, but I think everything
I have above is OK at least for now. Grant might correct me :)

cheers


[1]: One option is to put your device under an existing bus, but only if
that (fairly) accurately represents the hardware topology. You might
need to create a new node representing the bus your device appears on.
You can also manually create the device in C, but that is generally not
the right approach unless the device tree is immutable - ie. comes from
firmware that you don't control.

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-06  5:29                 ` Michael Ellerman
@ 2010-12-06  6:35                   ` Jeremy Kerr
  2010-12-06 11:56                     ` Michael Ellerman
  2010-12-06  9:58                   ` Guillaume Dargaud
  2010-12-07 12:46                   ` Guillaume Dargaud
  2 siblings, 1 reply; 29+ messages in thread
From: Jeremy Kerr @ 2010-12-06  6:35 UTC (permalink / raw)
  To: linuxppc-dev, michael

Hi Michael,

> So you have a device, it appears in your device tree, and you want to
> write a driver for it.

Nice write up, mind if I steal this for the devicetree.org wiki?

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-06  5:29                 ` Michael Ellerman
  2010-12-06  6:35                   ` Jeremy Kerr
@ 2010-12-06  9:58                   ` Guillaume Dargaud
  2010-12-06 12:07                     ` Michael Ellerman
  2010-12-06 12:17                     ` David Laight
  2010-12-07 12:46                   ` Guillaume Dargaud
  2 siblings, 2 replies; 29+ messages in thread
From: Guillaume Dargaud @ 2010-12-06  9:58 UTC (permalink / raw)
  To: linuxppc-dev

Thank you for the detailed answer. I'm trying to digest it...

> > What's a good source, besides grepping the kernel to no end ?
> 
> Nothing really I'm afraid.
8-|

> So you have a device, it appears in your device tree, and you want to
> write a driver for it.
That's the idea. Communication between usermode and the driver is limited to 
simple ioctl calls and the driver receives an interrupt when certain data has 
been placed in memory blocks by the hardware (like a DMA). Then the user prog 
figures out where that latest data buffer is (mmap) and saves it. 

> The first issue is that someone needs to create a device for your node,
> it doesn't necessarily happen by default. For many platforms this will
> all happen "automagically" as long as the device node that describes
> your device appears in the right place, but I'll describe it in full
> anyway.

I'm on a minimalist embedded system (buildroot+busybox+uclibc), so I'm pretty 
sure I have to do the whole thing. No udev/HAL here.

> In most cases your device will appear below a node that represents a
> bus, eg:
> 
> 	foobus@xyz {
> 		compatible = "vendor,foobus-v1.m.n", "simple-bus";
> 		...
> 		yournode@abc {
> 			...
> 		}
> 	}
> 
> If that isn't the case you need to arrange for it somehow [1].

Commenting on your [1] here. So should I just add "simple-bus" or does the 
VHDL needs to be modified so as to generate this additional bus info ?
I indeed have:

/dts-v1/;
/ {
	#address-cells = <1>;
	#size-cells = <1>;
	compatible = "xlnx,virtex405", "xlnx,virtex";
	model = "testing";
	...
	plb: plb@0 {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "xlnx,plb-v46-1.05.a", "xlnx,plb-v46-1.00.a", "simple-
bus";
		ranges ;
		...
		xps_acqui_data_0: xps-acqui-data@c9800000 {
			compatible = "xlnx,xps-acqui-data-3.00.a";
			...
		}
		...
	}
	...
}

> Somewhere there needs to be code to probe that bus and create devices on
> it. That is usually done in platform code with of_platform_bus_probe().

Isn't the of_* code outdated (just been told that on a previous message) ?
Or was it just for of_register_platform_driver ?

> If you don't know what platform you're on, you can look at a boot log
> for a line saying "Using <blah> machine description", it will be very
> early in the log. "blah" is then the name of the platform you're on, and
> you should be able to grep for it in arch/powerpc/platforms.

"Using Xilinx Virtex machine description"
 
> Once you've found the .c file for your platform, there should be a call
> somewhere to of_platform_bus_probe(), with a list of ids, and one of
> those ids should match the compatible property of your bus node. In a
> lot of cases that is just "simple-bus".

That'd be:
arch/powerpc/platforms/40x/virtex.c:51: .name = "Xilinx Virtex",
and
arch/powerpc/platforms/40x/virtex.c:21: { .compatible = "simple-bus", },

No match for simple-bus of acqui-data in dmesg.

> To check a device is being created for your device node, you can look
> in /sys/devices. The device names don't match 100% with what's in the
> device tree, but the name should be there, so in your case:
> 
> # find /sys/devices -name '*xps-acqui-data*'

Indeed: 
# ll /sys/devices/plb.0/c9800000.xps-acqui-data
-r--r--r--    1 root     root        4.0K Dec  6 09:47 devspec
-r--r--r--    1 root     root        4.0K Dec  6 09:47 modalias
-r--r--r--    1 root     root        4.0K Dec  6 09:47 name
lrwxrwxrwx    1 root     root           0 Dec  6 09:47 subsystem -> 
../../../bus/of_platform/
-rw-r--r--    1 root     root        4.0K Dec  6 09:47 uevent

So that's created on boot, right ?

> [...code snipped...]

I still need a platform_device_register() after your sample init, right ?
I'll get on to adapting your sample code now. Thanks a lot.
-- 
Guillaume Dargaud
http://www.gdargaud.net/Antarctica/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-06  6:35                   ` Jeremy Kerr
@ 2010-12-06 11:56                     ` Michael Ellerman
  0 siblings, 0 replies; 29+ messages in thread
From: Michael Ellerman @ 2010-12-06 11:56 UTC (permalink / raw)
  To: Jeremy Kerr; +Cc: linuxppc-dev

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

On Mon, 2010-12-06 at 14:35 +0800, Jeremy Kerr wrote:
> Hi Michael,
> 
> > So you have a device, it appears in your device tree, and you want to
> > write a driver for it.
> 
> Nice write up, mind if I steal this for the devicetree.org wiki?

Sure thing, feel free to correct any mistakes too ;D

cheers


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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-06  9:58                   ` Guillaume Dargaud
@ 2010-12-06 12:07                     ` Michael Ellerman
  2010-12-06 14:44                       ` Guillaume Dargaud
  2010-12-06 12:17                     ` David Laight
  1 sibling, 1 reply; 29+ messages in thread
From: Michael Ellerman @ 2010-12-06 12:07 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

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

On Mon, 2010-12-06 at 10:58 +0100, Guillaume Dargaud wrote:
> Thank you for the detailed answer. I'm trying to digest it...
> 
> > > What's a good source, besides grepping the kernel to no end ?
> > 
> > Nothing really I'm afraid.
> 8-|
> 
> > So you have a device, it appears in your device tree, and you want to
> > write a driver for it.

> That's the idea. Communication between usermode and the driver is limited to 
> simple ioctl calls and the driver receives an interrupt when certain data has 
> been placed in memory blocks by the hardware (like a DMA). Then the user prog 
> figures out where that latest data buffer is (mmap) and saves it. 

OK, that should be all pretty straight forward, and covered by the
material in LDD and similar references. You just need to get your device
probed.

> > The first issue is that someone needs to create a device for your node,
> > it doesn't necessarily happen by default. For many platforms this will
> > all happen "automagically" as long as the device node that describes
> > your device appears in the right place, but I'll describe it in full
> > anyway.
> 
> I'm on a minimalist embedded system (buildroot+busybox+uclibc), so I'm pretty 
> sure I have to do the whole thing. No udev/HAL here.

That's another problem. The device I'm talking about here is just the
minimal struct in the kernel that you need in order for your driver to
probe against it. Once your driver has matched against a device then you
(might) need to worry about exposing a device to userspace in /dev.

> > In most cases your device will appear below a node that represents a
> > bus, eg:
> > 
> > 	foobus@xyz {
> > 		compatible = "vendor,foobus-v1.m.n", "simple-bus";
> > 		...
> > 		yournode@abc {
> > 			...
> > 		}
> > 	}
> > 
> > If that isn't the case you need to arrange for it somehow [1].
> 
> Commenting on your [1] here. So should I just add "simple-bus" or does the 
> VHDL needs to be modified so as to generate this additional bus info ?

Doesn't look like it:

> I indeed have:
> 
> /dts-v1/;
> / {
> 	#address-cells = <1>;
> 	#size-cells = <1>;
> 	compatible = "xlnx,virtex405", "xlnx,virtex";
> 	model = "testing";
> 	...
> 	plb: plb@0 {
> 		#address-cells = <1>;
> 		#size-cells = <1>;
> 		compatible = "xlnx,plb-v46-1.05.a", "xlnx,plb-v46-1.00.a", "simple-bus";
> 		ranges ;
> 		...
> 		xps_acqui_data_0: xps-acqui-data@c9800000 {
> 			compatible = "xlnx,xps-acqui-data-3.00.a";
> 			...
> 		}
> 		...
> 	}
> 	...
> }

That looks good.

> > Somewhere there needs to be code to probe that bus and create devices on
> > it. That is usually done in platform code with of_platform_bus_probe().
> 
> Isn't the of_* code outdated (just been told that on a previous message) ?
> Or was it just for of_register_platform_driver ?

No it's just that platform_drivers are now able to do all the things an
of_platform_driver can do, so new code should just use platform_driver.

I'm not sure if of_platform_bus_probe() will go away eventually, but for
now it is the only way to achieve what you need.

> > If you don't know what platform you're on, you can look at a boot log
> > for a line saying "Using <blah> machine description", it will be very
> > early in the log. "blah" is then the name of the platform you're on, and
> > you should be able to grep for it in arch/powerpc/platforms.
> 
> "Using Xilinx Virtex machine description"

Cool.

> > Once you've found the .c file for your platform, there should be a call
> > somewhere to of_platform_bus_probe(), with a list of ids, and one of
> > those ids should match the compatible property of your bus node. In a
> > lot of cases that is just "simple-bus".
> 
> That'd be:
> arch/powerpc/platforms/40x/virtex.c:51: .name = "Xilinx Virtex",
> and
> arch/powerpc/platforms/40x/virtex.c:21: { .compatible = "simple-bus", },

Perfect.

> No match for simple-bus of acqui-data in dmesg.

That's normal, if the kernel printed out every device it found you'd
drown in messages. If you want to you can put a printk in
of_platform_device_create() and you should see it.

> > To check a device is being created for your device node, you can look
> > in /sys/devices. The device names don't match 100% with what's in the
> > device tree, but the name should be there, so in your case:
> > 
> > # find /sys/devices -name '*xps-acqui-data*'
> 
> Indeed: 
> # ll /sys/devices/plb.0/c9800000.xps-acqui-data
> -r--r--r--    1 root     root        4.0K Dec  6 09:47 devspec
> -r--r--r--    1 root     root        4.0K Dec  6 09:47 modalias
> -r--r--r--    1 root     root        4.0K Dec  6 09:47 name
> lrwxrwxrwx    1 root     root           0 Dec  6 09:47 subsystem -> ../../../bus/of_platform/
> -rw-r--r--    1 root     root        4.0K Dec  6 09:47 uevent
> 
> So that's created on boot, right ?

Yep, so that is all working fine. You just need to write a driver that
will match against that device.

> > [...code snipped...]
> 
> I still need a platform_device_register() after your sample init, right ?

I had one in there already, in foo_driver_init(), didn't I?

> I'll get on to adapting your sample code now. Thanks a lot.

No worries.

cheers


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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-06  9:58                   ` Guillaume Dargaud
  2010-12-06 12:07                     ` Michael Ellerman
@ 2010-12-06 12:17                     ` David Laight
  1 sibling, 0 replies; 29+ messages in thread
From: David Laight @ 2010-12-06 12:17 UTC (permalink / raw)
  To: linuxppc-dev

=20

> That's the idea. Communication between usermode and the driver is
limited to=20
> simple ioctl calls and the driver receives an interrupt when certain
data has=20
> been placed in memory blocks by the hardware (like a DMA).=20
> Then the user prog figures out where that latest data buffer is (mmap)
and saves it.=20

I've used pread() and pwrite() to directly copy data to/from a devices
PCI memory space.
The driver just verifies the offset and calls copy_to/from_user() [1].
High offsets can be used to access driver specific data.
The userspace code for pread/write is less painful than using ioctl()
for everything.
This also lets you dump the device memory space with hexdump.

I also made the device interrupt generate POLLIN (this needs a bit of
care since the interrupt can arrive before poll() is called).

	David

[1] I actually had to use the PCIe dma controller to get adequate
throughput.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-06 12:07                     ` Michael Ellerman
@ 2010-12-06 14:44                       ` Guillaume Dargaud
  2010-12-06 14:47                         ` David Laight
  2010-12-08  1:03                         ` Michael Ellerman
  0 siblings, 2 replies; 29+ messages in thread
From: Guillaume Dargaud @ 2010-12-06 14:44 UTC (permalink / raw)
  To: linuxppc-dev

Hello all,

> OK, that should be all pretty straight forward, and covered by the
> material in LDD and similar references. You just need to get your device
> probed.

I'm not sure what you mean with that term: simply identifying that the device 
works using device specific code ?
I've looked at several *_probe functions from other drivers and they are all 
completely different with no common code...

Or do you mean calling of_platform_bus_probe() ? What does that function do ?

> No it's just that platform_drivers are now able to do all the things an
> of_platform_driver can do, so new code should just use platform_driver.
> 
> I'm not sure if of_platform_bus_probe() will go away eventually, but for
> now it is the only way to achieve what you need.

I assume the kernel needs to be compiled with CONFIG_OF.
...hmm I had to "git pull" in order for this to compile your snippet. That's 
really recent! Unfortunately i need to reflash my device with the new kernel 
before i can begin testing my module.

When I try to compile your (adapted) snippet, I got this minor problems:

  .probe = foo_driver_probe,
^ warning: initialization from incompatible pointer type
Shouldn't foo_driver_probe be:
static int foo_driver_probe(struct platform_device *pdev)
instead of:
static int foo_driver_probe(struct platform_device *device,
                            const struct of_device_id *device_id)


Also:
       struct foo_device *foo;
That's where I put my own content, right ?
And needs to be kfreed in a foo_driver_remove() function, right ?

> > I still need a platform_device_register() after your sample init, right ?
> 
> I had one in there already, in foo_driver_init(), didn't I?

You had platform_driver_register(), not that I'm all clear yet on the 
distinction...


Another question: I just spent 10 minutes trying to find where "struct device" 
was defined. (ack-)grep was absolutely no use. Isn't there a way to cross-
reference my own kernel, the way I've compiled it ?
-- 
Guillaume Dargaud
http://www.gdargaud.net/Climbing/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-06 14:44                       ` Guillaume Dargaud
@ 2010-12-06 14:47                         ` David Laight
  2010-12-08  1:03                         ` Michael Ellerman
  1 sibling, 0 replies; 29+ messages in thread
From: David Laight @ 2010-12-06 14:47 UTC (permalink / raw)
  To: linuxppc-dev

=20
> Another question: I just spent 10 minutes trying to find
> where "struct device" was defined.

Dirty trick #4:

At the top of a source file (before the first include) add:
    struct device { int fubar; };
Then try to compile it.

The compiler will the tell where it is defined!

	David

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-06  5:29                 ` Michael Ellerman
  2010-12-06  6:35                   ` Jeremy Kerr
  2010-12-06  9:58                   ` Guillaume Dargaud
@ 2010-12-07 12:46                   ` Guillaume Dargaud
  2010-12-08  0:50                     ` Michael Ellerman
  2 siblings, 1 reply; 29+ messages in thread
From: Guillaume Dargaud @ 2010-12-07 12:46 UTC (permalink / raw)
  To: linuxppc-dev

Michael, 
in your example, when is foo_driver_probe() actually called ?
It's not being called when I do an insmod.
-- 
Guillaume Dargaud
http://www.gdargaud.net/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-07 12:46                   ` Guillaume Dargaud
@ 2010-12-08  0:50                     ` Michael Ellerman
  0 siblings, 0 replies; 29+ messages in thread
From: Michael Ellerman @ 2010-12-08  0:50 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

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

On Tue, 2010-12-07 at 13:46 +0100, Guillaume Dargaud wrote:
> Michael, 
> in your example, when is foo_driver_probe() actually called ?
> It's not being called when I do an insmod.

It should be called when the driver core finds a device that matches
your match table.

When you register your driver the driver core will iterate over all
devices on the platform bus and if they match then it will call your
probe routine.

I assume you've update the compatible property in the match table, I'm
not sure what else could be causing it to not be called.

cheers

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-06 14:44                       ` Guillaume Dargaud
  2010-12-06 14:47                         ` David Laight
@ 2010-12-08  1:03                         ` Michael Ellerman
  2010-12-08 10:18                           ` Guillaume Dargaud
  1 sibling, 1 reply; 29+ messages in thread
From: Michael Ellerman @ 2010-12-08  1:03 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

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

On Mon, 2010-12-06 at 15:44 +0100, Guillaume Dargaud wrote: 
> Hello all,
> 
> > OK, that should be all pretty straight forward, and covered by the
> > material in LDD and similar references. You just need to get your device
> > probed.
> 
> I'm not sure what you mean with that term: simply identifying that the device 
> works using device specific code ?

I just mean connecting your driver up to a struct device that represents
your device.

> I've looked at several *_probe functions from other drivers and they are all 
> completely different with no common code...

Yes that's pretty normal, the probe routine usually finds device
specific info about the device and stores it in some sort of structure
for later use.

> Or do you mean calling of_platform_bus_probe() ? What does that function do ?

The platform code does that. That function create devices on the
platform bus by examining the device tree. It looks for nodes that are
compatible with the compatible strings you give it, and treats them as
busses, ie. creates devices for all child nodes of those nodes.

> > No it's just that platform_drivers are now able to do all the things an
> > of_platform_driver can do, so new code should just use platform_driver.
> > 
> > I'm not sure if of_platform_bus_probe() will go away eventually, but for
> > now it is the only way to achieve what you need.
> 
> I assume the kernel needs to be compiled with CONFIG_OF.

Yes absolutely.

> ...hmm I had to "git pull" in order for this to compile your snippet. That's 
> really recent! Unfortunately i need to reflash my device with the new kernel 
> before i can begin testing my module.

It shouldn't be that recent, what kernel version were you using?

> When I try to compile your (adapted) snippet, I got this minor problems:
> 
>   .probe = foo_driver_probe,
> ^ warning: initialization from incompatible pointer type
> Shouldn't foo_driver_probe be:
> static int foo_driver_probe(struct platform_device *pdev)
> instead of:
> static int foo_driver_probe(struct platform_device *device,
>                             const struct of_device_id *device_id)

Yes sorry, that's a cut & paste bug, between the old and new style code.

> Also:
>        struct foo_device *foo;
> That's where I put my own content, right ?

Yep.

> And needs to be kfreed in a foo_driver_remove() function, right ?

If you have a remove then yes.

> > > I still need a platform_device_register() after your sample init, right ?
> > 
> > I had one in there already, in foo_driver_init(), didn't I?
> 
> You had platform_driver_register(), not that I'm all clear yet on the 
> distinction...

Oh sorry, I always read those wrong.

platform_device_register() creates a device on the platform bus. You
then write a driver for that device, and register it with
platform_driver_register(), your driver then attaches to the device.

In this case though you don't need to call platform_device_register()
because the device has already been created, using the device tree (by
of_platform_bus_probe()).

In general on powerpc we don't use platform_device_register() much,
instead things are described in the device tree and devices are created
for them.

platform_device_register() tends to be for cases where you can't
discover or probe a device, but you "know" that it exists.

> Another question: I just spent 10 minutes trying to find where "struct device" 
> was defined. (ack-)grep was absolutely no use. Isn't there a way to cross-
> reference my own kernel, the way I've compiled it ?

Yes, "make tags", then use vim :)

If you're cross-compiling make sure to set ARCH=powerpc when you make
tags.

cheers

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-08  1:03                         ` Michael Ellerman
@ 2010-12-08 10:18                           ` Guillaume Dargaud
  2010-12-08 13:45                             ` Michael Ellerman
  0 siblings, 1 reply; 29+ messages in thread
From: Guillaume Dargaud @ 2010-12-08 10:18 UTC (permalink / raw)
  To: linuxppc-dev

Thanks again for your detailed answer,
I'm learning, but not as fast as my colleagues with a deadline want me to !

> The platform code does that. That function create devices on the
> platform bus by examining the device tree. It looks for nodes that are
> compatible with the compatible strings you give it, and treats them as
> busses, ie. creates devices for all child nodes of those nodes.

Is there a way to enable some debug output from it, to see what's going on ?

> > ...hmm I had to "git pull" in order for this to compile your snippet.
> > That's really recent! Unfortunately i need to reflash my device with the
> > new kernel before i can begin testing my module.
> 
> It shouldn't be that recent, what kernel version were you using?

I had to go from 2.6.34 to 2.6.35, xilinx git tree.

> Yes sorry, that's a cut & paste bug, between the old and new style code.

No worries, I knew it was some uncompiled example.

> platform_device_register() creates a device on the platform bus. You
> then write a driver for that device, and register it with
> platform_driver_register(), your driver then attaches to the device.
> 
> In this case though you don't need to call platform_device_register()
> because the device has already been created, using the device tree (by
> of_platform_bus_probe()).

OK, I'll have to remove it from my sample code below.

> In general on powerpc we don't use platform_device_register() much,
> instead things are described in the device tree and devices are created
> for them.
> 
> platform_device_register() tends to be for cases where you can't
> discover or probe a device, but you "know" that it exists.

When you see something in /sys/devices/plb.0/, it means that you don't need 
platform_device_register, right ?

> Yes, "make tags", then use vim :)

Great, that works.


OK, here's the relevant part of my code, ripped directly from your sample, 
with a few additions and different variable names. Why do you think 
xad_driver_probe() is not being called ?


#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/device.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>         // char device
#include <linux/fs.h>
#include <linux/of.h>
#include <linux/interrupt.h>

#define DEVNAME "xps-acqui-data"
#define NAME "xad"              // This is only used for printk

#define SD "{%s %d} "
#define FL , __func__, __LINE__

static dev_t first;
static unsigned int count = 1;
static int my_major = 241, my_minor = 0;
// You must run "mknod /dev/xad c 241 0" in a shell at least once

struct cdev *my_cdev=NULL;
struct platform_device *pdev=NULL;

typedef struct XadDevice {
  struct resource *hw_region;
  struct device *dev;
  int irq;
} tXadDevice;
tXadDevice Xad;

// There should be something in:
// ll /sys/devices/plb.0/c9800000.xps-acqui-data
static const struct of_device_id xad_device_id[] = {                       
        { .compatible     = "xlnx,xps-acqui-data-3.00.a" },     // Must match 
the DTS
        {}
};

  
static irqreturn_t XadIsr(int irq, void *dev_id) {
  printk(KERN_INFO SD "IRQ:%d\n" FL, irq);
  return IRQ_HANDLED;
}

///////////////////////////////////////////////////////////////////////////////
// Platform Bus Support
///////////////////////////////////////////////////////////////////////////////

static int  xad_driver_probe(struct platform_device *device /*,
                            const struct of_device_id *device_id*/ ) {
  struct device_node *dn = device->dev.of_node;
  int rc;

  pr_devel("Probing %s\n", dn->full_name);
  
  Xad.irq = irq_of_parse_and_map(dn, 0);
  rc=request_irq(Xad.irq, XadIsr, IRQF_TRIGGER_RISING  | IRQF_DISABLED, 
"XadIsr", &Xad);
  if (rc) printk(KERN_INFO SD "Failled IRQ request: %d\n" FL, rc);
  
  return 0;
}

static int __devexit xad_driver_remove(struct platform_device *device) {
  printk(KERN_INFO SD "Removing...\n" FL);
  return 0;
}

static struct platform_driver xad_driver = {
  .probe  = xad_driver_probe,
  .remove = xad_driver_remove,
  .driver = {
    .owner = THIS_MODULE,
    .name = "xad-driver",
        .of_match_table = xad_device_id,
  },
};


///////////////////////////////////////////////////////////////////////////////
// This section deals with the /dev/xad device
///////////////////////////////////////////////////////////////////////////////
static int xad_open(struct inode *node, struct file *filep) {
  printk (KERN_INFO SD "OPENING device: %s\n" FL, NAME);
  return 0;
}

static int xad_release(struct inode *node, struct file *filep) {
  printk (KERN_INFO SD "RELEASING device: %s\n" FL, NAME);
  return 0;
}

static int  xad_ioctl(struct inode *node, struct file *filep, unsigned int cmd, 
unsigned long arg) {
  printk (KERN_INFO SD "IOCTL on device: %s, cmd:%d, arg:%lu\n" FL, NAME, cmd, 
arg);
  return 0;
}

static struct file_operations fops = {
  .owner   = THIS_MODULE,
  .open    = xad_open,
  .release = xad_release,
  .ioctl   = xad_ioctl,
};


///////////////////////////////////////////////////////////////////////////////
// Called on insmod
static int __init xad_init(void) {
  int rc=0;
  printk(KERN_INFO SD "Module %s: loading...\n" FL, NAME);
  
  // Deal with the device
  first = MKDEV (my_major, my_minor);
  register_chrdev_region(first, count, DEVNAME);
  my_cdev = cdev_alloc ();
  if (NULL==my_cdev) goto Err;
  
  cdev_init(my_cdev, &fops);
  cdev_add (my_cdev, first, count);

  printk(KERN_INFO SD "Module %s: Major=%d, Minor=%d, Count=%d\n" FL, NAME, 
my_major, my_minor, count);

  // Driver
  rc = platform_driver_register(&xad_driver);
//  rc = platform_driver_probe(&xad_driver, xad_driver_probe);
  if (rc) goto err_plat;

  // Device
  pdev=platform_device_register_simple("xps-acqui-data", -1, NULL, 0);
  if (IS_ERR(pdev)) {
          rc = PTR_ERR(pdev);
          platform_driver_unregister(&xad_driver);
          goto err_plat;
  }


  return 0;

err_plat:
  unregister_chrdev_region(first, count);
Err:
  printk(KERN_ERR SD "Module %s: Failed loading rc=%d\n" FL, NAME, rc);
  return rc;
}

///////////////////////////////////////////////////////////////////////////////
// Called on rmmod
static void xad_exit(void) {
  platform_device_unregister(pdev); pdev=NULL;
  platform_driver_unregister(&xad_driver);
  
  cdev_del (my_cdev); my_cdev=NULL;
  unregister_chrdev_region (first, count);
  printk(KERN_INFO SD "Module %s unloaded\n" FL, NAME);
}

module_init(xad_init);
module_exit(xad_exit);

MODULE_AUTHOR("Guillaume Dargaud");
MODULE_LICENSE("GPL");





And here's the result:

# tail -f /var/log/messages &
# insmod xad.ko
Dec  7 14:42:02 gandalf user.info kernel: [15897.152109] {xad_init 162} Module 
xad: loading...
Dec  7 14:42:02 gandalf user.info kernel: [15897.156665] {xad_init 173} Module 
xad: Major=241, Minor=0, Count=1

# ./xad_test	# A simple prog that opens, does an iocl and closes the device
./xad_test Initialisation
./xad_test Ioctl
./xad_test Closing

Dec  7 14:42:16 gandalf user.info kernel: [15911.160343] {xad_open 130} 
OPENING device: xad
Dec  7 14:42:16 gandalf user.info kernel: [15911.164521] {xad_ioctl 142} IOCTL 
on device: xad, cmd:0, arg:0
Dec  7 14:42:16 gandalf user.info kernel: [15911.173035] {xad_release 136} 
RELEASING device: xad

# rmmod xad
Dec  7 14:42:23 gandalf user.info kernel: [15918.753661] {xad_exit 206} Module 
xad unloaded


And in the dts:

/dts-v1/;
/ {
	...
	plb: plb@0 {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "xlnx,plb-v46-1.05.a", "xlnx,plb-v46-1.00.a", "simple-
bus";
		ranges ;
		...
		xps_acqui_data_0: xps-acqui-data@c9800000 {
			compatible = "xlnx,xps-acqui-data-3.00.a";
			interrupt-parent = <&xps_intc_0>;
			interrupts = < 0 2 >;
			reg = < 0xc9800000 0x10000 >;
			xlnx,family = "virtex4";
			xlnx,include-dphase-timer = <0x1>;
			xlnx,mplb-awidth = <0x20>;
			xlnx,mplb-clk-period-ps = <0x2710>;
			xlnx,mplb-dwidth = <0x40>;
			xlnx,mplb-native-dwidth = <0x40>;
			xlnx,mplb-p2p = <0x0>;
			xlnx,mplb-smallest-slave = <0x20>;
		} ;
		...
	} ;
	...
}  ;


# ll /sys/devices/plb.0/c9800000.xps-acqui-data/
-r--r--r--    1 root     root        4.0K Dec  7 12:55 devspec
-r--r--r--    1 root     root        4.0K Dec  7 12:55 modalias
-r--r--r--    1 root     root        4.0K Dec  7 12:55 name
lrwxrwxrwx    1 root     root           0 Dec  7 12:55 subsystem -> 
../../../bus/of_platform/
-rw-r--r--    1 root     root        4.0K Dec  7 12:55 uevent

-- 
Guillaume Dargaud
http://www.gdargaud.net/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-08 10:18                           ` Guillaume Dargaud
@ 2010-12-08 13:45                             ` Michael Ellerman
  2010-12-08 15:52                               ` Guillaume Dargaud
  2010-12-08 19:20                               ` Joachim Förster
  0 siblings, 2 replies; 29+ messages in thread
From: Michael Ellerman @ 2010-12-08 13:45 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

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

On Wed, 2010-12-08 at 11:18 +0100, Guillaume Dargaud wrote:
> Thanks again for your detailed answer,
> I'm learning, but not as fast as my colleagues with a deadline want me to !

:)

> > The platform code does that. That function create devices on the
> > platform bus by examining the device tree. It looks for nodes that are
> > compatible with the compatible strings you give it, and treats them as
> > busses, ie. creates devices for all child nodes of those nodes.
> 
> Is there a way to enable some debug output from it, to see what's going on ?

Not really, but there probably should be.

> > > ...hmm I had to "git pull" in order for this to compile your snippet.
> > > That's really recent! Unfortunately i need to reflash my device with the
> > > new kernel before i can begin testing my module.
> > 
> > It shouldn't be that recent, what kernel version were you using?
> 
> I had to go from 2.6.34 to 2.6.35, xilinx git tree.

Ah that is the problem I think.

Sorry I assumed you were working on mainline. In 2.6.35 you still need
to use an of_platform_driver, I'll describe below.

> > platform_device_register() tends to be for cases where you can't
> > discover or probe a device, but you "know" that it exists.
> 
> When you see something in /sys/devices/plb.0/, it means that you don't need 
> platform_device_register, right ?

That's right.

> > Yes, "make tags", then use vim :)
> 
> Great, that works.

Cool.

> OK, here's the relevant part of my code, ripped directly from your sample, 
> with a few additions and different variable names. Why do you think 
> xad_driver_probe() is not being called ?

As I said above in 2.6.35 platform drivers and of_platform drivers were
still separate. So your device is on the of_platform_bus (ie. was
discovered using the device tree), but your driver is on the
platform_bus. Yes this is very confusing.

So basically you need to change all occurrences of platform_driver to
of_platform_driver.

> #include <linux/kernel.h>
> #include <linux/init.h>
> #include <asm/device.h>
> #include <linux/platform_device.h>
> #include <linux/cdev.h>         // char device
> #include <linux/fs.h>
> #include <linux/of.h>
> #include <linux/interrupt.h>
> 
> #define DEVNAME "xps-acqui-data"
> #define NAME "xad"              // This is only used for printk
> 
> #define SD "{%s %d} "
> #define FL , __func__, __LINE__
> 
> static dev_t first;
> static unsigned int count = 1;
> static int my_major = 241, my_minor = 0;
> // You must run "mknod /dev/xad c 241 0" in a shell at least once
> 
> struct cdev *my_cdev=NULL;
> struct platform_device *pdev=NULL;
> 
> typedef struct XadDevice {
>   struct resource *hw_region;
>   struct device *dev;
>   int irq;
> } tXadDevice;
> tXadDevice Xad;
> 
> // There should be something in:
> // ll /sys/devices/plb.0/c9800000.xps-acqui-data
> static const struct of_device_id xad_device_id[] = {                       
>         { .compatible     = "xlnx,xps-acqui-data-3.00.a" },     // Must match 
> the DTS
>         {}
> };
> 
>   
> static irqreturn_t XadIsr(int irq, void *dev_id) {
>   printk(KERN_INFO SD "IRQ:%d\n" FL, irq);
>   return IRQ_HANDLED;
> }
> 
> ///////////////////////////////////////////////////////////////////////////////
> // Platform Bus Support
> ///////////////////////////////////////////////////////////////////////////////
> 
> static int  xad_driver_probe(struct platform_device *device /*,
>                             const struct of_device_id *device_id*/ ) {

So you need to switch the prototype here to:

static int xad_driver_probe(struct of_platform_device *ofdev,
                            const struct of_device_id *device_id) {

>   struct device_node *dn = device->dev.of_node;
>   int rc;
> 
>   pr_devel("Probing %s\n", dn->full_name);
>   
>   Xad.irq = irq_of_parse_and_map(dn, 0);
>   rc=request_irq(Xad.irq, XadIsr, IRQF_TRIGGER_RISING  | IRQF_DISABLED, 
> "XadIsr", &Xad);
>   if (rc) printk(KERN_INFO SD "Failled IRQ request: %d\n" FL, rc);
>   
>   return 0;
> }
> 
> static int __devexit xad_driver_remove(struct platform_device *device) {
>   printk(KERN_INFO SD "Removing...\n" FL);
>   return 0;
> }
> 
> static struct platform_driver xad_driver = {

Becomes of_platform_driver

>   .probe  = xad_driver_probe,
>   .remove = xad_driver_remove,
>   .driver = {
>     .owner = THIS_MODULE,
>     .name = "xad-driver",
>         .of_match_table = xad_device_id,
>   },
> };
> 
> 
> ///////////////////////////////////////////////////////////////////////////////
> // This section deals with the /dev/xad device
> ///////////////////////////////////////////////////////////////////////////////
> static int xad_open(struct inode *node, struct file *filep) {
>   printk (KERN_INFO SD "OPENING device: %s\n" FL, NAME);
>   return 0;
> }
> 
> static int xad_release(struct inode *node, struct file *filep) {
>   printk (KERN_INFO SD "RELEASING device: %s\n" FL, NAME);
>   return 0;
> }
> 
> static int  xad_ioctl(struct inode *node, struct file *filep, unsigned int cmd, 
> unsigned long arg) {
>   printk (KERN_INFO SD "IOCTL on device: %s, cmd:%d, arg:%lu\n" FL, NAME, cmd, 
> arg);
>   return 0;
> }
> 
> static struct file_operations fops = {
>   .owner   = THIS_MODULE,
>   .open    = xad_open,
>   .release = xad_release,
>   .ioctl   = xad_ioctl,
> };
> 
> 
> ///////////////////////////////////////////////////////////////////////////////
> // Called on insmod
> static int __init xad_init(void) {
>   int rc=0;
>   printk(KERN_INFO SD "Module %s: loading...\n" FL, NAME);
>   
>   // Deal with the device
>   first = MKDEV (my_major, my_minor);
>   register_chrdev_region(first, count, DEVNAME);
>   my_cdev = cdev_alloc ();
>   if (NULL==my_cdev) goto Err;
>   
>   cdev_init(my_cdev, &fops);
>   cdev_add (my_cdev, first, count);
> 
>   printk(KERN_INFO SD "Module %s: Major=%d, Minor=%d, Count=%d\n" FL, NAME, 
> my_major, my_minor, count);
> 
>   // Driver
>   rc = platform_driver_register(&xad_driver);

Should be of_register_platform_driver()

> //  rc = platform_driver_probe(&xad_driver, xad_driver_probe);
>   if (rc) goto err_plat;
> 
>   // Device
>   pdev=platform_device_register_simple("xps-acqui-data", -1, NULL, 0);
>   if (IS_ERR(pdev)) {
>           rc = PTR_ERR(pdev);
>           platform_driver_unregister(&xad_driver);
>           goto err_plat;
>   }
> 
> 
>   return 0;
> 
> err_plat:
>   unregister_chrdev_region(first, count);
> Err:
>   printk(KERN_ERR SD "Module %s: Failed loading rc=%d\n" FL, NAME, rc);
>   return rc;
> }
> 
> ///////////////////////////////////////////////////////////////////////////////
> // Called on rmmod
> static void xad_exit(void) {
>   platform_device_unregister(pdev); pdev=NULL;
>   platform_driver_unregister(&xad_driver);
>   
>   cdev_del (my_cdev); my_cdev=NULL;
>   unregister_chrdev_region (first, count);
>   printk(KERN_INFO SD "Module %s unloaded\n" FL, NAME);
> }
> 
> module_init(xad_init);
> module_exit(xad_exit);
> 
> MODULE_AUTHOR("Guillaume Dargaud");
> MODULE_LICENSE("GPL");
> 
> 

cheers


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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-08 13:45                             ` Michael Ellerman
@ 2010-12-08 15:52                               ` Guillaume Dargaud
  2010-12-09  0:22                                 ` Michael Ellerman
  2010-12-08 19:20                               ` Joachim Förster
  1 sibling, 1 reply; 29+ messages in thread
From: Guillaume Dargaud @ 2010-12-08 15:52 UTC (permalink / raw)
  To: linuxppc-dev

> Sorry I assumed you were working on mainline. In 2.6.35 you still need
> to use an of_platform_driver, I'll describe below.

> So basically you need to change all occurrences of platform_driver to
> of_platform_driver.

OK, thanks, I did that, compiled and ran the driver and its test prog... no 
changes: xad_driver_probe() doesn't get called.
...?

-- 
Guillaume Dargaud
http://www.gdargaud.net/Antarctica/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-08 13:45                             ` Michael Ellerman
  2010-12-08 15:52                               ` Guillaume Dargaud
@ 2010-12-08 19:20                               ` Joachim Förster
  1 sibling, 0 replies; 29+ messages in thread
From: Joachim Förster @ 2010-12-08 19:20 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

Hi Guillaume,

Michael Ellerman wrote:
> On Wed, 2010-12-08 at 11:18 +0100, Guillaume Dargaud wrote:
>> ///////////////////////////////////////////////////////////////////////////////
>> // Called on insmod
>> static int __init xad_init(void) {
>>   int rc=0;
>>   printk(KERN_INFO SD "Module %s: loading...\n" FL, NAME);
>>   

Are you sure that you want to have the chrdev registration here (the
following code)?

Such stuff typically goes into the probe() function. The modules's
init() just registers the driver. Furthermore your global variables
prohibit having more than one device instance using the driver.

>>   // Deal with the device
>>   first = MKDEV (my_major, my_minor);
>>   register_chrdev_region(first, count, DEVNAME);
>>   my_cdev = cdev_alloc ();
>>   if (NULL==my_cdev) goto Err;
>>   
>>   cdev_init(my_cdev, &fops);
>>   cdev_add (my_cdev, first, count);
>>
>>   printk(KERN_INFO SD "Module %s: Major=%d, Minor=%d, Count=%d\n" FL, NAME, 
>> my_major, my_minor, count);
>>
>>   // Driver
>>   rc = platform_driver_register(&xad_driver);
> 
> Should be of_register_platform_driver()
> 
>> //  rc = platform_driver_probe(&xad_driver, xad_driver_probe);
>>   if (rc) goto err_plat;
>>

I think the following function call to platform_device_register_simple()
and if() does not belong here.

As was said before, "devices" are registered by the (platform) bus. Your
driver module, needs to just register, well, the "driver". You are doing
this above - and that's it: (of_)platform_driver_register().

>>   // Device
>>   pdev=platform_device_register_simple("xps-acqui-data", -1, NULL, 0);
>>   if (IS_ERR(pdev)) {
>>           rc = PTR_ERR(pdev);
>>           platform_driver_unregister(&xad_driver);
>>           goto err_plat;
>>   }
>>
>>
>>   return 0;
>>
>> err_plat:
>>   unregister_chrdev_region(first, count);
>> Err:
>>   printk(KERN_ERR SD "Module %s: Failed loading rc=%d\n" FL, NAME, rc);
>>   return rc;
>> }

 Joachim

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-08 15:52                               ` Guillaume Dargaud
@ 2010-12-09  0:22                                 ` Michael Ellerman
  2010-12-10 16:21                                   ` Guillaume Dargaud
  0 siblings, 1 reply; 29+ messages in thread
From: Michael Ellerman @ 2010-12-09  0:22 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

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

On Wed, 2010-12-08 at 16:52 +0100, Guillaume Dargaud wrote:
> > Sorry I assumed you were working on mainline. In 2.6.35 you still need
> > to use an of_platform_driver, I'll describe below.
> 
> > So basically you need to change all occurrences of platform_driver to
> > of_platform_driver.
> 
> OK, thanks, I did that, compiled and ran the driver and its test prog... no 
> changes: xad_driver_probe() doesn't get called.
> ...?

Er. Not sure sorry. I can't see anything obviously wrong. Maybe post
your driver code again.

Also turn on CONFIG_DEBUG_DRIVER and see if that gives you anything
interesting.

cheers



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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-09  0:22                                 ` Michael Ellerman
@ 2010-12-10 16:21                                   ` Guillaume Dargaud
  2010-12-12 21:46                                     ` Michael Ellerman
  0 siblings, 1 reply; 29+ messages in thread
From: Guillaume Dargaud @ 2010-12-10 16:21 UTC (permalink / raw)
  To: linuxppc-dev

Hello all,

> Are you sure that you want to have the chrdev registration here (the
> following code)?

It was commented out in my lastest attempts after reading Michael's 
explainations.

> Such stuff typically goes into the probe() function. The modules's
> init() just registers the driver. Furthermore your global variables
> prohibit having more than one device instance using the driver.

Only one such device will ever be build, so don't expect a mainline kernel 
patch from me anytime soon !   C;-)

> Also turn on CONFIG_DEBUG_DRIVER and see if that gives you anything
> interesting.

I see an unset CONFIG_DEBUG_KERNEL but no CONFIG_DEBUG_DRIVER in the .config of 
my current kernel. 
Does it need to be changed in the .config with a full kernel recompilation, or 
can I still benefit from it in my module only by doing a #define at the begining 
of my code ? Some #defines like DEBUG seem to work locally on things like 
dev_dbg but I doubt the CONFIG_* work the same...

> Er. Not sure sorry. I can't see anything obviously wrong. Maybe post
> your driver code again.

Err... I ran it again this morning and it worked farther. I now get into the 
probe function and can now register my interrupt, yeah!, but I don't see the 
ISR being called. I'm currently checking if it can be a hardware problem 
before coming back here for more questions !

BTW, is errno/strerror used within the kernel ?

Thanks all.
-- 
Guillaume Dargaud
http://www.gdargaud.net/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
  2010-12-10 16:21                                   ` Guillaume Dargaud
@ 2010-12-12 21:46                                     ` Michael Ellerman
  0 siblings, 0 replies; 29+ messages in thread
From: Michael Ellerman @ 2010-12-12 21:46 UTC (permalink / raw)
  To: Guillaume Dargaud; +Cc: linuxppc-dev

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

On Fri, 2010-12-10 at 17:21 +0100, Guillaume Dargaud wrote:
> Hello all,

> 
> > Also turn on CONFIG_DEBUG_DRIVER and see if that gives you anything
> > interesting.
> 
> I see an unset CONFIG_DEBUG_KERNEL but no CONFIG_DEBUG_DRIVER in the .config of 
> my current kernel. 

Right you'd need to turn on CONFIG_DEBUG_KERNEL first, and then
CONFIG_DEBUG_DRIVER will appear.

> Does it need to be changed in the .config with a full kernel recompilation, or 
> can I still benefit from it in my module only by doing a #define at the begining 
> of my code ? Some #defines like DEBUG seem to work locally on things like 
> dev_dbg but I doubt the CONFIG_* work the same...

No you'd need to rebuild your kernel. DEBUG is the only #define I can
think of that has an effect locally. Using different values for a
CONFIG_ in the kernel vs modules will not work.

> > Er. Not sure sorry. I can't see anything obviously wrong. Maybe post
> > your driver code again.
> 
> Err... I ran it again this morning and it worked farther. I now get into the 
> probe function and can now register my interrupt, yeah!, but I don't see the 
> ISR being called. I'm currently checking if it can be a hardware problem 
> before coming back here for more questions !

Great!

> BTW, is errno/strerror used within the kernel ?

Nope.

cheers



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

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2010-12-12 21:46 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-12-01 10:15 Basic driver devel questions ? Guillaume Dargaud
2010-12-01 12:19 ` Michael Ellerman
2010-12-01 16:35   ` Getting the IRQ number (Was: Basic driver devel questions ?) Guillaume Dargaud
2010-12-01 18:29     ` Philipp Ittershagen
2010-12-01 18:41     ` Scott Wood
2010-12-02 15:36       ` Guillaume Dargaud
2010-12-02 16:17         ` Timur Tabi
2010-12-02 17:47           ` Guillaume Dargaud
2010-12-02 20:22             ` Benjamin Herrenschmidt
2010-12-03 14:58               ` Guillaume Dargaud
2010-12-03 15:37                 ` Martyn Welch
2010-12-06  5:29                 ` Michael Ellerman
2010-12-06  6:35                   ` Jeremy Kerr
2010-12-06 11:56                     ` Michael Ellerman
2010-12-06  9:58                   ` Guillaume Dargaud
2010-12-06 12:07                     ` Michael Ellerman
2010-12-06 14:44                       ` Guillaume Dargaud
2010-12-06 14:47                         ` David Laight
2010-12-08  1:03                         ` Michael Ellerman
2010-12-08 10:18                           ` Guillaume Dargaud
2010-12-08 13:45                             ` Michael Ellerman
2010-12-08 15:52                               ` Guillaume Dargaud
2010-12-09  0:22                                 ` Michael Ellerman
2010-12-10 16:21                                   ` Guillaume Dargaud
2010-12-12 21:46                                     ` Michael Ellerman
2010-12-08 19:20                               ` Joachim Förster
2010-12-06 12:17                     ` David Laight
2010-12-07 12:46                   ` Guillaume Dargaud
2010-12-08  0:50                     ` Michael Ellerman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.