Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 Aug 2014 16:41:24 -0300
From:      =?UTF-8?Q?Mat=C3=ADas_Perret_Cantoni?= <perretcantonim@gmail.com>
To:        freebsd-arm@freebsd.org
Subject:   Two questions on Flattened Device Tree, newbus and device driver attaching
Message-ID:  <CADLKG03f2KAEeTGCZTh=_ABufDfiWo6pSXW407aCcByon2BinA@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
Hello everyone!
I'm working with FreeBSD on the Zedboard (ported by Thomas Skibo
<http://www.thomasskibo.com/zedbsd/>). Currently I'm trying to fully
understand how the Flattened Device Tree (FDT) mechanism works and how it
integrates with FreeBSD. What I've already understand (I think) is:

    (1) how to represent devices, memory mapping/ranges, interrupts, etc...
in a Device Tree Source (DTS) file,
    (2) how  the newbus framework works, and
    (3) how the kernel manages resources, devices and drivers.

Although I've read all the documents I could find (and some source code)
there are still two things I don't understand:

*1) The DTS source file and CPUs definition:*

 The DTS file for the zedboard, /release/10.0.0/sys/boot/fdt/dts/zedboard.d=
ts
(here
<https://svnweb.freebsd.org/base/release/10.0.0/sys/boot/fdt/dts/zedboard.d=
ts?revision=3D260789&view=3Dmarkup>),
has the CPU definition all commented out:

   ...
   // cpus {
   //      #address-cells =3D <1>;
   //      #size-cells =3D <0>;
   //      cpu@0 {
   //              device-type =3D "cpu";
   //              model =3D "ARM Cortex-A9";
   //      };
   // };
   ...

This sounds really strange to me! How can the system tell the CPU it's
running on? I'v found some other DTS files for other boards that *do
define* it's
CPUs. For example:

imx53x.dtsi: (here
<https://svnweb.freebsd.org/base/release/10.0.0/sys/boot/fdt/dts/imx53x.dts=
i?view=3Dmarkup>
)

    ...
    cpus {
            #address-cells =3D <1>;
            #size-cells =3D <0>;

            cpu@0 {
                    device_type =3D "cpu";
                    compatible =3D "ARM,MCIMX535";
                   reg =3D <0x0>;
                   d-cache-line-size =3D <32>;
                   i-cache-line-size =3D <32>;
                   d-cache-size =3D <0x8000>;
                    i-cache-size =3D <0x8000>;
                    l2-cache-line-size =3D <32>;
                    l2-cache-line =3D <0x40000>;
                    timebase-frequency =3D <0>;
                    bus-frequency =3D <0>;
                    clock-frequency =3D <0>;
            };
    ...

or:

p1020rdb.dts (here
<https://svnweb.freebsd.org/base/release/10.0.0/sys/boot/fdt/dts/p1020rdb.d=
ts?view=3Dmarkup>
)

   ...
   cpus {
          #address-cells =3D <1>;
           #size-cells =3D <0>;

           PowerPC,P1020@0 {
                   device_type =3D "cpu";
                   reg =3D <0x0>;
                   next-level-cache =3D <&L2>;
           };

           PowerPC,P1020@1 {
                   device_type =3D "cpu";
                   reg =3D <0x1>;
                   next-level-cache =3D <&L2>;
           };
   };
   ...

*So my first question is: How can the system tell on wich CPU it running
on? can I add the CPUs definition in my DTS file?*

2) The 'compatible' property of a node, finding the driver and attaching it
to the corresponding newbus node: During autoconfiguration the the .dtb
(device tree blob) file is parsed and for each node of the device three the
autoconfiguration systen will create a new newbus node (with
device_add_child()) and then it will find a suitable driver for it and will
attach it:

*/
* This function is the core of the device autoconfiguration
* system. Its purpose is to select a suitable driver for a device and
* then call that driver to initialise the hardware appropriately. The
* driver is selected by calling the DEVICE_PROBE() method of a set of
* candidate drivers and then choosing the driver which returned the
* best value. This driver is then attached to the device using
* device_attach().
*
* The set of suitable drivers is taken from the list of drivers in
* the parent device's devclass. If the device was originally created
* with a specific class name (see device_add_child()), only drivers
* with that name are probed, otherwise all drivers in the devclass
* are probed. If no drivers return successful probe values in the
* parent devclass, the search continues in the parent of that
* devclass (see devclass_get_parent()) if any.
*
* @param dev the device to initialise
*/

int device_probe(device_t dev)

(I extracted this from here
<https://svnweb.freebsd.org/base/release/10.0.0/sys/kern/subr_bus.c?revisio=
n=3D260789&view=3Dmarkup>
)

I believe that the autoconfiguration system uses the
fdt_node_check_compatible() function (from fdtlib
<https://svnweb.freebsd.org/base/release/10.0.0/sys/contrib/libfdt/libfdt.h=
?revision=3D260789&view=3Dmarkup>)
to get the "compatible" property out of each node of the .dtb blob and then
it calls device_probe() to find the best driver and attach it to the
corresponding newbus node. (is this correct?).

>From the ePAPR
<https://www.power.org/wp-content/uploads/2012/06/Power_ePAPR_APPROVED_v1.1=
.pdf>
standard
we have this:

2.3.1 compatible
Property: compatible
Value type: <stringlist>

Description: The compatible property value consists of one or more strings
that define the specific
programming model for the device. This list of strings should be used by a
client program for
device driver selection. The property value consists of a concatenated list
of null terminated
strings, from most specific to most general. They allow a device to express
its compatibility
with a family of similar devices, potentially allowing a single device
driver to match against
several devices.
The recommended format is =E2=80=9Cmanufacturer,model=E2=80=9D, where manuf=
acturer is a
string describing the name of the manufacturer (such as a stock ticker
symbol), and model
specifies the model number.

Example:         *compatible=3D=E2=80=9Cfsl,mpc8641-uart=E2=80=9D, =E2=80=
=9Cns16550";*

 In this example, an operating system would first try to locate a device
driver that supported
fsl,mpc8641-uart. If a driver was not found, it would then try to locate a
driver that supported
the more general ns16550 device type.


*What I don't understand is how the system locates a device driver based on
the compatible property. For example the cpu node's compatible property
("ARM,MCIMX535") of the imx53x.dtsi example. More precisely: How can the
system relate the string "ARM,MCIMX535" with the actual device driver in
the file system.*

I hope my questions are clear enough. Many thanks in advance.

Best regards, Mat=C3=ADas.-



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CADLKG03f2KAEeTGCZTh=_ABufDfiWo6pSXW407aCcByon2BinA>