Reading GPIOs with DM_GPIO before device tree is loaded

Simon Glass sjg at chromium.org
Fri Jul 22 10:59:56 CEST 2022


Hi Hugo,

On Thu, 21 Jul 2022 at 11:14, Hugo Villeneuve <hugo at hugovil.com> wrote:
>
> On Wed, 20 Jul 2022 09:01:01 -0600
> Simon Glass <sjg at chromium.org> wrote:
>
> > Hi Hugo,
> >
> > On Wed, 20 Jul 2022 at 04:54, Hugo Villeneuve <hugo at hugovil.com> wrote:
> > >
> > > Hi,
> > > in board_early_init_f(), i call a custom function get_som_revision() to read some GPIOs that are used to determine the SOM revision. This function basically sets the iomux, and then uses gpio_request/gpio_direction_input/gpio_get_value functions to read the GPIOs. Then, this SOM revision information is used in  board_fit_config_name_match() to decide which device tree to load.
> > >
> > > This works perfectly fine without CONFIG_DM_GPIO. However, if I enable CONFIG_DM_GPIO, it doesn't work anymore. There is an error when calling gpio_request().
> > >
> > > What is the correct way to read GPIOs BEFORE any device tree is loaded?
> > >
> > > My board uses an MX6Q SOM.
> > >
> > > Here is part of the code I am using:
> > >
> > > ========================================
> > > static iomux_v3_cfg_t const boardcfg_pads[] = {
> > >         MX6_PAD_DISP0_DAT15__GPIO5_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL),
> > >         MX6_PAD_DISP0_DAT8__GPIO4_IO29  | MUX_PAD_CTRL(NO_PAD_CTRL),
> > >         MX6_PAD_DISP0_DAT0__GPIO4_IO21  | MUX_PAD_CTRL(NO_PAD_CTRL),
> > >         MX6_PAD_ENET_RXD0__GPIO1_IO27   | MUX_PAD_CTRL(NO_PAD_CTRL),
> > >         MX6_PAD_ENET_RXD1__GPIO1_IO26   | MUX_PAD_CTRL(NO_PAD_CTRL),
> > > };
> > >
> > > static int som_revision = -1;
> > >
> > > static const int boardcfg_gpio[] = {
> > >         IMX_GPIO_NR(5, 9),
> > >         IMX_GPIO_NR(4, 29),
> > >         IMX_GPIO_NR(4, 21),
> > >         IMX_GPIO_NR(1, 27),
> > >         IMX_GPIO_NR(1, 26),
> > > };
> > >
> > > static void get_som_revision(void)
> > > {
> > >         int i;
> > >         int rc;
> > >
> > >         som_revision = 0;
> > >
> > >         SETUP_IOMUX_PADS(boardcfg_pads);
> > >
> > >         for (i = 0; i < ARRAY_SIZE(boardcfg_gpio); ++i) {
> > >                 int v;
> > >
> > >                 rc = gpio_request(boardcfg_gpio[i], "som-revision-gpio");
> > >                 if (rc) {
> > >                         printf("%s(): gpio request %d failed\n", __func__, i);
> > >                         som_revision = -1;
> > >                         return;
> > >                 }
> > >
> > >                 gpio_direction_input(boardcfg_gpio[i]);
> > >                 v = gpio_get_value(boardcfg_gpio[i]);
> > >
> > >                 if ((v == 0) || (v == 1))
> > >                         som_revision |= v << i;
> > >                 else {
> > >                         som_revision = -1;
> > >                         return;
> > >                 }
> > >         }
> > > }
> > >
> > > int board_early_init_f(void)
> > > {
> > >         setup_iomux_uart();
> > >         get_som_revision();
> > >
> > >         return 0;
> > > }
> > >
> > > ========================================
> >
> > Well driver model needs the device tree to init, for example DM_GPIO
> > cannot operate without one unless you are hacking around with
> > platdata, which is a bit of a pain.
> >
> > One option you might have is to use a general DT before relocation,
> > then figure out which one you really want to use and select that for
> > post relocation. That works better with driver model.
> >
> > Regards,
> > Simon
>
> Hi Simon,
> I finally fixed the problem by hacking the mxc_gpio driver and simply enabling the DM_FLAG_PRE_RELOC flag with this simple patch:
>
> diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
> index 3cc0e7f353..be2bc6d655 100644
> --- a/drivers/gpio/mxc_gpio.c
> +++ b/drivers/gpio/mxc_gpio.c
> @@ -396,6 +396,7 @@ U_BOOT_DRIVER(gpio_mxc) = {
>         .priv_auto      = sizeof(struct mxc_bank_info),
>         .of_match = mxc_gpio_ids,
>         .bind   = mxc_gpio_bind,
> +       .flags  = DM_FLAG_PRE_RELOC,
>  };
>
>  DM_DRIVER_ALIAS(gpio_mxc, fsl_imx6q_gpio)
>
> No other changes were required.
>
> However, this is probably not a solution that would get accepted into mainline U-Boot, or not?

Seems fine to me. You can also put a u-boot,dm-... tag in the device
tree for that device, just for your board, if you don't want to affect
all boards.

See also dm_gpio_get_values_as_int() and I suspect I don't quite
understand what phase of U-Boot is selecting the DT. Is it SPL or
pre-reloc U-Boot?

Regards,
Simon


More information about the U-Boot mailing list