Hi Alex, On 17 January 2018 at 16:33, Alexander Graf <[email protected]> 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 <[email protected]> > --- > 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 <[email protected]> > + * > + * 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 _______________________________________________ U-Boot mailing list [email protected] https://lists.denx.de/listinfo/u-boot

