[U-Boot] [PATCH v2 1/2] bcm283x: Add pinctrl driver

Simon Glass sjg at chromium.org
Thu Jan 18 17:26:10 UTC 2018


Hi Alex,

On 17 January 2018 at 16:33, Alexander Graf <agraf at suse.de> wrote:
> The bcm283x family of SoCs have a GPIO controller that also acts as
> pinctrl controller.
>
> This patch introduces a new pinctrl driver that can actually properly mux
> devices into their device tree defined pin states and is now the primary
> owner of the gpio device. The previous GPIO driver gets moved into a
> subdevice of the pinctrl driver, bound to the same OF node.
>
> That way whenever a device asks for pinctrl support, it gets it
> automatically from the pinctrl driver and GPIO support is still available
> in the normal command line phase.
>
> Signed-off-by: Alexander Graf <agraf at suse.de>
> ---
>  MAINTAINERS                                |   1 +
>  arch/arm/mach-bcm283x/include/mach/gpio.h  |   2 -
>  board/raspberrypi/rpi/rpi.c                |   5 +-
>  configs/rpi_0_w_defconfig                  |   4 +
>  configs/rpi_2_defconfig                    |   4 +
>  configs/rpi_3_32b_defconfig                |   4 +
>  configs/rpi_3_defconfig                    |   4 +
>  configs/rpi_defconfig                      |   4 +
>  drivers/gpio/bcm2835_gpio.c                |  29 ++----
>  drivers/pinctrl/Kconfig                    |   1 +
>  drivers/pinctrl/Makefile                   |   1 +
>  drivers/pinctrl/broadcom/Kconfig           |   7 ++
>  drivers/pinctrl/broadcom/Makefile          |   7 ++
>  drivers/pinctrl/broadcom/pinctrl-bcm283x.c | 150 +++++++++++++++++++++++++++++
>  14 files changed, 200 insertions(+), 23 deletions(-)
>  create mode 100644 drivers/pinctrl/broadcom/Kconfig
>  create mode 100644 drivers/pinctrl/broadcom/Makefile
>  create mode 100644 drivers/pinctrl/broadcom/pinctrl-bcm283x.c

That was quick!

[...]

> diff --git a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
> new file mode 100644
> index 0000000000..62c35698f5
> --- /dev/null
> +++ b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
> @@ -0,0 +1,150 @@
> +/*
> + * Copyright (C) 2018 Alexander Graf <agraf at suse.de>
> + *
> + * Based on drivers/pinctrl/mvebu/pinctrl-mvebu.c and
> + *          drivers/gpio/bcm2835_gpio.c
> + *
> + * This driver gets instantiated by the GPIO driver, because both devices
> + * share the same device node.
> + *
> + * SPDX-License-Identifier:    GPL-2.0
> + * https://spdx.org/licenses
> + */
> +
> +#include <common.h>
> +#include <config.h>
> +#include <fdtdec.h>
> +#include <errno.h>
> +#include <dm.h>
> +#include <dm/pinctrl.h>
> +#include <dm/root.h>
> +#include <dm/device-internal.h>
> +#include <dm/lists.h>
> +#include <asm/system.h>
> +#include <asm/io.h>
> +#include <asm/gpio.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct bcm283x_pinctrl_priv {
> +       u32 *base_reg;
> +};
> +
> +#define MAX_PINS_PER_BANK 16
> +
> +static void bcm2835_gpio_set_func_id(struct udevice *dev, unsigned int gpio,
> +                                    int func)
> +{
> +       struct bcm283x_pinctrl_priv *priv = dev_get_priv(dev);
> +       int reg_offset;
> +       int field_offset;
> +
> +       reg_offset = BCM2835_GPIO_FSEL_BANK(gpio);
> +       field_offset = BCM2835_GPIO_FSEL_SHIFT(gpio);
> +
> +       clrsetbits_le32(&priv->base_reg[reg_offset],
> +                       BCM2835_GPIO_FSEL_MASK << field_offset,
> +                       (func & BCM2835_GPIO_FSEL_MASK) << field_offset);
> +}
> +
> +static int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned int gpio)
> +{
> +       struct bcm283x_pinctrl_priv *priv = dev_get_priv(dev);
> +       u32 val;
> +
> +       val = readl(&priv->base_reg[BCM2835_GPIO_FSEL_BANK(gpio)]);
> +
> +       return (val >> BCM2835_GPIO_FSEL_SHIFT(gpio) & BCM2835_GPIO_FSEL_MASK);
> +}
> +
> +/*
> + * bcm283x_pinctrl_set_state: configure pin functions.
> + * @dev: the pinctrl device to be configured.
> + * @config: the state to be configured.
> + * @return: 0 in success
> + */
> +int bcm283x_pinctrl_set_state(struct udevice *dev, struct udevice *config)
> +{
> +       const void *blob = gd->fdt_blob;
> +       int node = dev_of_offset(config);
> +       u32 pin_arr[MAX_PINS_PER_BANK];
> +       u32 function;
> +       int i, pin_count;
> +
> +       pin_count = fdtdec_get_int_array_count(blob, node,
> +                                              "brcm,pins",
> +                                              pin_arr,
> +                                              ARRAY_SIZE(pin_arr));
> +       if (pin_count <= 0) {
> +               debug("Failed reading pins array for pinconfig %s (%d)\n",
> +                     config->name, pin_count);
> +               return -EINVAL;
> +       }
> +
> +       function = fdtdec_get_int(blob, node, "brcm,function", -1);

Please use dev_read_...() interface.

> +       if (function < 0) {
> +               debug("Failed reading function for pinconfig %s (%d)\n",
> +                     config->name, function);
> +               return -EINVAL;
> +       }
> +
> +       for (i = 0; i < pin_count; i++)
> +               bcm2835_gpio_set_func_id(dev, pin_arr[i], function);
> +
> +       return 0;
> +}
> +
> +static int bcm283x_pinctrl_get_gpio_mux(struct udevice *dev, int banknum,
> +                                       int index)
> +{
> +       if (banknum != 0)
> +               return -EINVAL;
> +
> +       return bcm2835_gpio_get_func_id(dev, index);
> +}
> +
> +static const struct udevice_id bcm2835_pinctrl_id[] = {
> +       {.compatible = "brcm,bcm2835-gpio"},
> +       {}
> +};
> +
> +int bcm283x_pinctl_probe(struct udevice *dev)
> +{
> +       struct bcm283x_pinctrl_priv *priv;
> +       int ret;
> +       struct udevice *pdev;
> +
> +       priv = dev_get_priv(dev);
> +       if (!priv) {
> +               debug("%s: Failed to get private\n", __func__);
> +               return -EINVAL;
> +       }
> +
> +       priv->base_reg = devfdt_get_addr_ptr(dev);
> +       if (priv->base_reg == (void *)FDT_ADDR_T_NONE) {
> +               debug("%s: Failed to get base address\n", __func__);
> +               return -EINVAL;
> +       }
> +
> +       /* Create GPIO device as well */
> +       ret = device_bind(dev, lists_driver_lookup_name("gpio_bcm2835"),
> +                         "gpio_bcm2835", NULL, dev_of_offset(dev), &pdev);
> +       if (ret)
> +               printf("Failed to bind GPIO driver\n");

Can you add a comment as to why this is non-fatal?

> +
> +       return 0;
> +}
> +
> +static struct pinctrl_ops bcm283x_pinctrl_ops = {
> +       .set_state      = bcm283x_pinctrl_set_state,
> +       .get_gpio_mux   = bcm283x_pinctrl_get_gpio_mux,
> +};
> +
> +U_BOOT_DRIVER(pinctrl_bcm283x) = {
> +       .name           = "bcm283x_pinctrl",
> +       .id             = UCLASS_PINCTRL,
> +       .of_match       = of_match_ptr(bcm2835_pinctrl_id),
> +       .priv_auto_alloc_size = sizeof(struct bcm283x_pinctrl_priv),
> +       .ops            = &bcm283x_pinctrl_ops,
> +       .probe          = bcm283x_pinctl_probe
> +};
> --
> 2.12.3
>

Regards,
Simon


More information about the U-Boot mailing list