Platform driver probe() not being called when device-tree overlaid
Laurence Rochfort
laurence.rochfort at gmail.com
Fri Feb 15 14:38:59 EST 2019
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 <laurence.rochfort at gmail.com>");
MODULE_DESCRIPTION("GPIO driver for Good Display GDE060F3 ePaper Display");
MODULE_LICENSE("GPL");
overlay file:
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2708";
fragment at 0 {
// target or target-path?
target-path = "/";
__overlay__ {
gde060f3: gde060f3 {
compatible = "gde060f3";
status = "okay";
};
};
};
};
More information about the Kernelnewbies
mailing list