Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to parse platform bus in Linux driver

2025-01-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

How to parse the platform bus in the Linux driver, many novices are not very clear about this. In order to help you solve this problem, the following editor will explain it in detail. People with this need can come and learn. I hope you can get something.

1. Brief introduction of platform bus 1.1, separation and layering of Linux drivers 1.1.1, separation of Linux drivers

First of all, let's talk about the separation of Linux drivers. The Linux operating system supports running on all kinds of CPU, because each CPU has different drivers for devices, which results in a large amount of code accumulated in the Linux kernel, and these codes have roughly the same description of the same device, which makes the kernel code very redundant. Take CPU controlling MPU6050 through I2C as an example:

From the figure, we can see that there is a set of host drivers and a set of device drivers under each platform. Because the I2C controller of each platform is different, this host driver should be equipped with its own for each platform, but the MPU6050 used by everyone is the same, so it is possible to share a set of device driver code. The improved framework is as follows:

Of course, this is only for the MPU6050 under I2C, in fact, a lot of devices will be mounted under I2C. According to this idea, we can get the framework as follows:

In the actual development, the I2C host driver semiconductor manufacturer will write, and the device driver will also be written by the equipment manufacturer. We only need to provide the equipment information, such as the I2C speed when the device is connected to that I2C interface. This is equivalent to stripping the device information from the device driver, and the device driver will also use standard methods to obtain device information (such as getting device information from the device tree). This is equivalent to the driver is only responsible for the driver, the device (information) is only responsible for the device, find a way to match the two, to do this matching work is the bus, which constitutes the bus-driver-device model in Linux. The structure diagram is as follows:

1.2.The platform platform driver model

Above we talk about the separation of device drivers, get the bus-driver-device model, this bus is what I usually call I2C, SPI, USB and other buses. But the problem is that some devices do not need to go through a certain follow-up bus, which introduces the platform bus.

It should be noted that platform bus is a virtual bus which is different from USB, SPI and I2C buses. It is said that it is virtual because SoC addresses some peripherals such as LED, timer and buzzer through the addressing space of memory, so CPU does not need a bus to communicate with these devices at all, so there is no such bus on hardware. However, the kernel has the need for unified management of these devices, so a virtual platform bus is created for these devices that are directly addressed through memory, and all devices that are directly addressed through memory are mapped to this virtual bus.

Advantages of platform bus:

1. Through the platform bus, you can traverse all the devices mounted on the platform bus

2. Realize the separation of the device and the driver. Through the platform bus, the device and the driver are registered separately. Because there is a probe function, the driver that matches the device can be detected at any time. If the matching is successful, the driver will be registered with the kernel.

3. A driver can be used by several devices of the same kind. This function is realized because there is an operation to traverse the device in the process of driver registration.

2. Platform Framework 2.1and platform bus

The Linux kernel uses the bus_type structure to represent the bus, and the I2C, SPI, and USB we use are all defined by this structure. The structure is as follows:

/ * include/linux/device.h * / struct bus_type {const char * name; / * bus name * / const char * dev_name; struct device * dev_root; struct device_attribute * dev_attrs; const struct attribute_group * * bus_groups; / * bus attribute * / const struct attribute_group * * dev_groups / * device attributes * / const struct attribute_group * * drv_groups; / * driver attributes * / int (* match) (struct device * dev, struct device_driver * drv); / * device driver matching function * / int (* uevent) (struct device * dev, struct kobj_uevent_env * env); int (* probe) (struct device * dev); int (* remove) (struct device * dev) Void (* shutdown) (struct device * dev); int (* online) (struct device * dev); int (* offline) (struct device * dev); int (* suspend) (struct device * dev, pm_message_t state); int (* resume) (struct device * dev); const struct dev_pm_ops * pm; const struct iommu_ops * iommu_ops; struct subsys_private * p; struct lock_class_key lock_key;}

The platform bus is a constant of type bus_type. It is said to be constant because this variable has been assigned by the Linux kernel, and the corresponding function of its structure member has been written in the kernel.

The definition is as follows:

/ * drivers/base/platform.c * / struct bus_type platform_bus_type = {.name = "platform", .dev _ groups = platform_dev_groups, .match = platform_match, / * matching function * / .uevent = platform_uevent, .pm = & platform_dev_pm_ops,}

Platform_match in platform_bus_type is the function we mentioned earlier to match driver and device. This function is defined as follows:

/ * drivers/base/platform.c * / static int platform_match (struct device * dev, struct device_driver * drv) {struct platform_device * pdev = to_platform_device (dev); struct platform_driver * pdrv = to_platform_driver (drv); / * When driver_override is set,only bind to the matching driver*/ if (pdev- > driver_override) return! strcmp (pdev- > driver_override, drv- > name) / * device tree OF type matching the compatible matching table in the of_match_table of the driver base class is compared with the compatible attribute of each device node in the device tree. The same means that the match is successful * / if (of_driver_match_device (dev, drv)) return 1; / * ACPI matching * / if (acpi_driver_match_device (dev, drv)) return 1 / * id_table matching the id_table array in the platform driver will save a lot of id information * / if (pdrv- > id_table) return platform_match_id (pdrv- > id_table, pdev)! = NULL; / * name match directly compare the name information in the platform driver and the device * / return (strcmp (pdev- > name, drv- > name) = = 0);}

When and where to use this matching function, we might as well leave a suspense.

2.2.2. platform driver 2.2.1, platform driver definition

The platform driver is represented by the structure platform_driver, which contains:

/ * include/linux/platform_device.h * / struct platform_driver {int (* probe) (struct platform_device *); / * this probe function will be executed when the platform driver matches the platform device * / int (* remove) (struct platform_device *); void (* shutdown) (struct platform_device *); int (* suspend) (struct platform_device *, pm_message_t state); int (* resume) (struct platform_device *) Struct device_driver driver; / * driver base class * / const struct platform_device_id * id_table; / * id_ table * / bool prevent_deferred_probe;}

Const struct platform_device_id * id_table in platform_driver is the id_table table, which is used in the id_table table matching method when platform bus matches drivers and devices. This id_table table is actually an array in which each element type is platform_device_id,platform_device_id is a structure, and the contents are as follows:

Struct platform_device_id {char name [platform _ NAME_SIZE]; kernel_ulong_t driver_data;}

Driver in platform_driver is a driver base class, which is equivalent to the most basic properties of drivers, and the attributes under different buses are stored under the platform_driver structure.

The device_driver of the driver base class structure is as follows:

The fourth way for / * include/linux/device.h * / struct device_driver {const char * name; / * platform bus to match the device and driver is to directly and roughly match their name fields * / struct bus_type * bus; struct module * owner; const char * mod_name Bool suppress_bind_attrs; const struct of_device_id * of_match_table; / * matching table used by drivers when using device tree * / const struct acpi_device_id * acpi_match_table; int (* probe) (struct device * dev); int (* remove) (struct device * dev); void (* shutdown) (struct device * dev); int (* suspend) (struct device * dev, pm_message_t state) Int (* resume) (struct device * dev); const struct attribute_group * * groups; const struct dev_pm_ops * pm; struct driver_private * p;}

Of_match_table in driver is also a matching table. This matching table is used by platform bus to match drivers and devices using device tree matching. It is also an array. The array elements are of type of_device_id. The structure of this type is as follows:

/ * include/linux/mod_devicetable.h * / struct of_device_id {char name [32]; char type [32]; char compatible [128]; / * when using device tree matching, the compatible attribute value of the device node is compared with the compatible of each item in the of_match_table. If it is equal, it means that the device and driver match successfully * / const void * data }; 2.2.2, platform driver registration

After defining the platform driver with the platform_driver structure, register the platform driver with the Linux kernel with the platform_driver_register function. The general flow of the function is as follows:

Platform_driver_register (drv)-> _ _ platform_driver_register-> drv- > driver.probe = platform_drv_probe / * assign the platform_drv_probe function to the probe function of the driver base class drier in the platform driver * /-> driver_registe (& drv- > driver) / * register the driver base class driver * /-> with the Linux kernel. -> drv- > driver- > probe / * finally executes the probe function that drives the base class driver In fact, the platform_drv_probe function given above * /-> platform_drv_probe-> drv- > probe / * platform_drv_probe function will be executed again. Platform drives the probe function of drv * /

In the above analysis, we have replaced the step from driver_register (& drv- > driver) to drv- > driver- > probe with ellipses. Now let's do some analysis:

Driver_register (& drv- > driver)-> bus_add_driver / * add drivers to the bus * /-> driver_attach-> bus_for_each_dev / * find every device under the bus That is, the traversal operation * /-> _ _ driver_attach / * each device calls this function * /-> driver_match_device / * to check whether it matches * /-> call the match matching function under bus-> driver_probe Execute this function after the _ device / * match * /-> really_probe-> drv- > probe / * execute the probe function under drv * /

According to the driver_register function flow, we know that the bus match matching function will be used here, which answers a question we left before: where to use the bus match function, and once the match is successful, it will enter the driver probe function.

According to the flow of platform_driver_register function, we can draw a conclusion: in the process of registering platform driver with Linux kernel, there will be a process of traversing the matching between driver and device. After successful matching, the probe function of platform driver will eventually be executed. In the process, the probe function and platform_drv_probe function of the driver base class driver are just transit functions to achieve this purpose.

It is worth noting that the probe function of platform driver that will eventually be executed is written by us, so the initiative is back in our hands.

2.3. platform device 2.3.1, platform device definition

If the Linux version we use supports the device tree, then describe the device in the device tree. If the device tree is not supported, define the platform device. One point we need to consider here is that the matching function match under the bus matches the device tree first, then the id_table table, and then the name field. When supporting the device tree, change the device information directly in the device tree node. The kernel will automatically traverse the device tree node when the kernel starts, and a platform_device will be automatically generated when the match is successful, which will be used in the next step. If it is not a device tree, the platform_device is written by the developer.

Here we do not need the device tree, we define platform devices ourselves. Platform devices are represented by a platform_device structure, which is defined as follows:

/ * include/linux/platform_device.h * / struct platform_device {const char * name; / * device name, which must be the same as the name of the corresponding platform driver, otherwise the device cannot match the corresponding driver * / int id; bool id_auto; struct device dev; U32 num_resources; struct resource * resource Const struct platform_device_id * id_entry; char * driver_override; / * Driver name to force a match * / / * MFD cell pointer * / struct mfd_cell * mfd_cell; / * arch specific additions * / struct pdev_archdata archdata;}; 2.4. Platform matching process

In fact, the matching process of platform bus to drivers and devices has been talked about in bits and pieces, and now we put it together and go over it again.

As mentioned earlier, the matching of drivers and devices under the bus is realized through the match function under the bus. The match function corresponding to different buses must be different. We don't have to worry about this, the kernel will write it. The match function corresponding to the platform bus we use is the platform_match function. Analyze this function:

Platform_match-> of_driver_match_device / * device tree matching * /-> acpi_driver_match_device / * ACPI matching * /-> platform_match_id / * platform_driver- > id_table matching * /-> strcmp (pdev- > name, drv- > name) / * name matching * /

Through a simple analysis of the matching function above, we know that the matching order of the matching function is to match the device tree first, then the id_table table, and then the brute force match name field. For the Linux version that supports the device tree, we will do the device tree matching as soon as we come up. When the device tree is not supported, we have to define the platform device, and then use the id_tabale table or name to match. Generally, we choose name matching.

Now let's take a look at the matching process under the condition of device tree:

The of_driver_match_device / * of function is generally used for device trees. This also gives us a hint * /-> of_match_device (drv- > of_match_table, dev)-> of_match_node-> _ _ of_match_node-> _ _ of_device_is_compatible-> _ _ of_find_property (device, "compatible", NULL) / * take out the compatible attribute value * /

Looking at the above analysis, we know that the matching process ultimately drives the compatible in the of_match_table of the base class to the compatible attribute in the device tree node for comparison. This is a mechanism of stringing the device tree with the platform bus, thus realizing the purpose of writing device information in the corresponding node of the device tree and driving separately, that is, the driver separation we mentioned earlier.

3. Summary

In the specific development process, we do not really need to write a platform bus model, we have been defined in the kernel. Our analysis of the platform bus model is mainly to figure out how to match the driver and the device, that is, when we insert the device how to find the corresponding driver or insert the driver how to find the corresponding device, and finally call the probe function. In fact, whether there is a driver before a device, or a device before a driver, the first thing to do after a successful match is to execute the driver's probe function, so we can rest assured to ignore the tortuous emotional entanglements in the middle and focus directly on the final probe function.

Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report