[U-Boot] Driver Model and DTS Parsing

Simon Glass sjg at chromium.org
Tue Jun 3 03:26:58 CEST 2014


Hi Jon,

On 30 May 2014 08:49, Jon Loeliger <loeliger at gmail.com> wrote:
> Folks,
>
> I'd like to discuss the new Driver Model's parsing of the DTS file
> for the purposes of instancing and binding devices as I was not
> able to get the existing code to work anything like I was expecting.
>
> The current code only finds and binds the top-level nodes of the
> DTS file.  This leads to a bind function one-level above where it
> should be for each of the actual device nodes and an extra "parent"
> node that is empty.  For example, the gpio_exynos_gpio_bind()
> function here:
>
> http://git.denx.de/?p=u-boot/u-boot-x86.git;a=blob;f=drivers/gpio/s5p_gpio.c;h=8100d50ed2da686353c593ed90693c441cf24b4f;hb=refs/heads/us-gpioc
>
> Looks like this:
>
> 386 /**
> 387  * We have a top-level GPIO device with no actual GPIOs. It has a child
> 388  * device for each Exynos GPIO bank.
> 389  */
> 390 static int gpio_exynos_bind(struct device *parent)
> 391 {
> 392         struct exynos_gpio_platdata *plat = parent->platdata;
> 393         struct s5p_gpio_bank *bank;
> 394         const void *blob = gd->fdt_blob;
> 395         int node;
> 396
> 397         /* If this is a child device, there is nothing to do here */
> 398         if (plat)
> 399                 return 0;
> 400
> 401         bank = (struct s5p_gpio_bank *)fdtdec_get_addr(gd->fdt_blob,
> 402
> parent->of_offset, "reg");
> 403         for (node = fdt_first_subnode(blob, parent->of_offset); node > 0;
> 404              node = fdt_next_subnode(blob, node)) {
> 405                 struct exynos_gpio_platdata *plat;
> 406                 struct device *dev;
> 407                 int ret;
> 408
> 409                 plat = calloc(1, sizeof(*plat));
> 410                 if (!plat)
> 411                         return -ENOMEM;
> 412                 plat->bank = bank;
> 413                 plat->port_name = fdt_get_name(blob, node, NULL);
> 414
> 415                 ret = device_bind(parent, parent->driver,
> 416                                         plat->port_name, plat, -1, &dev);
> 417                 if (ret)
> 418                         return ret;
> 419                 dev->of_offset = parent->of_offset;
> 420                 bank++;
> 421         }
> 422
> 423         return 0;
> 424 }
>
> Why is this function being called once at the parent node, which
> then iterates over each device, instantiates and binds it?  Why
> isn't this function instead called once for each individual device
> as matched from the DTS?  Where did the compatible matching
> and check take place in this implementation?

Driver model works by looking up compatible strings in the top-level
nodes and binding a driver for each one it finds.

The exynos pinctrl device tree binding does not have a compatible
string in each of its banks. In fact it just has a single compatible
string at the level above the banks. So there seems to be no
alternative but to iterate through the banks binding devices as we go.

The node looks something like this:

    pinctrl at 13410000 {
        compatible = "samsung,exynos5420-pinctrl";
        reg = <0x13410000 0x0000011f>;
        interrupts = <0x00000000 0x67706330 0x000004a6>;
        gpc0 {
            gpio-controller;
            #gpio-cells = <0x00000002>;
            interrupt-controller;
            #interrupt-cells = <0x00000002>;
        };
        gpc1 {
            gpio-controller;
            #gpio-cells = <0x00000002>;
            interrupt-controller;
            #interrupt-cells = <0x00000002>;
        };

So we get a bind call on the pinctrl node and then bind each of the banks.


>
>
> Instead, I think it should be a recursive structure essentially
> identical in structure to the Linux of_platform_populate() function.
> There should be a compatible matching step, and then the
> call to bind the specific instance.
>
> Am I missing something here?  Or is this code that just needs to
> be developed further still?

Certainly this could be done, and it's a small change but this code
doesn't exist yet. I deliberately left this out of the implementation
until we have I2C implemented, or something similar. Then it will be
clearer what is needed here.

My concern is partly that access to the device may be mediated through
the parent and thus not discoverable by the child. As an example, the
Chrome OS EC driver can attached to I2C, SPI or LPC. The connection
needs to be made at the parent level, which provides a
'communications' layer for the generic driver.

So in short I think we need to address these things and make the
decisions as we go. For the same reason I didn't implement driver
model for SPL or pre-relocation (although I have a series out for the
latter now).

A lot of things will be clearer to me when I2C is ported over.

Regards,
Simon


More information about the U-Boot mailing list