Overview/Reference Manual for Open Firmware Device Trees

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 insmoding 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:

  1. Simple to change the configuration of the system without having to recompile any source code.
  2. 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...)
  3. 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.
  4. They (can) provide easy to read and understand descriptions of the hardware, and can give hardware components descriptive names.

Some of the disadvantages includes:

  1. Not so easy to write a new .dts file, because it requires very detailed knowledge of the hardware.
  2. 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



Leave a reply



Submit