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