How to Perform id table Matching in a Platform Device Driver in Linux

Beaglebone black board

In this article, we explain and demonstrate how to perform id table matching in a platform device driver in linux.

Perhaps one of the simplest types of matching in a platform device driver in linux is name based matching.

The name based matching is when a platform driver probes platform devices for a match based on the name attribute.

It functions kind of just like a search engine.

You would specify a name that the platform driver is to seek and the platform driver would probe all devices in a match for this name. It would match with all devices that have this name.

id table matching is a more sophisticated search.

When would you use id table matching?

id table matching would be used more if you have several devices that may be slightly different.

For example, you are using 3 sensors but they are different versions.

For example, maybe you are using 3 different temperature sensors in an embedded system, and each sensor is made by the same manufacturer but they are different versions. They may vary based on a few parameters, such as one being able to detect higher or lower temperatures than another.

Another example is proximity sensors in that you have different versions that vary in terms of the distance that the sensor can detect up to. For example, one may detect up to 20cm of distance, another 50 cm, another up to 100cm. Otherwise, they have the same functioning.

In this case, you wouldn't create a separate driver for each, being that it's the roughly the same sensor with minor variations. You would simply create one platform driver and can give each device its own id. You can refer to each id as it actually is. For example, if sensor 1 is ABC123, sensor 2 is DEF345, sensor 3 is GHI678, and sensor 4 is JKL123, you can specify these as the id values.

So before we go into the actual code to implement this id table, let's go over important code in the linux source file that summarize this process first.

The first structure we want to look at is the platform_driver structure, which is the foundation for our platform driver that we will build.

In order to create our platform driver, we must create structures to implement the probe functionality, as can be seen in this structure, amongst others.

platform_driver structure in linux

Specifically, in the case of creating device matching by id tables, you see in the second-to-last line that there is a structure of type platform_device_id named *id_table

This platform_device_id structure is found in the /include/linux/mod_devicetable.h header file.

It is actually a very simple structure consisting of 2 fields, a name field and a driver_data field (which is of long integer type).

The name field is the id name which we will give each device.

The driver_data field is a field where the driver can extract data from about each of the devices.

One important thing worth mentioning and understanding is, how does the driver know to do name-based matching or id table matching or any other type of matching?

How this works is on a system of priority.

This is displayed in the platform_match() function in the includes/drivers/base/platform.c file shown below.

platform_match() function in linux

The platform_match function is a function that the driver software uses to match with matching devices.

How it does so can be done in a variety of ways.

The platform_match() function will attempt matching by an OF style match first. If there is no OF style match code present, it will then attempt to match by ACPI style match. If this is not present, then it will try to match against the id table. If there is no id table present, then it will attempt to name match.

So if a code has an id table present and a name present in the platform driver code, the id table matching will take priority.

So let's now go to code and see how this id table is implemented.

So let's go first to the pcd_device_setup.c file.

In this file, we will specify different names for each of the devices.

Let's imagine that we have 4 devices. The devices are pcdevA1, pcdevA2, pcdevA3, and pcdevA4.

These would be represented as such in the file.

So the names that you see in each of the devices represents the id values for each of the devices.

So now we go to the pcdev_platform_driver.c file.

To use the id table matching, you must include the <linux/mod_devicetable.h> header file.

Next, we create an enum structure simply to represent the devices better. enum without initialization starts at an index of 0. So, in this case, device 1, PCDEVA1, has an index of 0. Device 2, PCDEVA2, has an index of 1. Device 3, PCDEVA3, has an index of 2. Device 4, PCDEV4, has an index of 3.

Next, we create a structure named device_driver_data

This structure can have as many variables as you would like that are necessary for your particular device.

In this case, 2 integer values are included in this structure, but this can be adapted to suit your device's needs.

Next we create anstance of the device_driver_data, specifying our values for each of the devices.

Remember that PCDEVA1 simply represents 0

PCDEVA2 represents 1, PCDEVA3 represents 2, and PCDEVA4 represents 3.

So PCDEVA1 will have a property1 value of 20 and a property2 value of 80.

So PCDEVA2 will have a property1 value of 21 and a property2 value of 81.

So PCDEVA3 have a property1 value of 22 and a property2 value of 82.

So PCDEVA4 will have a property1 value of 23 and a property2 value of 83.

Lastly, we have the struct of type platform_device_id, named pcdevs_ids[], which contains the id names and the driver data for each of the devices.

This structure then placed into the structure of type platform_driver, which is named, pcd_platform_driver

Let's take a look at this last structure, which is shown below.

Look at how in this structure we have an .id_table property and we have a name property.

As shown before, the id table property has priority over the name property. Thus, the matching will be done based off the id table value and not the name value in this case. In fact, with this setup, specifying the name of the driver is not even needed, since the id table property takes precedent over it. However, you can still have both in your code without any errors being caused.

Lastly, in our code we want to print out the driver data of the devices.

We do this through the following lines of code.

We place this within the probe function.

We know that the data for the driver data is within the pcdev_driver_data structure.

However, how do we access the data in this structure beginning with the pdev platform device, which is the input parameter for the probe function.

We begin with this because that's the only way we know which platform device we are dealing with.

pdev represents the platform device.

The structure for the platform device is shown below.

platform_device structure in linux

You can see that there is a field, *id_entry.

This *id_entry is of a structure of type platform_device_id, which we showed earlier above.

This structure has the field, driver_data, which brings us to the driver data, which is what the pcdev_driver_data structure represents. We now just need to specify the field we want within this data, either property1 or property2.

So now save this code and then build it.

If there are no errors, then insert the 2 modules into the linux kernel through the following lines of code.

So after you run dmesg, you should get an output similar to that shown below.

Output of platform driver with id table matching in linux

So you can see that all of the platform devices, along with the driver data for each one.

If we look in the dev directory, we see all the different devices that we just created.

Platform devices with id table matching in the dev directory in linux

And this is how to create a platform device driver that matches to a corresponding platform device based on the id table value of the device or devices.

Related Resources

HTML Comment Box is loading comments...