[U-Boot] Best way to use UCLASS_GPIO board id

Michael Nazzareno Trimarchi michael at amarulasolutions.com
Mon Nov 18 21:11:22 UTC 2019


Hi

draft very quick from another one, draft below

On Mon, Nov 18, 2019 at 5:39 PM Simon Glass <sjg at chromium.org> wrote:
>
> Hi Michael,
>
> On Sun, 10 Nov 2019 at 02:08, Michael Nazzareno Trimarchi
> <michael at amarulasolutions.com> wrote:
> >
> > Hi Simon
> >
> > +       project_id: project-id {
> > +               pid0: bid0 {
> > +                       rockchip,pins = <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>;
> > +               };
> > +
> > +               pid1: pid1 {
> > +                       rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;
> > +               };
> > +
> > +               pid2: pid2 {
> > +                       rockchip,pins = <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
> > +               };
> > +       };
> > +
> > +       pcb_id: pcb-id {
> > +               pcbid0: pcbid0 {
> > +                       rockchip,pins = <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
> > +               };
> > +
> > +               pcbid1: pcbid1 {
> > +                       rockchip,pins = <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
> > +               };
> > +
> > +               pcbid2: pcbid2 {
> > +                       rockchip,pins = <2 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
> > +               };
> > +       };
> >
> >
> > I have defined the pins needed for tinker board and understand what
> > board revision is. Now I would like to use them from spl_board_init
> > and I have
> > them in dtb
> >
> > +&pcbid0 {
> > +       u-boot,dm-spl;
> > +};
> > +
> > +&pcbid1 {
> > +       u-boot,dm-spl;
> > +};
> > +
> > +&pcbid2 {
> > +       u-boot,dm-spl;
> > +};
> > +
> > +&pid1 {
> > +       u-boot,dm-spl;
> > +};
> > +
> > +&pid2 {
> > +       u-boot,dm-spl;
> > +};
> > +
> > +&pid0 {
> > +       u-boot,dm-spl;
> > +};
> > +
> > +&pid1 {
> > +       u-boot,dm-spl;
> > +};
> > +
> > +&pid2 {
> > +       u-boot,dm-spl;
> > +};
> >
> > Now is there a way to reference them easily after probe the UCLASS_GPIO?
> >
> > +int spl_board_init(void)
> > +{
> > +       int ret;
> > +       struct udevice *gpio_dev2 = NULL;
> > +       struct udevice *gpio_dev6 = NULL;
> > +
> > +       if (uclass_get_device_by_name(UCLASS_GPIO, "gpio2 at ff790000",
> > &gpio_dev2) ||
> > +           uclass_get_device_by_name(UCLASS_GPIO, "gpio6 at ff7d0000",
> > &gpio_dev6)) {
> > +               printf("Could not get GPIO device.\n");
> > +               return -EINVAL;
> > +       }
> > +
> > +       ret = device_probe(gpio_dev2);
> > +       if (ret)
> > +               pr_err("%s - probe failed: %d\n", gpio_dev2->name, ret);
> > +
> > +       ret = device_probe(gpio_dev6);
> > +       if (ret)
> > +               pr_err("%s - probe failed: %d\n", gpio_dev6->name, ret);
> >
> >
> > Michael
>
> This seems pretty painful and doesn't really use pinctrl to best advantage.
>
> My suggestion would be to create a driver in UCLASS_BOARD and put the
> GPIOs into property, like:
>
> your-board {
>    compatible = "...";
>    board-id-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH
>        &gpio2 3 GPIO_ACTIVE_HIGH
>       ...>;
>    pinctrl=0 = <&board_id>;
>
> Then you can use gpio_request_list_by_name() to get the GPIOs and
> dm_gpio_get_values_as_int() to convert them to an int.
>
> For pinctrl, put it all in one node in pinctrl, like the others, e.g.
> ids {
>    board_id: board-id {
>        rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up
>            2 3 RK_FUNC_GPIO &pcfg_pull_up
>              ...>;
>     };
> };
>

/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * (C) Copyright 2019
 * Michael Trimarchi, Amarula Solutions Sro , michael at amarulasolutions.com
 *
 */
#include <common.h>
#include <dm.h>
#include <board.h>
#include <asm/gpio.h>

#include "tinker.h"

/**
 * struct board_tinker_priv - Private data structure for the tinker board
 *                 driver.
 * @pcbid_gpios:    GPIOs for the board's hardware variant GPIOs
 * @projectid_gpios:    GPIOs for the board's hardware version GPIOs
 * @board_id:        Container for the board's hardware variant
 * @hwversion:        Container for the board's hardware version
 */
struct board_tinker_priv {
    struct gpio_desc ver_gpios[3];
    struct gpio_desc board_gpios[3];
    int board_id;
    int hwversion;
};

/**
 * _read_hwversion() - Read the hardware version from the board.
 * @dev: The board device for which to read the hardware version.
 *
 * The hardware version read from the board (from hard-wired GPIOs) is stored
 * in the private data structure of the driver to be used by other driver
 * methods.
 *
 * Return: 0 if OK, -ve on error.
 */
static int _read_hwversion(struct udevice *dev)
{
    struct board_tinker_priv *priv = dev_get_priv(dev);
    int res;

    res = gpio_request_list_by_name(dev, "ver-gpios", priv->ver_gpios,
                    ARRAY_SIZE(priv->ver_gpios),
                    GPIOD_IS_IN);
    if (res < 0) {
        debug("%s: Error getting GPIO list 'ver-gpios' (err = %d)\n",
              dev->name, res);
        return -ENODEV;
    }

    res = dm_gpio_get_values_as_int(priv->ver_gpios,
                    ARRAY_SIZE(priv->ver_gpios));
    if (res < 0) {
        debug("%s: Error reading HW version from expander (err = %d)\n",
              dev->name, res);
        return res;
    }

    priv->hwversion = res;

    res = gpio_request_list_by_name(dev, "board-gpios", priv->board_gpios,
                    ARRAY_SIZE(priv->board_gpios),
                    GPIOD_IS_IN);
    if (res < 0) {
        debug("%s: Error getting GPIO list 'ver-gpios' (err = %d)\n",
              dev->name, res);
        return -ENODEV;
    }

    res = dm_gpio_get_values_as_int(priv->board_gpios,
                    ARRAY_SIZE(priv->board_gpios));
    if (res < 0) {
        debug("%s: Error reading HW version from expander (err = %d)\n",
              dev->name, res);
        return res;
    }

    priv->board_id = res;

    res = gpio_free_list(dev, priv->board_gpios, ARRAY_SIZE(priv->board_gpios));
    if (res < 0) {
        debug("%s: Error freeing HW version GPIO list (err = %d)\n",
              dev->name, res);
        return res;
    }

    return 0;
}

static int board_tinker_detect(struct udevice *dev)
{
    int res;

    res = _read_hwversion(dev);
    if (res) {
        debug("%s: Error reading hardware version (err = %d)\n",
              dev->name, res);
        return res;
    }

    return 0;
}

static int board_tinker_get_int(struct udevice *dev, int id, int *val)
{
    struct board_tinker_priv *priv = dev_get_priv(dev);

    switch (id) {
    case BOARD_HWVERSION:
        *val = priv->hwversion;
        break;
    case BOARD_VARIANT:
        *val = priv->board_id;
        break;
    default:
        debug("%s: Integer value %d unknown\n", dev->name, id);
        return -EINVAL;
    }

    return 0;
}

static const struct udevice_id board_tinker_ids[] = {
    { .compatible = "asus,board_tinker" },
    { /* sentinel */ }
};

static const struct board_ops board_tinker_ops = {
    .detect = board_tinker_detect,
    .get_int = board_tinker_get_int,
};

static int board_tinker_probe(struct udevice *dev)
{
    return 0;
}

U_BOOT_DRIVER(board_tinker) = {
    .name           = "board_tinker",
    .id             = UCLASS_BOARD,
    .of_match       = board_tinker_ids,
    .ops        = &board_tinker_ops,
    .priv_auto_alloc_size = sizeof(struct board_tinker_priv),
    .probe          = board_tinker_probe,
};

> Good luck!
>
> Regards,
> Simon



-- 
| Michael Nazzareno Trimarchi                     Amarula Solutions BV |
| COO  -  Founder                                      Cruquiuskade 47 |
| +31(0)851119172                                 Amsterdam 1018 AM NL |
|                  [`as] http://www.amarulasolutions.com               |


More information about the U-Boot mailing list