The whole story starts from non discover-able devices in the system. This post will provide you information about non discoverable devices as well it will provide you one of way of Linux kernel to deal with it. The second and fresh way is device tree.
Kernel starts, it has to initialize the drivers for the devices on the board. But often on embedded systems, devices can’t be discover at running time(i2c, spi, etc.). In this case, the Linux kernel has a c (board file) file that initialize these devices for the board. The below image shows structure for non discoverable devices and platform data for same. This will be registered with the virtual bus named platform bus and driver will also register it self with platform bus with the same name.
In this method, kernel must be modified/compiled for each board or change in hardware on board. Kernels are typically built around a single board file and cannot boot on any other type of system. Solution of this situation is provided by “Device tree”. A device tree is a tree data structure with nodes that describe the physical devices on the board. While using device tree, kernel no longer contains the description of the hardware, it is located in a separate binary blob called the device tree blob. The device tree is passed to the kernel at boot time. Kernel reads through it to learn about what kind of system it is. So on the change of board only developer needs to change device tree blob and that it new port of kernel is ready.
Here, you will get a good article on device tree format. It is recommended to go through it first at this stage.
Platform devices can work with dtb enabled system with out any extra modification. If the device tree includes a platform device that device will be instantiated and matched against a driver. All resource data will be available to the driver probe() in a usual way. The driver dose now know wither this device is not initialized with hard-cored. in board file.
Every device in the system is represented by a device tree node. The next step is to populate the tree with a node for each of the devices. The snippet below shows the dtb with node name “ps7-xadc”. Every node in the tree represents a device, which must have a compatible property. compatible i
s the key using which an operating system uses to decide which device driver to bind to a device. In short compatible(ps7-xadc-1.00-a) specifies the name of the platform device which will get registered with bus.
On other side, in device driver when platform deriver structure is declared, it stores a pointer to “of_device_id”. This is shown by the below snippet. This name should be same which was given in the dtb file. Now, when driver with name of “ps7-xadc-1.00.a” will get register with the platform bus, probe of that driver will get called.
The below snippet shows the probe function of the driver. In the probe, function platform_get_resource() provides property described by “reg” in dtb file. In our case base address of register set(0xf8007100) for hardware module and offset from the base address(0x20) can be retrieved. Using which driver can request the memory region form the kernel. As same, function platform_get_irq() provides the property which id describe by “interrupts” in dtb file.
After garbing all details from dtb file, probe will register device as a normal way. This is very straight forward procedure using which platform drivers work with device trees. As a result of this, no need to declare platform_device in board file.