[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