Hi all,

I'm attempting to write a platform device driver that gets loaded when
a compatible device-tree overlay is loaded by dtoverlay.

This is just a learning exercise at the moment, so I'm trying to write
the simplest platform device I can, rather than extending one of the device 
drivers that extend platform device (terminology?). I'm trying to get just 
enough to get the driver's probe() function called when the device-tree overlay 
is applied, and then create a misc device.

My module seems to init just fine, and the device-tree overlay seems
to also load without issue, but for some reason probe() is never
called.

Am I correct in using probe() with platform devices? I understand
platform devices can't be enumerated/detected, but I thought that probe() would 
be called when there was a compatibility match between the driver and the 
device-tree overlay.

Any pointers would be much appreciated.

Cheers,
Laurence.


Here's what /sys shows:

$ cat /sys/devices/platform/gde060f3/uevent
OF_NAME=gde060f3
OF_FULLNAME=/gde060f3
OF_COMPATIBLE_0=gde060f3
OF_COMPATIBLE_N=1
MODALIAS=of:Ngde060f3T<NULL>Cgde060f3

$ cat /sys/firmware/devicetree/base/gde060f3/compatible 
gde060f3

$ cat /sys/firmware/devicetree/base/gde060f3/name
gde060f3

$ cat /sys/firmware/devicetree/base/gde060f3/status
okay


Here's the loaded device-tree:

$ dtc -I fs /proc/device-tree
/dts-v1/;

/ {
        compatible = "raspberrypi,3-model-b-plus", "brcm,bcm2837";
        serial-number = "00000000427625f0";
        model = "Raspberry Pi 3 Model B Plus Rev 1.3";
        memreserve = <0x3b400000 0x4c00000>;
        interrupt-parent = <0x1>;
        #address-cells = <0x1>;
        #size-cells = <0x1>;

        clocks {
        *** SNIPPED ***
        };

        __overrides__ {
        *** SNIPPED ***
        };

        gde060f3 {
                compatible = "gde060f3";
                status = "okay";
                phandle = <0x7b>;
                linux,phandle = <0x7b>;
        };

        system {
                linux,serial = <0x0 0x427625f0>;
                linux,revision = <0xa020d3>;
        };

        *** SNIPPED ***
};


module file:

#define DEBUG

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>

struct gde060f3_struct {
        struct platform_device *pdev;
        struct miscdevice mdev;
};

static inline struct gde060f3_struct *to_gde060f3_struct(struct file *file)
{
        struct miscdevice *miscdev = file->private_data;
        return container_of(miscdev, struct gde060f3_struct, mdev);
}

static ssize_t gde060f3_read(struct file *file, char __user *buf, size_t count,
                             loff_t *pos)
{
        struct gde060f3_struct *gde060f3 = to_gde060f3_struct(file); /* just 
for example */

        (void)gde060f3; /* unused */
        return simple_read_from_buffer(buf, count, pos, "gde060f3 text", 14);
}

static const struct file_operations gde060f3_fops = {
        .owner  = THIS_MODULE,
        .read   = gde060f3_read,
};

static const struct of_device_id gde060f3_match[] = {
        { .compatible = "gde060f3" },
        {},
};
MODULE_DEVICE_TABLE(of, gde060f3_match);

static int gde060f3_probe(struct platform_device *pdev)
{
        struct gde060f3_struct *gde060f3;
        int ret;

        pr_info("gde060f3_probe()\n");
        gde060f3 = kmalloc(sizeof(*gde060f3), GFP_KERNEL);
        if (!gde060f3)
                return -ENOMEM;

        platform_set_drvdata(pdev, gde060f3);
        gde060f3->pdev = pdev;

        gde060f3->mdev.minor  = MISC_DYNAMIC_MINOR;
        gde060f3->mdev.name   = "gde060f3";
        gde060f3->mdev.fops   = &gde060f3_fops;
        gde060f3->mdev.parent = NULL;

        ret = misc_register(&gde060f3->mdev);
        if (ret) {
                dev_err(&pdev->dev, "Failed to register miscdev\n");
                return ret;
        }

        dev_info(&pdev->dev, "Registered\n");
        pr_info("Registered\n");

        return 0;
}

static int gde060f3_remove(struct platform_device *pdev)
{
        struct gde060f3_struct *gde060f3 = platform_get_drvdata(pdev);

        misc_deregister(&gde060f3->mdev);
        kfree(gde060f3);
        dev_info(&pdev->dev, "Unregistered\n");
        pr_info("Unregistered\n");

        return 0;
}

static struct platform_driver gde060f3_driver = {
        .probe      = gde060f3_probe,
        .remove     = gde060f3_remove,
        .driver = {
                .name = "gde060f3",
                .of_match_table = gde060f3_match,
        },
};

module_platform_driver_probe(gde060f3_driver, gde060f3_probe);


MODULE_AUTHOR("Laurence Rochfort <[email protected]>");
MODULE_DESCRIPTION("GPIO  driver for Good Display GDE060F3 ePaper Display");
MODULE_LICENSE("GPL");




overlay file:

/dts-v1/;
/plugin/;

/ {
        compatible = "brcm,bcm2708";
        fragment@0 {
                // target or target-path?
                target-path = "/";
                __overlay__ {
                        gde060f3: gde060f3 {
                                compatible = "gde060f3";
                                status = "okay";
                        };
                };
        };
};

_______________________________________________
Kernelnewbies mailing list
[email protected]
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

Reply via email to