Platform Driver Support - cu-ecen-aeld/buildroot-assignments-base GitHub Wiki
Overview
This is an overview of platform device drivers.
Note: The code snippets provided are from the project Password Authentication using Custom UART driver, where a custom UART driver was developed and tested.
What are Platform Drivers?
A platform device is one that is hardwired on the board and hence not hot-pluggable. The driver for this device need not check for the presence of the device and can just go on and do what is required to enable the device to make it operational. If the device is not found, the driver is simply ignored.
Platform drivers are dedicated to such devices that are not based on conventional buses. For example, I2C devices or SPI devices are platform devices, but respectively rely on I2C or SPI buses not on the platform bus. Everything needs to be done manually with the platform driver. The platform driver must implement a probe
function, called by the kernel when the module is inserted or when a device claims it.
Developing Platform Drivers
When developing platform drivers, the main structure you have to fill is struct platform_driver
as can be seen below. This structure represents a device on the platform.
static struct platform_driver hw_plat_driver = {
.driver = {
.name = "serial",
.owner = THIS_MODULE,
.of_match_table = hw_match_table},
.probe = hw_probe,
.remove = hw_remove
};
The of_match_table
member of the driver structure is of significance here. The compatible
member of the hw_match_table
(below) holds the string which is searched for by the kernel. At load time, the kernel calls the probe routine if it finds a match between the compatible
field in the device tree (dtsi
file) and an entry in the of_match_table
provided by a given driver. Instructions on how to modify the dtsi
file are described in the 'Applying the Hardware Patch' section below.
static struct of_device_id hw_match_table[] =
{
{
.compatible = "serial",
},
};
If there are multiple devices that match this driver, the probe routine will be called once for each. The probe routine contains the bulk of the configuration that defines the driver's functionality.
Understanding the Probe Function
The probe function is called by the kernel for every matched device. It performs the housekeeping for initializing a device; allocate a structure for a suitable framework, allocate memory, map I/O memory, register interrupts, etc
We have added debug prints to our driver source code to trace the flow of data in the driver
Device Registration
For regular character drivers, the device driver is introduced in the system by loading the kernel object using insmod
or modprobe
and only then registering the device (registering the device includes allocating it a region, assigning it major and minor numbers, etc ).
However, in the case of platform device drivers, the device registration is handled by module_platform_driver()
function. The platform device gets registered as a misc device by default. Thus, simply running insmod
or modprobe
will complete the registration of the device.
Applying the Hardware Patch
This is an example of applying the UART patch for platform device drivers to modify the dtsi
file.
The original patch for the UART driver can be found here
Our modified patch file can be found here
The original patch file is meant to work for the default UART driver present in the Beaglebone Black. To make it work for our custom device driver we need to add the compatible
member to the dtsi file. The kernel calls the probe
routine if it finds a match between the compatible
field in the device tree and an entry in the of_match_table
provided by a given driver.
Here is a generic explanation of the code in the UART patch
compatible = "serial"
->> This is used to identify a compatible device driver which gets matched here in the driver code
pinctrl-names = "default"
->> This is the name that corresponds to the pin control mode
pinctrl-0 = <&uart1_pins>
->> This binds the UART1 device to the pin control mode defined above
status = "okay"
->> Setting status to “okay” will enable the device
Along with this addition, we have also modified the numbers in the file to adjust the changes we have made. This was possible since there were only minor changes in the file. However, to generate an entire patch file from scratch please use the git diff utility.
References
- Linux Device Drivers Development by John Madieu
- Reference blog