[U-Boot] [PATCH v4 3/5] pinctrl: at91-pio4: Add pinctrl driver

Simon Glass sjg at chromium.org
Fri Jun 10 02:35:19 CEST 2016


Hi Wenyou,

On 7 June 2016 at 01:24, Wenyou Yang <wenyou.yang at atmel.com> wrote:
> AT91 PIO4 controller is a combined gpio-controller, pin-mux and
> pin-config module. The peripheral's pins are assigned through
> per-pin based muxing logic.
>
> The pin configuration is performed on specific registers which
> are shared along with the gpio controller. So regard the pinctrl
> device as a child of atmel_pio4 device.
>
> Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> ---
>
> Changes in v4: None
> Changes in v3:
>  - Rework due to the pinctrl device is regarded as atmel_pio4
>    device's child.
>
> Changes in v2:
>  - remove meaningless comment.
>  - add else path for argument of pinconf.
>  - add inline attribute for atmel_pio4_bank_base().
>  - add handle if the pinmux entries is greater maximum value.
>
>  drivers/pinctrl/Kconfig             |   7 ++
>  drivers/pinctrl/Makefile            |   1 +
>  drivers/pinctrl/pinctrl-at91-pio4.c | 185 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 193 insertions(+)
>  create mode 100644 drivers/pinctrl/pinctrl-at91-pio4.c

Reviewed-by: Simon Glass <sjg at chromium.org>

With one nit below.

>
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index 567b766..68ecfbb 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -123,6 +123,13 @@ config QCA953X_PINCTRL
>           both the GPIO definitions and pin control functions for each
>           available multiplex function.
>
> +config PINCTRL_AT91PIO4
> +       bool "AT91 PIO4 pinctrl driver"
> +       depends on DM
> +       help
> +         This option is to enable the AT91 pinctrl driver for AT91 PIO4
> +         controller which is available on SAMA5D2 SoC.
> +
>  config ROCKCHIP_PINCTRL
>         bool "Rockchip pin control driver"
>         depends on DM
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index b99ed2f..4df10a4 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -5,6 +5,7 @@
>  obj-y                                  += pinctrl-uclass.o
>  obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC)   += pinctrl-generic.o
>
> +obj-$(CONFIG_PINCTRL_AT91PIO4)         += pinctrl-at91-pio4.o
>  obj-y                                  += nxp/
>  obj-$(CONFIG_ARCH_ATH79) += ath79/
>  obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
> diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
> new file mode 100644
> index 0000000..ed63f68
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl-at91-pio4.c
> @@ -0,0 +1,185 @@
> +/*
> + * Atmel PIO4 pinctrl driver
> + *
> + * Copyright (C) 2016 Atmel Corporation
> + *               Wenyou.Yang <wenyou.yang at atmel.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm/device.h>
> +#include <dm/pinctrl.h>
> +#include <linux/io.h>
> +#include <linux/err.h>
> +#include <mach/atmel_pio4.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/*
> + * Warning:
> + * In order to not introduce confusion between Atmel PIO groups and pinctrl
> + * framework groups, Atmel PIO groups will be called banks.
> + */
> +
> +struct atmel_pio4_platdata {
> +       struct atmel_pio4_port *reg_base;
> +};
> +
> +static const struct pinconf_param conf_params[] = {
> +       { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
> +       { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
> +       { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
> +       { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
> +       { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
> +       { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
> +       { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
> +};
> +
> +static u32 atmel_pinctrl_get_pinconf(const void *blob, int node)
> +{
> +       const struct pinconf_param *params;
> +       u32 param, arg, conf = 0;
> +       u32 i;
> +
> +       for (i = 0; i < ARRAY_SIZE(conf_params); i++) {
> +               params = &conf_params[i];
> +               if (!fdt_get_property(blob, node, params->property, NULL))
> +                       continue;
> +
> +               param = params->param;
> +               arg = params->default_value;
> +
> +               switch (param) {
> +               case PIN_CONFIG_BIAS_DISABLE:
> +                       conf &= (~ATMEL_PIO_PUEN_MASK);
> +                       conf &= (~ATMEL_PIO_PDEN_MASK);
> +                       break;
> +               case PIN_CONFIG_BIAS_PULL_UP:
> +                       conf |= ATMEL_PIO_PUEN_MASK;
> +                       break;
> +               case PIN_CONFIG_BIAS_PULL_DOWN:
> +                       conf |= ATMEL_PIO_PDEN_MASK;
> +                       break;
> +               case PIN_CONFIG_DRIVE_OPEN_DRAIN:
> +                       if (arg == 0)
> +                               conf &= (~ATMEL_PIO_OPD_MASK);
> +                       else
> +                               conf |= ATMEL_PIO_OPD_MASK;
> +                       break;
> +               case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> +                       if (arg == 0)
> +                               conf |= ATMEL_PIO_SCHMITT_MASK;
> +                       else
> +                               conf &= (~ATMEL_PIO_SCHMITT_MASK);
> +                       break;
> +               case PIN_CONFIG_INPUT_DEBOUNCE:
> +                       if (arg == 0) {
> +                               conf &= (~ATMEL_PIO_IFEN_MASK);
> +                               conf &= (~ATMEL_PIO_IFSCEN_MASK);
> +                       } else {
> +                               conf |= ATMEL_PIO_IFEN_MASK;
> +                               conf |= ATMEL_PIO_IFSCEN_MASK;
> +                       }
> +                       break;
> +               default:
> +                       printf("%s: Unsupported configuration parameter: %u\n",
> +                              __func__, param);
> +                       break;
> +               }
> +       }
> +
> +       return conf;
> +}
> +
> +static inline struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
> +                                                          u32 bank)
> +{
> +       struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
> +       struct atmel_pio4_port *bank_base =
> +                       (struct atmel_pio4_port *)((u32)plat->reg_base +
> +                       ATMEL_PIO_BANK_OFFSET * bank);
> +
> +       return bank_base;
> +}
> +
> +#define MAX_PINMUX_ENTRIES     40
> +
> +static int atmel_pinctrl_set_state(struct udevice *dev, struct udevice *config)
> +{
> +       struct atmel_pio4_port *bank_base;
> +       const void *blob = gd->fdt_blob;
> +       int node = config->of_offset;
> +       u32 offset, func, bank, line;
> +       u32 cells[MAX_PINMUX_ENTRIES];
> +       u32 i, conf;
> +       int count;
> +
> +       conf = atmel_pinctrl_get_pinconf(blob, node);
> +
> +       count = fdtdec_get_int_array_count(blob, node, "pinmux",
> +                                          cells, ARRAY_SIZE(cells));
> +       if (count < 0) {
> +               printf("%s: bad pinmux array %d\n", __func__, count);
> +               return -EINVAL;
> +       }
> +
> +       if (count > MAX_PINMUX_ENTRIES) {
> +               printf("%s: unsupported pinmux array count %d\n",
> +                      __func__, count);
> +               return -EINVAL;
> +       }
> +
> +       for (i = 0 ; i < count; i++) {
> +               offset = ATMEL_GET_PIN_NO(cells[i]);
> +               func = ATMEL_GET_PIN_FUNC(cells[i]);
> +
> +               bank = ATMEL_PIO_BANK(offset);
> +               line = ATMEL_PIO_LINE(offset);
> +
> +               bank_base = atmel_pio4_bank_base(dev, bank);
> +
> +               writel(BIT(line), &bank_base->mskr);
> +               conf &= (~ATMEL_PIO_CFGR_FUNC_MASK);
> +               conf |= (func & ATMEL_PIO_CFGR_FUNC_MASK);
> +               writel(conf, &bank_base->cfgr);
> +       }
> +
> +       return 0;
> +}
> +
> +const struct pinctrl_ops atmel_pinctrl_ops  = {
> +       .set_state = atmel_pinctrl_set_state,
> +};
> +
> +static int atmel_pinctrl_probe(struct udevice *dev)
> +{
> +       struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
> +       fdt_addr_t addr_base;
> +
> +       dev = dev_get_parent(dev);
> +       if (!dev)
> +               return -EINVAL;
> +
> +       addr_base = dev_get_addr(dev);
> +       if (addr_base == FDT_ADDR_T_NONE)
> +               return -ENODEV;

-EINVAL

> +
> +       plat->reg_base = (struct atmel_pio4_port *)addr_base;
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id atmel_pinctrl_match[] = {
> +       { .compatible = "atmel,sama5d2-pinctrl" },
> +       {}
> +};
> +
> +U_BOOT_DRIVER(atmel_pinctrl) = {
> +       .name = "pinctrl_atmel_pio4",
> +       .id = UCLASS_PINCTRL,
> +       .of_match = atmel_pinctrl_match,
> +       .probe = atmel_pinctrl_probe,
> +       .platdata_auto_alloc_size = sizeof(struct atmel_pio4_platdata),
> +       .ops = &atmel_pinctrl_ops,
> +};
> --
> 2.7.4
>

Regards,
Simon


More information about the U-Boot mailing list