[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