Device tree and driver probing
Answering my own question (from information in this document): this was a misunderstanding on my part. It is actually a choice, and the usage of the second device type specified under compatible
from within the code was an implementation detail of the driver in question.
Device Tree and manual registration
Dynamically modifying the loaded device tree is not something we usually do, although it's possible.
I understand you don't really care about the device tree for this new device.
I suggest you create a new module to add your device and, once it's loaded (after insmod
ing it), insmod
your driver module. In fact, the order doesn't matter. When you add a device, all drivers will be checked and the ones that match will be probed, and when you add a driver, all devices are checked against it.
To create the device, you first allocate it:
struct platform_device *pdev;
int inst_id = 1; /* instance unique ID: base address would be a good choice */
pdev = platform_device_alloc("unique_name_here", inst_id);
Then, you will want to create resources, at least one for the memory mapped range. For this, create and fill an array of struct resource
. A struct resource
is pretty simple. Here's an example on how to fill a memory resource:
struct resource res = {
.start = 0x50000000,
.end = 0x50001fff,
.name = "some_name",
.flags = IORESOURCE_MEM,
};
Once you have that, add it to the platform device you're building:
platform_device_add_resources(pdev, &res, 1);
Make sure res
is not on the stack, though (make it global, or kzalloc
it and kfree
when unloading the module).
You're now ready to add the platform device:
platform_device_add(pdev);
Device tree aside, platform devices are matched to platform drivers by the "platform bus" (not a real actual physical bus) by name. So your platform driver will need to provide an equivalent name (unique_name_here
hereabove). Your platform driver will have something like:
static struct platform_driver my_platform_driver = {
.probe = my_probe,
.remove = my_remove,
.driver = {
.name = "unique_name_here",
.owner = THIS_MODULE,
},
};
module_platform_driver(my_platform_driver);
and voilà. Your driver should be probed if a platform device with the same name was added.
Drivers using the device tree add another member to .driver
, which is .of_match_table
. A match table (array of strings) is given there. The match is then using the compatible
property of device tree nodes.
How to compile dts Linux device tree source files to dtb?
Device trees do not need to be compiled with "architecture-aware" tools. The dtc compiler on your ubuntu machine is probably current enough to compile your device tree. Or you can download the latest source and compile it yourself. The dtc compiler can be found here:
https://git.kernel.org/pub/scm/utils/dtc/dtc.git
There are some good documents in that package that will help you better understand device trees in general.
It's pretty easy to compile (and disassemble) device trees. For example
$ dtc -O dtb -o p4080ds.dtb p4080ds.dts
To get the device tree in text from from the device tree blob, do this:
$ dtc -I dtb -O dts p4080ds.dtb
Hope this helps!
What is Device Tree?Advantages & Disadvantages?
The device tree is a description of hardware components in a system, here is the list of device tree files in linux for the arm arch:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts?id=refs/tags/v3.10
From here:
http://devicetree.org/Device_Tree_Usage
The device tree is a simple tree structure of nodes and properties.
Properties are key-value pairs, and node may contain both properties
and child nodes
The nodes of the tree describe parameters that the linux kernel, or other software systems like u-boot, uses to init hardware.
Some of the advantages include:
- Simple to change the configuration of the system without having to recompile any source code.
- Can easily add support for new hardware (for example if you have a new rev of a board which only changes some minor components, you may be able to run the same software load as previous revs of the board, with only small changes to the .dts file on the new board...)
- Can reuse existing .dts files with include statements, and can override previously defined functionality. For example if you include a dtsi (device tree include file) that defines a hardware component, but has it disabled, then you can just create a new node in your higher level dts file that does nothing but enable that component.
- They (can) provide easy to read and understand descriptions of the hardware, and can give hardware components descriptive names.
Some of the disadvantages includes:
- Not so easy to write a new .dts file, because it requires very detailed knowledge of the hardware.
- Even if you know all the details of the hardware it may be hard to figure out the exact syntax to use to express what you want to do... (i.e. the documentation is lacking in many respects)
For me writing a .dts file is almost 100% trial and error, pulling examples from other .dts files and see what it does and if it gets closer to what I want... Often times the examples are all I have to work with, and there isn't much in the way of an explanation of what is going on.
Related Topics
How to Make Library Installed from Opam Available to Ocaml
Laravel-Mix No Build Notification
How Does Iwlist() Command Scans The Wireless Networks
Gnuplot-Like Program for Timeline Data
Sox Batch Process Under Debian
Interpreting Openssl Speed Output for Rsa with Multi Option
Changing /Proc/Sys/Kernel/Core_Pattern File Inside Docker Container
Difference Between "Cpu/Mem-Loads/Pp" and "Cpu/Mem-Loads/"
Downloading a Tarball from Github Without Curl
Deleting All Files Except Ones Mentioned in Config File
Kaggle API Issue "Could Not Find Kaggle.JSON. Make Sure It's Located In......"
How to Customize or Remove Extra Linux Kernel Version Details Shown at Boot
Make for Compiling - All *.C Files in Folders & Subfolders in Project