Recently, I was looking at the driver model, but the more confused I was, the more I used to come into contact with some character drivers. I have a certain understanding of the character-driven framework. Later, I wanted to create a device file in the driver. I also learned that the sysfs file system and udev file system will inevitably involve the driver model. However, we found that the driver model has no connection with the character drivers that we previously used.
For example, before writing a character driver, the main content is to implement functions in the file_operations struct, and then apply for a device number and register a character device, there is no device driver model involved. In the driver model, device_driver does not involve functions related to device operations, such as file_operations. There are only some functions related to power management and hot swapping. Platform_device is mainly used for resource management, so it doesn't matter at all. It's also strange why we need to implement two sets of things, and the two cannot match.
Later I looked at some of the driver source code in the kernel and found that many of them were implemented using miscdevice, platform_device, and platform_driver, and the process was very similar:
1. Register platform_device during system initialization. Add resources corresponding to the device to the linked list so that the system can manage the resources occupied by the device in a unified manner;
2. Implement platform_driver and register it. In this part, we need to implement probe in the platform_driver structure, remove, shutdown, and other functions on hot swapping and power management.
3. Register platform_driver (platform_driver_register) in the module initialization function (xx_init)
The device Resource Acquisition (platform_get_resource), such as IO memory, IO port, interrupt number, request, physical address to virtual address ing (ioremap ), misc_device registration (misc_register), clock acquisition (clk_get) and enable (clk_enable) are all implemented in the probe function. When the probe function is registered in the platform_driver, or when a new device is added, after the platform_device and platform_driver match (by name) successfully, the registration process is different from the character driver used in the past.
For misc_device, the implementation of the device operation function is the same as that of the character device. The file_operations struct is filled and then registered in the module initialization function (misc_register ).
For the platform driver model, platform_device is responsible for device resources, platform_driver is responsible for power management, resource application, interrupted registration, and other device initialization and startup operations, then there is the registration of the device operation method (file_operations) (misc_register or cdev_add), and The cdev or misc_device is responsible for file_operations.
However, there are still many questions:
1. Where can I apply for a device number? How can I put it in the device structure of the driver model?
2. The platform_driver struct and the device_driver struct contain probe, remove, and shutdown. Why do we need to put repeated items in the outer layer? What are the relationships and differences between the two?
3. In the misc_register implementation, device_add will be called in the same way as platform_device_register. In this way, there are not two devices in the device driver model that correspond to device_driver, but there is only one physical device?
4. It seems that the driver model is an abstraction of the actual device and driver. extract their information and package it into the kernel object kobject, then, they are classified and managed hierarchically (Building a tree) based on their relationships. These objects are managed by the system to apply for registration, release, and actually drive (file_operations) of device resources) and power management (the system can decide the order of device shutdown Based on the Device Tree, device-> device_driver-> shutdown ).
Therefore, in the device driver model, the device is only used to establish the Device Tree. In the end, the device will implement a reasonable Power Switch Sequence Based on the power management function in the device_driver in the structure?
The functions related to hot swapping are related to the matching process of device and device_driver, but are irrelevant to the hierarchical relationship of the device tree?
()
========================================================== ========
The driver program of Linux devices has encountered chaos recently. please let us know.
In the Linux Device Model: bus_type, device, device_driver
In the Linux device model chapter of Linux Device Drivers, all devices are connected by bus.
To add a device Deva, you must specify the bus_type domain of the device struct, initialize other domains, and then call device_register (& Deva) to Deva the device.
Register with the specified bus.
To add drivera, you must specify the bus_type field of the device_driver struct, initialize other domains, and then call driver_register (& drivera ),
Register the driver on the bus.
If the driver drivera and the device Deva match successfully, that is, the probe function is successfully called, a symbolic link between them is established to bind the device with the driver.
In reality, platform_device is widely used in Linux source code,
Struct platform_device {
Const char * Name;
U32 ID;
Struct device dev;
U32 num_resources;
Struct resource * resource;
};
And
Struct platform_driver {
INT (* probe) (struct platform_device *);
INT (* remove) (struct platform_device *);
Void (* shutdown) (struct platform_device *);
INT (* suspend) (struct platform_device *, pm_message_t State );
INT (* suspend_late) (struct platform_device *, pm_message_t State );
INT (* resume_early) (struct platform_device *);
INT (* resume) (struct platform_device *);
Struct device_driver driver;
};
From the structure, we can see that platform_device is derived from device, and platform_driver is derived from device_driver.
The device platformdeva is also added. When the dev domain of the platform_device struct is initialized, its bus_type domain is not initialized, but the device is actually added to the Sys \ bus \ platform \ devices directory,
You can see this part of code in the source code.
Similarly, the driver platformdrva is added. When the driver domain of the platform_driver struct is initialized, its bus_type domain is not initialized. Instead, the driver is actually added to the Sys \ bus \ platform \ DRIVERS directory,
You can see this part of code in the source code.
And
Struct miscdevice {
Int minor;
Const char * Name;
Const struct file_operations * fops;
Struct list_head list;
Struct device * parent;
Struct device * this_device;
};
And memory devices
Struct cdev {
Struct kobject kobj;
Struct module * owner;
Const struct file_operations * OPS;
Struct list_head list;
Dev_t dev;
Unsigned int count;
};
From the struct, we can see that miscdevice is derived from device, which is different from platform_device:
1. platform_device contains the information resource of the resources used by the device.
2. Use file_operations in miscdevice.
From the device driver source code:
Step 1
Static struct platform_device at91sam9260_adc_device = {
. Name = "at91_adc ",
. ID =-1,
. Dev = {
. Platform_data = & adc_data,
},
. Resource = adc_resources,
. Num_resources = array_size (adc_resources ),
};
Static struct resource spi0_resources [] = {
[0] = {
. Start = at91sam9260_base_spi0,
. End = at91sam9260_base_spi0 + sz_16k-1,
. Flags = ioresource_mem,
},
[1] = {
. Start = at91sam9260_id_spi0,
. End = at91sam9260_id_spi0,
. Flags = ioresource_irq,
},
};
// Add this device to the system and register the device resources
Platform_device_register (& at91sam9260_adc_device );
Step 2:
Static struct file_operations at91_adc_fops = {
. Owner = this_module,
. IOCTL = at91_adc_ioctl,
. Read = at91_adc_readdata,
. Open = at91_adc_open,
. Release = at91_adc_release,
};
Static struct miscdevice at91_adc_dev = {
. Minor = misc_dynamic_minor,
. Name = "ADC ",
. Fops = & at91_adc_fops,
};
// Add this device to the system and register the device usage
Misc_register (& at91_adc_dev );
Step 3:
Static struct platform_driver at91_i2c_driver = {
. Probe = at91_adc_probe,
. Remove = _ devexit_p (at91_adc_remove ),
. Suspend = at91_adc_suspend,
. Resume = at91_adc_resume,
. Driver = {
. Name = "at91_adc ",
. Owner = this_module,
},
};
// Register the driver for this device
Platform_driver_register (& at91_i2c_driver );
These three struct relationships:
(Base class)
Kobject -------
/\\
/\\
Device cdev driver
// \ (Device Driver Operation Method )\
/\\
Miscdevice platform_device platform_driver
(Device Driver Operation Method) (device resources) (Device Driver)
My questions:
1. When I write a driver for a balanced device, I generally only use the cdev struct. This method does not seem to display the device in sysfs.
2. Does miscdevice support character devices and Block devices. If you use it to identify Block devices or character devices.
3. Whether miscdevice, platform_device, and platform_driver can be used as common device driver methods, and platform_device registers device resources.
How to Use platform_driver to register a device driver and miscdevice to register a device.