[PATCH v4 1/4] dm: core: Bind another driver with the same compatible string

Michal Simek monstr at monstr.eu
Wed Mar 30 14:49:55 CEST 2022


ne 24. 10. 2021 v 22:01 odesílatel Simon Glass <sjg at chromium.org> napsal:
>
> Hi Michal,
>
> On Fri, 15 Oct 2021 at 07:17, Michal Simek <michal.simek at xilinx.com> wrote:
> >
> > When one IP can have multiple configurations (like timer and PWM) covered
> > by multiple drivers. Because it is the same IP it should also have the same
> > compatible string.
> > Current code look for the first driver which matches compatible string and
> > call bind function. If this is not the right driver which is express by
> > returning -ENODEV ("Driver XYZ refuses to bind") there is no reason not to
> > continue over compatible list to try to find out different driver with the
> > same compatible string which match it.
> >
> > When the first compatible string is found core looks for driver bind()
> > function. If if assigned driver refuse to bind, core continue in a loop to
> > check if there is another driver which match compatible string.
> >
> > This driver is going to be used with cdnc,ttc driver which has driver as
> > timer and also can be used as PWM. The difference is done via #pwm-cells
> > property in DT.
> >
> > Signed-off-by: Michal Simek <michal.simek at xilinx.com>
> > ---
> >
> > Changes in v4:
> > - Remove goto from code
> > - Also continue on prereloc case
> >
> > Changes in v3:
> > - New patch in series
> >
> > When this is acked I will spent my time on writing test for it.
> >
> > ---
> >  drivers/core/lists.c | 84 +++++++++++++++++++++++++++-----------------
> >  1 file changed, 52 insertions(+), 32 deletions(-)
> >
> > diff --git a/drivers/core/lists.c b/drivers/core/lists.c
> > index 5d4f2ea0e3ad..8b655db68edb 100644
> > --- a/drivers/core/lists.c
> > +++ b/drivers/core/lists.c
> > @@ -221,45 +221,65 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp,
> >                 compat = compat_list + i;
> >                 log_debug("   - attempt to match compatible string '%s'\n",
> >                           compat);
> > -
> > -               for (entry = driver; entry != driver + n_ents; entry++) {
> > -                       ret = driver_check_compatible(entry->of_match, &id,
> > -                                                     compat);
> > -                       if ((drv) && (drv == entry))
> > -                               break;
> > -                       if (!ret)
> > +               entry = driver;
> > +
> > +               while (1) {
> > +                       for (; entry != driver + n_ents; entry++) {
> > +                               ret = driver_check_compatible(entry->of_match,
> > +                                                             &id, compat);
> > +                               if (drv && drv == entry)
> > +                                       break;
> > +                               if (!ret)
> > +                                       break;
> > +                       }
> > +                       /*
> > +                        * Reach the last entry - time to look at next
> > +                        * compatible string.
> > +                        */
> > +                       if (entry == driver + n_ents)
> >                                 break;
> > -               }
> > -               if (entry == driver + n_ents)
> > -                       continue;
> > -
> > -               if (pre_reloc_only) {
> > -                       if (!ofnode_pre_reloc(node) &&
> > -                           !(entry->flags & DM_FLAG_PRE_RELOC)) {
> > -                               log_debug("Skipping device pre-relocation\n");
> > -                               return 0;
> > +
> > +                       if (pre_reloc_only) {
> > +                               if (!ofnode_pre_reloc(node) &&
> > +                                   !(entry->flags & DM_FLAG_PRE_RELOC)) {
> > +                                       log_debug("Skipping device pre-relocation\n");
> > +                                       entry++;
> > +                                       continue;
> > +                               }
> >                         }
> > -               }
> >
> > -               log_debug("   - found match at '%s': '%s' matches '%s'\n",
> > -                         entry->name, entry->of_match->compatible,
> > -                         id->compatible);
> > -               ret = device_bind_with_driver_data(parent, entry, name,
> > -                                                  id->data, node, &dev);
> > -               if (ret == -ENODEV) {
> > -                       log_debug("Driver '%s' refuses to bind\n", entry->name);
> > -                       continue;
> > -               }
> > -               if (ret) {
> > -                       dm_warn("Error binding driver '%s': %d\n", entry->name,
> > -                               ret);
> > -                       return log_msg_ret("bind", ret);
> > -               } else {
> > +                       log_debug("   - found match at '%s': '%s' matches '%s'\n",
> > +                                 entry->name, entry->of_match->compatible,
> > +                                 id->compatible);
> > +                       ret = device_bind_with_driver_data(parent, entry, name,
> > +                                                          id->data, node,
> > +                                                          &dev);
> > +                       /*
> > +                        * Driver found but didn't bind properly try another one
> > +                        */
> > +                       if (ret == -ENODEV) {
> > +                               log_debug("Driver '%s' refuses to bind\n",
> > +                                         entry->name);
> > +                               entry++;
> > +                               continue;
> > +                       }
> > +
> > +                       /* Error in binding driver */
> > +                       if (ret) {
> > +                               dm_warn("Error binding driver '%s': %d\n",
> > +                                       entry->name, ret);
> > +                               return log_msg_ret("bind", ret);
> > +                       }
> > +
> > +                       /* Properly binded driver */
>
> bound
>
> >                         found = true;
> >                         if (devp)
> >                                 *devp = dev;
> > +                       break;
> >                 }
> > -               break;
> > +
> > +               if (found)
> > +                       break;
> >         }
> >
> >         if (!found && !result && ret != -ENODEV)
> > --
> > 2.33.1
> >
>
> The impl looks OK to me. I still feel a separate function would help
> readability...we don't need to worry about the parameters in general,
> since the compiler will inline the code and LTO is even more
> agressive.
>
> But I'm OK with this as it is if you prefer it, as it isn't too horrendous.
>
> Should we put this behind a Kconfig given the run-time penalty?
>
> Also, please add a test.

I will take a look at adding a test. But in standard configuration PMW
and TTC timers are not enabled both that's why the patch can come
later.

Thanks,
Michal



-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs


More information about the U-Boot mailing list