How to Create a Platform Device Driver in Linux

Beaglebone black board






In this article, we show how to create a platform device driver in linux.

A platform device driver is a driver which can handle the detection and configuration of a platform device.

A platform device is a device connected to a platform bus in linux, which means that it does not have autodiscoverability; therefore, we must write adequate code so that our embedded system can discover it and load the driver to know all about its configurations and workings.

So the first thing that should be done is we need to create 2 main files, which we will use to create our platform device driver and our platform devices.

We separate each.

We will create one file named pcd_device_setup.c. This file will hold the created platform devices.

We then will create another file named pcd_platform_driver.c. This file will hold the platform device driver.

Create a directory named platform_drivers anywhere in your home directory or any directory that you want to work from.

The only requirement is that within this directory you will need to have a Makefile, which needs to be able to build each of these 2 files when you are doing a build.

The contents of this Makefile can be found at the following link: Makefile

One another file we will create in addition to the 2 main files is the platform.h header file, which will contain some structure and macro definitions.

The contents of this platform.h file is shown below.





This file really doesn't need much explanation. It simply gives us some structure and macro definitions.

You just have to make sure to include this in the top of the other 2 main files for those files to have these definitions.

The next file that we have is the pcd_device_setup.c file.

This file contains the platform data for each of the platform devices, as well as the platform devices themselves.





So let's now go over this code.

First, we have a pcdev_release() method, which releases the device when the module is removed.

Then, we create the platform data for each device. In this case, we create 4 platform devices, so we need 4 sets of data for these platform devices.

The platform data consists of size, permission, and serial numbers for each of the platform devices.

So we can see that the first platform device has a size of 512, RDWR permissions, and a serial number of PCDEVABC1111

The second platform device has a size of 1024, RDWR permissions, and a serial number of PCDEVXYZ2222

The third platform device has a size of 50, RDONLY permissions, and a serial number of PCDEVXYZ3333

The fourth platform device has a size of 100, WRONLY permissions, and a serial number of PCDEVXYZ4444

Next, we create the platform devices in this file.

We create 4 platform devices.

Each of these devices will have the same name.

This is because we are doing name matching when the probe function is run.

name matching will simply match to the name of the device, in this case, pseudo-char-device

There are more sophisticated ways of matching that will be covered in other articles.

For now, we just create this as the most basic way of matching for probe functions.

Each device will need its own unique id number.

We then specify the platform data set and the release function for each device.

The platform data is all unique for each device and the release functions are all the same in this case.

In our init function, pcdev_platform_init(), we register all of these platform devices.

In our exit function, pcdev_platform_exit(), we unregister all of these platform devices.

This concludes our pcdev_device_setup.c file.

Next, we have our platform driver file, pcd_platform_driver.c

The contents of this file is shown below.





We specify the private data structure, pcdev_private_data, and the driver private data structure, pcdrv_private_data.

We then create an instance of this driver private data structure, which we assign it the name, pcdrv_data

Next, we have the check_permission() function, which checks to see what permissions the file has and what the user is trying to do.

We then have our file operation methods including the lseek, read, write, open, and release methods.

We have our usual file operations of the driver.

Next we have the remove function, pcd_platform_driver_remove

This function takes a variable representing the platform device, *pdev

We create a structure, *dev_data, which is an instance of the pcdev_private_data structure based on the private data of the matched device.

We remove the device through the device_destroy() function, specifying the class and the device numer into this function.

We remove the character device from the system.

We then decrement the number of total devices.

Next, we have our probe function, pcd_platform_driver_probe()

This is the function which is called when there is a matched platform device.

In this function, we create an instance of the pcdev_private_data, *dev_data, and an instance of the pcdev_platform_data, *pdata.

We get the platform data through the dev_get_platdata() API function.

We allocate memory for this device private data through the devm_kzalloc() function.

We then save the device private data pointer in the platform device structure with the dev_set_drvdata() function.

We then dynamically allocate memory for the device buffer using size information from the platform data using the devm_kzalloc() function.

We then get the device number which is made up of the device base number and the id of the device.

We then initialize the cdev structure with the cdev_init() function, passing in the device's cdev structure as the first parameter and the file operation methods as the second parameter.

We then set the owner of the cdev as THIS_MODULE

We also do a good amount of error checking to make sure that each function works.

We then create a device file for the detected platform device using the device_create() function.

We then increment total devices by 1.

Next, we create a structure, pcd_platform_driver, which defines several function, including the probe and remove function, along with defining the name of the driver.

Lastly, we create our init function, pcd_platform_driver_init()

In this function, we dynamically allocate a device number using the alloc_chrdev_region() function

We then create a device class under the /sys/class directory using the class_create() function.

We then register our platform driver.

Then we have our exit function, pcd_platform_driver_cleanup()

This function unregisters the platform driver, destroys the class, and unregisters the device numbers for the devices.

Once this is all done, we build the project through the line, make host

If this runs without any errors, then we are all ready to test our platform device driver.

We insert the platform driver module into the linux kernel through the line shown below.





After running this code and running dmesg, we get the following output shown below.


Inserting the platform driver module into the linux kernel


Next, we insert the pcd_device_setup.ko into the linux kernel through the line shown below.





After running this code and running dmesg, we get the following output shown below.


Inserting the platform device setup module into the linux kernel


You can see that all 4 platform devices are shown here; they have all been detected due to name matching.

If we go to the /dev directory which is present in the root directory in linux, we should see all of the platform devices.

This is shown below.


Output of platform driver with name based matching in linux


Now, let's remove the module, starting with the pcd_device_setup.ko

We remove the pcd_device_setup.ko from the linux kernel through the line shown below.





After running this code and running dmesg, we get the following output shown below.


Removing the platform device setup module from the linux kernel


You can see that all devices have been removed.

Next we remove the platform driver module from the linux kernel through the line shown below.





After running this code and running dmesg, we get the following output shown below.


Removing the platform driver module from the linux kernel


You can see that the platform driver has been unloaded.

Next, the last thing would be to test the file operation methods, including the read and write file operation methods.

And this is how to create a platform device driver in linux.



Related Resources





HTML Comment Box is loading comments...