Getting the IRQ number (Was: Basic driver devel questions ?)
Michael Ellerman
michael at ellerman.id.au
Thu Dec 9 00:45:10 EST 2010
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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part
URL: <http://lists.ozlabs.org/pipermail/linuxppc-dev/attachments/20101209/9e22f3c7/attachment.pgp>
More information about the Linuxppc-dev
mailing list