[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