[PATCH 0/8] arm: mvebu: Add Armada 38x pin muxing support

This patch series add support for configuring pin muxing on Armada 38x via device tree properties used by Linux kernel. It extends also mvebu gpio driver to properly set pin function to gpio prior assigning pins and enable gpio and pinmux support on Turris Omnia.
Pali Rohár (8): pinctrl: Add new function pinctrl_generic_set_state_prefix() mvebu: pinctrl: Add Armada 38x driver arm: mvebu: Add gpio-ranges into Armada 38x device tree file pinctrl: Add third argument label for pinctrl_gpio_request() function gpio: mvebu_gpio: Add .request and .rfree methods for Armada 38x gpio: mvebu_gpio: Read number of gpios from DT gpio: mvebu_gpio: Set bank name to mvebu%d arm: mvebu: turris_omnia: Enable a38x pinctrl and gpio support
arch/arm/dts/armada-38x.dtsi | 2 + configs/turris_omnia_defconfig | 4 +- drivers/gpio/mvebu_gpio.c | 11 +- drivers/pinctrl/mvebu/Kconfig | 7 + drivers/pinctrl/mvebu/Makefile | 1 + drivers/pinctrl/mvebu/pinctrl-armada-38x.c | 589 +++++++++++++++++++++ drivers/pinctrl/pinctrl-generic.c | 100 +++- drivers/pinctrl/pinctrl-uclass.c | 3 +- include/dm/pinctrl.h | 5 +- 9 files changed, 699 insertions(+), 23 deletions(-) create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-38x.c

This new function pinctrl_generic_set_state_prefix() behaves like pinctrl_generic_set_state() but it takes third string argument which is used as the prefix for each device tree string property.
This is needed for Marvell pinctrl drivers, becase Linux device tree files have pinmux properties prefixed by "marvell," string.
This change allows to use generic U-Boot pinctrl functions for Armada 38x pinctrl driver without need to copy+paste of the majority U-Boot pinctrl code.
Signed-off-by: Pali Rohár pali@kernel.org --- drivers/pinctrl/pinctrl-generic.c | 100 +++++++++++++++++++++++++----- include/dm/pinctrl.h | 2 + 2 files changed, 85 insertions(+), 17 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c index 3c8e24088ce4..ec21d4ff8387 100644 --- a/drivers/pinctrl/pinctrl-generic.c +++ b/drivers/pinctrl/pinctrl-generic.c @@ -234,6 +234,24 @@ enum pinmux_subnode_type { PST_PINMUX, };
+static const char *alloc_name_with_prefix(const char *name, const char *prefix) +{ + if (prefix) { + char *name_with_prefix = malloc(strlen(prefix) + sizeof("pins")); + if (name_with_prefix) + sprintf(name_with_prefix, "%s%s", prefix, name); + return name_with_prefix; + } else { + return name; + } +} + +static void free_name_with_prefix(const char *name_with_prefix, const char *prefix) +{ + if (prefix) + free((char *)name_with_prefix); +} + /** * pinctrl_generic_set_state_one() - set state for a certain pin/group * Apply all pin multiplexing and pin configurations specified by @config @@ -248,9 +266,11 @@ enum pinmux_subnode_type { */ static int pinctrl_generic_set_state_one(struct udevice *dev, struct udevice *config, + const char *prefix, enum pinmux_subnode_type subnode_type, unsigned selector) { + const char *function_propname; const char *propname; const void *value; struct ofprop property; @@ -259,18 +279,26 @@ static int pinctrl_generic_set_state_one(struct udevice *dev,
assert(subnode_type != PST_NONE);
+ function_propname = alloc_name_with_prefix("function", prefix); + if (!function_propname) + return -ENOMEM; + dev_for_each_property(property, config) { value = dev_read_prop_by_prop(&property, &propname, &len); - if (!value) + if (!value) { + free_name_with_prefix(function_propname, prefix); return -EINVAL; + }
/* pinmux subnodes already have their muxing set */ if (subnode_type != PST_PINMUX && - !strcmp(propname, "function")) { + !strcmp(propname, function_propname)) { func_selector = pinmux_func_name_to_selector(dev, value); - if (func_selector < 0) + if (func_selector < 0) { + free_name_with_prefix(function_propname, prefix); return func_selector; + } ret = pinmux_enable_setting(dev, subnode_type == PST_GROUP, selector, @@ -291,10 +319,13 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, selector, param, arg); }
- if (ret) + if (ret) { + free_name_with_prefix(function_propname, prefix); return ret; + } }
+ free_name_with_prefix(function_propname, prefix); return 0; }
@@ -309,20 +340,34 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, */ static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice *dev, struct udevice *config, + const char *prefix, int *count) { const struct pinctrl_ops *ops = pinctrl_get_ops(dev); + const char *propname;
- *count = dev_read_string_count(config, "pins"); + propname = alloc_name_with_prefix("pins", prefix); + if (!propname) + return -ENOMEM; + *count = dev_read_string_count(config, propname); + free_name_with_prefix(propname, prefix); if (*count >= 0) return PST_PIN;
- *count = dev_read_string_count(config, "groups"); + propname = alloc_name_with_prefix("groups", prefix); + if (!propname) + return -ENOMEM; + *count = dev_read_string_count(config, propname); + free_name_with_prefix(propname, prefix); if (*count >= 0) return PST_GROUP;
if (ops->pinmux_property_set) { - *count = dev_read_size(config, "pinmux"); + propname = alloc_name_with_prefix("pinmux", prefix); + if (!propname) + return -ENOMEM; + *count = dev_read_size(config, propname); + free_name_with_prefix(propname, prefix); if (*count >= 0 && !(*count % sizeof(u32))) { *count /= sizeof(u32); return PST_PINMUX; @@ -338,23 +383,30 @@ static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice * * @dev: pin controller device * @config: pseudo device pointing to config node + * @prefix: device tree property prefix (e.g. vendor specific) * @return: 0 on success, or negative error code on failure */ static int pinctrl_generic_set_state_subnode(struct udevice *dev, - struct udevice *config) + struct udevice *config, + const char *prefix) { enum pinmux_subnode_type subnode_type; + const char *propname; const char *name; int count, selector, i, ret, scratch; const u32 *pinmux_groups = NULL; /* prevent use-uninitialized warning */
- subnode_type = pinctrl_generic_get_subnode_type(dev, config, &count); + subnode_type = pinctrl_generic_get_subnode_type(dev, config, prefix, &count);
debug("%s(%s, %s): count=%d\n", __func__, dev->name, config->name, count);
if (subnode_type == PST_PINMUX) { - pinmux_groups = dev_read_prop(config, "pinmux", &scratch); + propname = alloc_name_with_prefix("pinmux", prefix); + if (!propname) + return -ENOMEM; + pinmux_groups = dev_read_prop(config, propname, &scratch); + free_name_with_prefix(propname, prefix); if (!pinmux_groups) return -EINVAL; } @@ -362,13 +414,21 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev, for (i = 0; i < count; i++) { switch (subnode_type) { case PST_PIN: - ret = dev_read_string_index(config, "pins", i, &name); + propname = alloc_name_with_prefix("pins", prefix); + if (!propname) + return -ENOMEM; + ret = dev_read_string_index(config, propname, i, &name); + free_name_with_prefix(propname, prefix); if (ret) return ret; selector = pinctrl_pin_name_to_selector(dev, name); break; case PST_GROUP: - ret = dev_read_string_index(config, "groups", i, &name); + propname = alloc_name_with_prefix("groups", prefix); + if (!propname) + return -ENOMEM; + ret = dev_read_string_index(config, propname, i, &name); + free_name_with_prefix(propname, prefix); if (ret) return ret; selector = pinctrl_group_name_to_selector(dev, name); @@ -390,8 +450,8 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev, if (selector < 0) return selector;
- ret = pinctrl_generic_set_state_one(dev, config, subnode_type, - selector); + ret = pinctrl_generic_set_state_one(dev, config, prefix, + subnode_type, selector); if (ret) return ret; } @@ -399,22 +459,28 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev, return 0; }
-int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config) +int pinctrl_generic_set_state_prefix(struct udevice *dev, struct udevice *config, + const char *prefix) { struct udevice *child; int ret;
- ret = pinctrl_generic_set_state_subnode(dev, config); + ret = pinctrl_generic_set_state_subnode(dev, config, prefix); if (ret) return ret;
for (device_find_first_child(config, &child); child; device_find_next_child(&child)) { - ret = pinctrl_generic_set_state_subnode(dev, child); + ret = pinctrl_generic_set_state_subnode(dev, child, prefix); if (ret) return ret; }
return 0; } + +int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config) +{ + return pinctrl_generic_set_state_prefix(dev, config, NULL); +} diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index a09b242fd990..5436dc4a9a71 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -491,6 +491,8 @@ enum pin_config_param { * Return: 0 on success, or negative error code on failure */ int pinctrl_generic_set_state(struct udevice *pctldev, struct udevice *config); +int pinctrl_generic_set_state_prefix(struct udevice *pctldev, struct udevice *config, + const char *prefix); #else static inline int pinctrl_generic_set_state(struct udevice *pctldev, struct udevice *config)

On 25.07.22 13:56, Pali Rohár wrote:
This new function pinctrl_generic_set_state_prefix() behaves like pinctrl_generic_set_state() but it takes third string argument which is used as the prefix for each device tree string property.
This is needed for Marvell pinctrl drivers, becase Linux device tree files have pinmux properties prefixed by "marvell," string.
This change allows to use generic U-Boot pinctrl functions for Armada 38x pinctrl driver without need to copy+paste of the majority U-Boot pinctrl code.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
drivers/pinctrl/pinctrl-generic.c | 100 +++++++++++++++++++++++++----- include/dm/pinctrl.h | 2 + 2 files changed, 85 insertions(+), 17 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c index 3c8e24088ce4..ec21d4ff8387 100644 --- a/drivers/pinctrl/pinctrl-generic.c +++ b/drivers/pinctrl/pinctrl-generic.c @@ -234,6 +234,24 @@ enum pinmux_subnode_type { PST_PINMUX, };
+static const char *alloc_name_with_prefix(const char *name, const char *prefix) +{
- if (prefix) {
char *name_with_prefix = malloc(strlen(prefix) + sizeof("pins"));
if (name_with_prefix)
sprintf(name_with_prefix, "%s%s", prefix, name);
return name_with_prefix;
- } else {
return name;
- }
+}
+static void free_name_with_prefix(const char *name_with_prefix, const char *prefix) +{
- if (prefix)
free((char *)name_with_prefix);
+}
- /**
- pinctrl_generic_set_state_one() - set state for a certain pin/group
- Apply all pin multiplexing and pin configurations specified by @config
@@ -248,9 +266,11 @@ enum pinmux_subnode_type { */ static int pinctrl_generic_set_state_one(struct udevice *dev, struct udevice *config,
{const char *prefix, enum pinmux_subnode_type subnode_type, unsigned selector)
- const char *function_propname; const char *propname; const void *value; struct ofprop property;
@@ -259,18 +279,26 @@ static int pinctrl_generic_set_state_one(struct udevice *dev,
assert(subnode_type != PST_NONE);
- function_propname = alloc_name_with_prefix("function", prefix);
- if (!function_propname)
return -ENOMEM;
- dev_for_each_property(property, config) { value = dev_read_prop_by_prop(&property, &propname, &len);
if (!value)
if (!value) {
free_name_with_prefix(function_propname, prefix); return -EINVAL;
}
/* pinmux subnodes already have their muxing set */ if (subnode_type != PST_PINMUX &&
!strcmp(propname, "function")) {
!strcmp(propname, function_propname)) { func_selector = pinmux_func_name_to_selector(dev, value);
if (func_selector < 0)
if (func_selector < 0) {
free_name_with_prefix(function_propname, prefix); return func_selector;
} ret = pinmux_enable_setting(dev, subnode_type == PST_GROUP, selector,
@@ -291,10 +319,13 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, selector, param, arg); }
if (ret)
if (ret) {
free_name_with_prefix(function_propname, prefix); return ret;
}
}
free_name_with_prefix(function_propname, prefix); return 0; }
@@ -309,20 +340,34 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, */ static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice *dev, struct udevice *config,
{ const struct pinctrl_ops *ops = pinctrl_get_ops(dev);const char *prefix, int *count)
- const char *propname;
- *count = dev_read_string_count(config, "pins");
- propname = alloc_name_with_prefix("pins", prefix);
- if (!propname)
return -ENOMEM;
- *count = dev_read_string_count(config, propname);
- free_name_with_prefix(propname, prefix); if (*count >= 0) return PST_PIN;
- *count = dev_read_string_count(config, "groups");
propname = alloc_name_with_prefix("groups", prefix);
if (!propname)
return -ENOMEM;
*count = dev_read_string_count(config, propname);
free_name_with_prefix(propname, prefix); if (*count >= 0) return PST_GROUP;
if (ops->pinmux_property_set) {
*count = dev_read_size(config, "pinmux");
propname = alloc_name_with_prefix("pinmux", prefix);
if (!propname)
return -ENOMEM;
*count = dev_read_size(config, propname);
if (*count >= 0 && !(*count % sizeof(u32))) { *count /= sizeof(u32); return PST_PINMUX;free_name_with_prefix(propname, prefix);
@@ -338,23 +383,30 @@ static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice
- @dev: pin controller device
- @config: pseudo device pointing to config node
*/ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
- @prefix: device tree property prefix (e.g. vendor specific)
- @return: 0 on success, or negative error code on failure
struct udevice *config)
struct udevice *config,
{ enum pinmux_subnode_type subnode_type;const char *prefix)
- const char *propname; const char *name; int count, selector, i, ret, scratch; const u32 *pinmux_groups = NULL; /* prevent use-uninitialized warning */
- subnode_type = pinctrl_generic_get_subnode_type(dev, config, &count);
subnode_type = pinctrl_generic_get_subnode_type(dev, config, prefix, &count);
debug("%s(%s, %s): count=%d\n", __func__, dev->name, config->name, count);
if (subnode_type == PST_PINMUX) {
pinmux_groups = dev_read_prop(config, "pinmux", &scratch);
propname = alloc_name_with_prefix("pinmux", prefix);
if (!propname)
return -ENOMEM;
pinmux_groups = dev_read_prop(config, propname, &scratch);
if (!pinmux_groups) return -EINVAL; }free_name_with_prefix(propname, prefix);
@@ -362,13 +414,21 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev, for (i = 0; i < count; i++) { switch (subnode_type) { case PST_PIN:
ret = dev_read_string_index(config, "pins", i, &name);
propname = alloc_name_with_prefix("pins", prefix);
if (!propname)
return -ENOMEM;
ret = dev_read_string_index(config, propname, i, &name);
case PST_GROUP:free_name_with_prefix(propname, prefix); if (ret) return ret; selector = pinctrl_pin_name_to_selector(dev, name); break;
ret = dev_read_string_index(config, "groups", i, &name);
propname = alloc_name_with_prefix("groups", prefix);
if (!propname)
return -ENOMEM;
ret = dev_read_string_index(config, propname, i, &name);
free_name_with_prefix(propname, prefix); if (ret) return ret; selector = pinctrl_group_name_to_selector(dev, name);
@@ -390,8 +450,8 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev, if (selector < 0) return selector;
ret = pinctrl_generic_set_state_one(dev, config, subnode_type,
selector);
ret = pinctrl_generic_set_state_one(dev, config, prefix,
if (ret) return ret; }subnode_type, selector);
@@ -399,22 +459,28 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev, return 0; }
-int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config) +int pinctrl_generic_set_state_prefix(struct udevice *dev, struct udevice *config,
{ struct udevice *child; int ret;const char *prefix)
- ret = pinctrl_generic_set_state_subnode(dev, config);
ret = pinctrl_generic_set_state_subnode(dev, config, prefix); if (ret) return ret;
for (device_find_first_child(config, &child); child; device_find_next_child(&child)) {
ret = pinctrl_generic_set_state_subnode(dev, child);
ret = pinctrl_generic_set_state_subnode(dev, child, prefix);
if (ret) return ret; }
return 0; }
+int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config) +{
- return pinctrl_generic_set_state_prefix(dev, config, NULL);
+} diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index a09b242fd990..5436dc4a9a71 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -491,6 +491,8 @@ enum pin_config_param {
- Return: 0 on success, or negative error code on failure
*/ int pinctrl_generic_set_state(struct udevice *pctldev, struct udevice *config); +int pinctrl_generic_set_state_prefix(struct udevice *pctldev, struct udevice *config,
#else static inline int pinctrl_generic_set_state(struct udevice *pctldev, struct udevice *config)const char *prefix);
Viele Grüße, Stefan Roese

This new Armada 38x driver is based on Linux kernel driver. It can set any pin to any valid function specified in DT like Linux kernel, it provides support for 'pinmux status -a' command and also for pinctrl_gpio_request().
Signed-off-by: Pali Rohár pali@kernel.org --- drivers/pinctrl/mvebu/Kconfig | 7 + drivers/pinctrl/mvebu/Makefile | 1 + drivers/pinctrl/mvebu/pinctrl-armada-38x.c | 589 +++++++++++++++++++++ 3 files changed, 597 insertions(+) create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-38x.c
diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig index 07d4f3e216ae..574fb4dfb07f 100644 --- a/drivers/pinctrl/mvebu/Kconfig +++ b/drivers/pinctrl/mvebu/Kconfig @@ -1,5 +1,12 @@ if ARCH_MVEBU
+config PINCTRL_ARMADA_38X + depends on ARMADA_38X && PINCTRL_FULL + bool "Armada 38x pin control driver" + help + Support pin multiplexing and pin configuration control on + Marvell's Armada-38x SoC. + config PINCTRL_ARMADA_37XX depends on ARMADA_3700 && PINCTRL_FULL bool "Armada 37xx pin control driver" diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile index c2df96bf5b12..15303d83a71e 100644 --- a/drivers/pinctrl/mvebu/Makefile +++ b/drivers/pinctrl/mvebu/Makefile @@ -4,5 +4,6 @@ # # https://spdx.org/licenses
+obj-$(CONFIG_PINCTRL_ARMADA_38X) += pinctrl-armada-38x.o obj-$(CONFIG_PINCTRL_ARMADA_37XX) += pinctrl-armada-37xx.o obj-$(CONFIG_PINCTRL_ARMADA_8K) += pinctrl-mvebu.o diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c new file mode 100644 index 000000000000..252151f3e5d9 --- /dev/null +++ b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c @@ -0,0 +1,589 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// (C) 2022 Pali Rohár pali@kernel.org + +#include <common.h> +#include <config.h> +#include <dm.h> +#include <dm/devres.h> +#include <dm/lists.h> +#include <dm/pinctrl.h> +#include <dm/root.h> +#include <errno.h> +#include <asm/io.h> + +struct mvebu_mpp_ctrl_setting { + const char *name; + const char *subname; + u8 val; + u8 variant; +}; + +struct mvebu_mpp_mode { + const char *name; + size_t nsettings; + struct mvebu_mpp_ctrl_setting *settings; +}; + +#define MPP_MODE(_name, ...) \ + { \ + .name = _name, \ + .nsettings = ARRAY_SIZE(( \ + (struct mvebu_mpp_ctrl_setting[]) \ + { __VA_ARGS__ })), \ + .settings = (struct mvebu_mpp_ctrl_setting[]){ \ + __VA_ARGS__ }, \ + } + +#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \ + { \ + .val = _val, \ + .name = _name, \ + .subname = _subname, \ + .variant = _mask, \ + } + +#define MVEBU_MPPS_PER_REG 8 +#define MVEBU_MPP_BITS 4 +#define MVEBU_MPP_MASK 0xf + +enum { + V_88F6810 = BIT(0), + V_88F6820 = BIT(1), + V_88F6828 = BIT(2), + V_88F6810_PLUS = (V_88F6810 | V_88F6820 | V_88F6828), + V_88F6820_PLUS = (V_88F6820 | V_88F6828), +}; + +static struct mvebu_mpp_mode armada_38x_mpp_modes[] = { + MPP_MODE("mpp0", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ua0", "rxd", V_88F6810_PLUS)), + MPP_MODE("mpp1", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ua0", "txd", V_88F6810_PLUS)), + MPP_MODE("mpp2", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "i2c0", "sck", V_88F6810_PLUS)), + MPP_MODE("mpp3", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "i2c0", "sda", V_88F6810_PLUS)), + MPP_MODE("mpp4", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge", "mdc", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ua1", "txd", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ua0", "rts", V_88F6810_PLUS)), + MPP_MODE("mpp5", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge", "mdio", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ua1", "rxd", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ua0", "cts", V_88F6810_PLUS)), + MPP_MODE("mpp6", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "txclkout", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge0", "crs", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "cs3", V_88F6810_PLUS)), + MPP_MODE("mpp7", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "txd0", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad9", V_88F6810_PLUS)), + MPP_MODE("mpp8", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "txd1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad10", V_88F6810_PLUS)), + MPP_MODE("mpp9", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "txd2", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad11", V_88F6810_PLUS)), + MPP_MODE("mpp10", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "txd3", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad12", V_88F6810_PLUS)), + MPP_MODE("mpp11", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "txctl", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad13", V_88F6810_PLUS)), + MPP_MODE("mpp12", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "rxd0", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "pcie0", "rstout", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi0", "cs1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad14", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "pcie3", "clkreq", V_88F6810_PLUS)), + MPP_MODE("mpp13", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "rxd1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "pcie0", "clkreq", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "pcie1", "clkreq", V_88F6820_PLUS), + MPP_VAR_FUNCTION(4, "spi0", "cs2", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad15", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "pcie2", "clkreq", V_88F6810_PLUS)), + MPP_MODE("mpp14", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "rxd2", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ptp", "clk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "dram", "vttctrl", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi0", "cs3", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "we1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "pcie3", "clkreq", V_88F6810_PLUS)), + MPP_MODE("mpp15", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "rxd3", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge", "mdc slave", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "pcie0", "rstout", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi0", "mosi", V_88F6810_PLUS)), + MPP_MODE("mpp16", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "rxctl", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge", "mdio slave", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "dram", "deccerr", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi0", "miso", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "pcie0", "clkreq", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "pcie1", "clkreq", V_88F6820_PLUS)), + MPP_MODE("mpp17", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "rxclk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ptp", "clk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ua1", "rxd", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi0", "sck", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "sata1", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "sata0", "prsnt", V_88F6810_PLUS)), + MPP_MODE("mpp18", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "rxerr", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ptp", "trig", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ua1", "txd", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi0", "cs0", V_88F6810_PLUS)), + MPP_MODE("mpp19", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "col", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ptp", "evreq", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ge0", "txerr", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sata1", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "ua0", "cts", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)), + MPP_MODE("mpp20", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ge0", "txclk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ptp", "clk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sata0", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "ua0", "rts", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)), + MPP_MODE("mpp21", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "spi0", "cs1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "rxd0", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "sata0", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sd0", "cmd", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "bootcs", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "sata1", "prsnt", V_88F6810_PLUS)), + MPP_MODE("mpp22", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "spi0", "mosi", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad0", V_88F6810_PLUS)), + MPP_MODE("mpp23", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "spi0", "sck", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad2", V_88F6810_PLUS)), + MPP_MODE("mpp24", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "spi0", "miso", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ua0", "cts", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ua1", "rxd", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sd0", "d4", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ready", V_88F6810_PLUS)), + MPP_MODE("mpp25", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "spi0", "cs0", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ua0", "rts", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ua1", "txd", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sd0", "d5", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "cs0", V_88F6810_PLUS)), + MPP_MODE("mpp26", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "spi0", "cs2", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "i2c1", "sck", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sd0", "d6", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "cs1", V_88F6810_PLUS)), + MPP_MODE("mpp27", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "spi0", "cs3", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "txclkout", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "i2c1", "sda", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sd0", "d7", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "cs2", V_88F6810_PLUS)), + MPP_MODE("mpp28", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "txd0", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sd0", "clk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad5", V_88F6810_PLUS)), + MPP_MODE("mpp29", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "txd1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ale0", V_88F6810_PLUS)), + MPP_MODE("mpp30", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "txd2", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "oe", V_88F6810_PLUS)), + MPP_MODE("mpp31", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "txd3", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ale1", V_88F6810_PLUS)), + MPP_MODE("mpp32", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "txctl", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "we0", V_88F6810_PLUS)), + MPP_MODE("mpp33", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "dram", "deccerr", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad3", V_88F6810_PLUS)), + MPP_MODE("mpp34", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad1", V_88F6810_PLUS)), + MPP_MODE("mpp35", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ref", "clk_out1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "a1", V_88F6810_PLUS)), + MPP_MODE("mpp36", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ptp", "trig", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "a0", V_88F6810_PLUS)), + MPP_MODE("mpp37", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ptp", "clk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "rxclk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sd0", "d3", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad8", V_88F6810_PLUS)), + MPP_MODE("mpp38", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ptp", "evreq", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "rxd1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ref", "clk_out0", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sd0", "d0", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad4", V_88F6810_PLUS)), + MPP_MODE("mpp39", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "i2c1", "sck", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "rxd2", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ua0", "cts", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sd0", "d1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "a2", V_88F6810_PLUS)), + MPP_MODE("mpp40", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "i2c1", "sda", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "rxd3", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ua0", "rts", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "sd0", "d2", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad6", V_88F6810_PLUS)), + MPP_MODE("mpp41", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ua1", "rxd", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge1", "rxctl", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ua0", "cts", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi1", "cs3", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "burst/last", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "nand", "rb0", V_88F6810_PLUS)), + MPP_MODE("mpp42", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ua1", "txd", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "ua0", "rts", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "ad7", V_88F6810_PLUS)), + MPP_MODE("mpp43", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "pcie0", "clkreq", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "dram", "vttctrl", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "dram", "deccerr", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi1", "cs2", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dev", "clkout", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "nand", "rb1", V_88F6810_PLUS)), + MPP_MODE("mpp44", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "sata1", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "sata2", "prsnt", V_88F6828), + MPP_VAR_FUNCTION(4, "sata3", "prsnt", V_88F6828)), + MPP_MODE("mpp45", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ref", "clk_out0", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "pcie0", "rstout", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)), + MPP_MODE("mpp46", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ref", "clk_out1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "pcie0", "rstout", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)), + MPP_MODE("mpp47", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "sata1", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "sata2", "prsnt", V_88F6828), + MPP_VAR_FUNCTION(5, "sata3", "prsnt", V_88F6828)), + MPP_MODE("mpp48", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "dram", "vttctrl", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "tdm", "pclk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "audio", "mclk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "sd0", "d4", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "pcie0", "clkreq", V_88F6810_PLUS)), + MPP_MODE("mpp49", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "sata2", "prsnt", V_88F6828), + MPP_VAR_FUNCTION(2, "sata3", "prsnt", V_88F6828), + MPP_VAR_FUNCTION(3, "tdm", "fsync", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "audio", "lrclk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "sd0", "d5", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "pcie1", "clkreq", V_88F6820_PLUS)), + MPP_MODE("mpp50", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "pcie0", "rstout", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "tdm", "drx", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "audio", "extclk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "sd0", "cmd", V_88F6810_PLUS)), + MPP_MODE("mpp51", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "tdm", "dtx", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "audio", "sdo", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "dram", "deccerr", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "ptp", "trig", V_88F6810_PLUS)), + MPP_MODE("mpp52", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "pcie0", "rstout", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "tdm", "int", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "audio", "sdi", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "sd0", "d6", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "ptp", "clk", V_88F6810_PLUS)), + MPP_MODE("mpp53", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "sata1", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "sata0", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "tdm", "rst", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "audio", "bclk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "sd0", "d7", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "ptp", "evreq", V_88F6810_PLUS)), + MPP_MODE("mpp54", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "sata1", "prsnt", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "pcie0", "rstout", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "ge0", "txerr", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "sd0", "d3", V_88F6810_PLUS)), + MPP_MODE("mpp55", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ua1", "cts", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge", "mdio", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "pcie1", "clkreq", V_88F6820_PLUS), + MPP_VAR_FUNCTION(4, "spi1", "cs1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "sd0", "d0", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)), + MPP_MODE("mpp56", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "ua1", "rts", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "ge", "mdc", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "dram", "deccerr", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi1", "mosi", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)), + MPP_MODE("mpp57", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi1", "sck", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "sd0", "clk", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)), + MPP_MODE("mpp58", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "pcie1", "clkreq", V_88F6820_PLUS), + MPP_VAR_FUNCTION(2, "i2c1", "sck", V_88F6810_PLUS), + MPP_VAR_FUNCTION(3, "pcie2", "clkreq", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi1", "miso", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "sd0", "d1", V_88F6810_PLUS), + MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)), + MPP_MODE("mpp59", + MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS), + MPP_VAR_FUNCTION(1, "pcie0", "rstout", V_88F6810_PLUS), + MPP_VAR_FUNCTION(2, "i2c1", "sda", V_88F6810_PLUS), + MPP_VAR_FUNCTION(4, "spi1", "cs0", V_88F6810_PLUS), + MPP_VAR_FUNCTION(5, "sd0", "d2", V_88F6810_PLUS)), +}; + +static const char * const armada_38x_mpp_function_names[] = { + "gpio", /* make gpio always as function 0 */ + + "audio", + "dev", + "dram", + "ge", + "ge0", + "ge1", + "i2c0", + "i2c1", + "nand", + "pcie0", + "pcie1", + "pcie2", + "pcie3", + "ptp", + "ref", + "sata0", + "sata1", + "sata2", + "sata3", + "sd0", + "spi0", + "spi1", + "tdm", + "ua0", + "ua1", +}; + +struct armada_38x_pinctrl { + void __iomem *base; + u8 variant; +}; + +static int armada_38x_pinctrl_get_pins_count(struct udevice *dev) +{ + return ARRAY_SIZE(armada_38x_mpp_modes); +} + +static const char *armada_38x_pinctrl_get_pin_name(struct udevice *dev, unsigned int selector) +{ + return armada_38x_mpp_modes[selector].name; +} + +static int armada_38x_pinctrl_get_functions_count(struct udevice *dev) +{ + return ARRAY_SIZE(armada_38x_mpp_function_names); +} + +static const char *armada_38x_pinctrl_get_function_name(struct udevice *dev, unsigned int selector) +{ + return armada_38x_mpp_function_names[selector]; +} + +static int armada_38x_pinctrl_get_pin_muxing(struct udevice *dev, unsigned int selector, + char *buf, int size) +{ + struct armada_38x_pinctrl *info = dev_get_priv(dev); + unsigned int off = (selector / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; + unsigned int shift = (selector % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; + const char *func_name = NULL; + const char *sub_name = NULL; + unsigned long config; + int i; + + config = (readl(info->base + off) >> shift) & MVEBU_MPP_MASK; + + for (i = 0; i < armada_38x_mpp_modes[selector].nsettings; i++) { + if (armada_38x_mpp_modes[selector].settings[i].val == config) + break; + } + + if (i < armada_38x_mpp_modes[selector].nsettings) { + func_name = armada_38x_mpp_modes[selector].settings[i].name; + sub_name = armada_38x_mpp_modes[selector].settings[i].subname; + } + + snprintf(buf, size, "%s%s%s", + func_name ? func_name : "unknown", + sub_name ? "_" : "", + sub_name ? sub_name : ""); + return 0; +} + +static int armada_38x_pinctrl_pinmux_set(struct udevice *dev, unsigned int pin_selector, + unsigned int func_selector) +{ + struct armada_38x_pinctrl *info = dev_get_priv(dev); + unsigned int off = (pin_selector / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; + unsigned int shift = (pin_selector % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; + const char *func_name = armada_38x_mpp_function_names[func_selector]; + unsigned long config, reg; + int i; + + for (i = 0; i < armada_38x_mpp_modes[pin_selector].nsettings; i++) { + if (strcmp(armada_38x_mpp_modes[pin_selector].settings[i].name, func_name) == 0) + break; + } + + if (i >= armada_38x_mpp_modes[pin_selector].nsettings) + return -EINVAL; + + if (!(info->variant & armada_38x_mpp_modes[pin_selector].settings[i].variant)) + return -EINVAL; + + reg = readl(info->base + off) & ~(MVEBU_MPP_MASK << shift); + config = armada_38x_mpp_modes[pin_selector].settings[i].val; + writel(reg | (config << shift), info->base + off); + + return 0; +} + +static int armada_38x_pinctrl_gpio_request_enable(struct udevice *dev, unsigned int selector) +{ + char buf[20]; + + armada_38x_pinctrl_get_pin_muxing(dev, selector, buf, sizeof(buf)); + if (strcmp(buf, "gpio") != 0) + printf("Warning: Changing mpp%u function from %s to gpio...\n", selector, buf); + + return armada_38x_pinctrl_pinmux_set(dev, selector, 0); /* gpio is always function 0 */ +} + +static int armada_38x_pinctrl_gpio_disable_free(struct udevice *dev, unsigned int selector) +{ + /* nothing to do */ + return 0; +} + +static int armada_38x_pinctrl_set_state(struct udevice *dev, struct udevice *config) +{ + return pinctrl_generic_set_state_prefix(dev, config, "marvell,"); +} + +static int armada_38x_pinctrl_probe(struct udevice *dev) +{ + struct armada_38x_pinctrl *info = dev_get_priv(dev); + + info->variant = (u8)dev_get_driver_data(dev); + info->base = dev_read_addr_ptr(dev); + + if (!info->base) + return -EINVAL; + + return 0; +} + +struct pinctrl_ops armada_37xx_pinctrl_ops = { + .get_pins_count = armada_38x_pinctrl_get_pins_count, + .get_pin_name = armada_38x_pinctrl_get_pin_name, + .get_functions_count = armada_38x_pinctrl_get_functions_count, + .get_function_name = armada_38x_pinctrl_get_function_name, + .get_pin_muxing = armada_38x_pinctrl_get_pin_muxing, + .pinmux_set = armada_38x_pinctrl_pinmux_set, + .gpio_request_enable = armada_38x_pinctrl_gpio_request_enable, + .gpio_disable_free = armada_38x_pinctrl_gpio_disable_free, + .set_state = armada_38x_pinctrl_set_state, +}; + +static const struct udevice_id armada_38x_pinctrl_of_match[] = { + { + .compatible = "marvell,mv88f6810-pinctrl", + .data = V_88F6810, + }, + { + .compatible = "marvell,mv88f6820-pinctrl", + .data = V_88F6820, + }, + { + .compatible = "marvell,mv88f6828-pinctrl", + .data = V_88F6828, + }, + { }, +}; + +U_BOOT_DRIVER(armada_38x_pinctrl) = { + .name = "armada-38x-pinctrl", + .id = UCLASS_PINCTRL, + .of_match = of_match_ptr(armada_38x_pinctrl_of_match), + .probe = armada_38x_pinctrl_probe, + .priv_auto = sizeof(struct armada_38x_pinctrl), + .ops = &armada_37xx_pinctrl_ops, +};

On 25.07.22 13:56, Pali Rohár wrote:
This new Armada 38x driver is based on Linux kernel driver. It can set any pin to any valid function specified in DT like Linux kernel, it provides support for 'pinmux status -a' command and also for pinctrl_gpio_request().
Signed-off-by: Pali Rohár pali@kernel.org
I'm very happy to see this support coming in. Thanks!
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
drivers/pinctrl/mvebu/Kconfig | 7 + drivers/pinctrl/mvebu/Makefile | 1 + drivers/pinctrl/mvebu/pinctrl-armada-38x.c | 589 +++++++++++++++++++++ 3 files changed, 597 insertions(+) create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-38x.c
diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig index 07d4f3e216ae..574fb4dfb07f 100644 --- a/drivers/pinctrl/mvebu/Kconfig +++ b/drivers/pinctrl/mvebu/Kconfig @@ -1,5 +1,12 @@ if ARCH_MVEBU
+config PINCTRL_ARMADA_38X
- depends on ARMADA_38X && PINCTRL_FULL
- bool "Armada 38x pin control driver"
- help
Support pin multiplexing and pin configuration control on
Marvell's Armada-38x SoC.
- config PINCTRL_ARMADA_37XX depends on ARMADA_3700 && PINCTRL_FULL bool "Armada 37xx pin control driver"
diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile index c2df96bf5b12..15303d83a71e 100644 --- a/drivers/pinctrl/mvebu/Makefile +++ b/drivers/pinctrl/mvebu/Makefile @@ -4,5 +4,6 @@ # # https://spdx.org/licenses
+obj-$(CONFIG_PINCTRL_ARMADA_38X) += pinctrl-armada-38x.o obj-$(CONFIG_PINCTRL_ARMADA_37XX) += pinctrl-armada-37xx.o obj-$(CONFIG_PINCTRL_ARMADA_8K) += pinctrl-mvebu.o diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c new file mode 100644 index 000000000000..252151f3e5d9 --- /dev/null +++ b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c @@ -0,0 +1,589 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// (C) 2022 Pali Rohár pali@kernel.org
+#include <common.h> +#include <config.h> +#include <dm.h> +#include <dm/devres.h> +#include <dm/lists.h> +#include <dm/pinctrl.h> +#include <dm/root.h> +#include <errno.h> +#include <asm/io.h>
+struct mvebu_mpp_ctrl_setting {
- const char *name;
- const char *subname;
- u8 val;
- u8 variant;
+};
+struct mvebu_mpp_mode {
- const char *name;
- size_t nsettings;
- struct mvebu_mpp_ctrl_setting *settings;
+};
+#define MPP_MODE(_name, ...) \
- { \
.name = _name, \
.nsettings = ARRAY_SIZE(( \
(struct mvebu_mpp_ctrl_setting[]) \
{ __VA_ARGS__ })), \
.settings = (struct mvebu_mpp_ctrl_setting[]){ \
__VA_ARGS__ }, \
- }
+#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \
- { \
.val = _val, \
.name = _name, \
.subname = _subname, \
.variant = _mask, \
- }
+#define MVEBU_MPPS_PER_REG 8 +#define MVEBU_MPP_BITS 4 +#define MVEBU_MPP_MASK 0xf
+enum {
- V_88F6810 = BIT(0),
- V_88F6820 = BIT(1),
- V_88F6828 = BIT(2),
- V_88F6810_PLUS = (V_88F6810 | V_88F6820 | V_88F6828),
- V_88F6820_PLUS = (V_88F6820 | V_88F6828),
+};
+static struct mvebu_mpp_mode armada_38x_mpp_modes[] = {
- MPP_MODE("mpp0",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ua0", "rxd", V_88F6810_PLUS)),
- MPP_MODE("mpp1",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ua0", "txd", V_88F6810_PLUS)),
- MPP_MODE("mpp2",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "i2c0", "sck", V_88F6810_PLUS)),
- MPP_MODE("mpp3",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "i2c0", "sda", V_88F6810_PLUS)),
- MPP_MODE("mpp4",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge", "mdc", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ua1", "txd", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ua0", "rts", V_88F6810_PLUS)),
- MPP_MODE("mpp5",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge", "mdio", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ua1", "rxd", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ua0", "cts", V_88F6810_PLUS)),
- MPP_MODE("mpp6",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "txclkout", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge0", "crs", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "cs3", V_88F6810_PLUS)),
- MPP_MODE("mpp7",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "txd0", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad9", V_88F6810_PLUS)),
- MPP_MODE("mpp8",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "txd1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad10", V_88F6810_PLUS)),
- MPP_MODE("mpp9",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "txd2", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad11", V_88F6810_PLUS)),
- MPP_MODE("mpp10",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "txd3", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad12", V_88F6810_PLUS)),
- MPP_MODE("mpp11",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "txctl", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad13", V_88F6810_PLUS)),
- MPP_MODE("mpp12",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "rxd0", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "pcie0", "rstout", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi0", "cs1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad14", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "pcie3", "clkreq", V_88F6810_PLUS)),
- MPP_MODE("mpp13",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "rxd1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "pcie0", "clkreq", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "pcie1", "clkreq", V_88F6820_PLUS),
MPP_VAR_FUNCTION(4, "spi0", "cs2", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad15", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "pcie2", "clkreq", V_88F6810_PLUS)),
- MPP_MODE("mpp14",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "rxd2", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ptp", "clk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "dram", "vttctrl", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi0", "cs3", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "we1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "pcie3", "clkreq", V_88F6810_PLUS)),
- MPP_MODE("mpp15",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "rxd3", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge", "mdc slave", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "pcie0", "rstout", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi0", "mosi", V_88F6810_PLUS)),
- MPP_MODE("mpp16",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "rxctl", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge", "mdio slave", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "dram", "deccerr", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi0", "miso", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "pcie0", "clkreq", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "pcie1", "clkreq", V_88F6820_PLUS)),
- MPP_MODE("mpp17",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "rxclk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ptp", "clk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ua1", "rxd", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi0", "sck", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "sata1", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "sata0", "prsnt", V_88F6810_PLUS)),
- MPP_MODE("mpp18",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "rxerr", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ptp", "trig", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ua1", "txd", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi0", "cs0", V_88F6810_PLUS)),
- MPP_MODE("mpp19",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "col", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ptp", "evreq", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ge0", "txerr", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sata1", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "ua0", "cts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)),
- MPP_MODE("mpp20",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "txclk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ptp", "clk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sata0", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "ua0", "rts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)),
- MPP_MODE("mpp21",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "spi0", "cs1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "rxd0", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "sata0", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sd0", "cmd", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "bootcs", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "sata1", "prsnt", V_88F6810_PLUS)),
- MPP_MODE("mpp22",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "spi0", "mosi", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad0", V_88F6810_PLUS)),
- MPP_MODE("mpp23",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "spi0", "sck", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad2", V_88F6810_PLUS)),
- MPP_MODE("mpp24",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "spi0", "miso", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ua0", "cts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ua1", "rxd", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sd0", "d4", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ready", V_88F6810_PLUS)),
- MPP_MODE("mpp25",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "spi0", "cs0", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ua0", "rts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ua1", "txd", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sd0", "d5", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "cs0", V_88F6810_PLUS)),
- MPP_MODE("mpp26",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "spi0", "cs2", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "i2c1", "sck", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sd0", "d6", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "cs1", V_88F6810_PLUS)),
- MPP_MODE("mpp27",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "spi0", "cs3", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "txclkout", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "i2c1", "sda", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sd0", "d7", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "cs2", V_88F6810_PLUS)),
- MPP_MODE("mpp28",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "txd0", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sd0", "clk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad5", V_88F6810_PLUS)),
- MPP_MODE("mpp29",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "txd1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ale0", V_88F6810_PLUS)),
- MPP_MODE("mpp30",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "txd2", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "oe", V_88F6810_PLUS)),
- MPP_MODE("mpp31",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "txd3", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ale1", V_88F6810_PLUS)),
- MPP_MODE("mpp32",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "txctl", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "we0", V_88F6810_PLUS)),
- MPP_MODE("mpp33",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "dram", "deccerr", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad3", V_88F6810_PLUS)),
- MPP_MODE("mpp34",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad1", V_88F6810_PLUS)),
- MPP_MODE("mpp35",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ref", "clk_out1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "a1", V_88F6810_PLUS)),
- MPP_MODE("mpp36",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ptp", "trig", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "a0", V_88F6810_PLUS)),
- MPP_MODE("mpp37",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ptp", "clk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "rxclk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sd0", "d3", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad8", V_88F6810_PLUS)),
- MPP_MODE("mpp38",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ptp", "evreq", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "rxd1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ref", "clk_out0", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sd0", "d0", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad4", V_88F6810_PLUS)),
- MPP_MODE("mpp39",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "i2c1", "sck", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "rxd2", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ua0", "cts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sd0", "d1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "a2", V_88F6810_PLUS)),
- MPP_MODE("mpp40",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "i2c1", "sda", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "rxd3", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ua0", "rts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sd0", "d2", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad6", V_88F6810_PLUS)),
- MPP_MODE("mpp41",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ua1", "rxd", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge1", "rxctl", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ua0", "cts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi1", "cs3", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "burst/last", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "nand", "rb0", V_88F6810_PLUS)),
- MPP_MODE("mpp42",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ua1", "txd", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "ua0", "rts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "ad7", V_88F6810_PLUS)),
- MPP_MODE("mpp43",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "pcie0", "clkreq", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "dram", "vttctrl", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "dram", "deccerr", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi1", "cs2", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dev", "clkout", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "nand", "rb1", V_88F6810_PLUS)),
- MPP_MODE("mpp44",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "sata1", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "sata2", "prsnt", V_88F6828),
MPP_VAR_FUNCTION(4, "sata3", "prsnt", V_88F6828)),
- MPP_MODE("mpp45",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ref", "clk_out0", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "pcie0", "rstout", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)),
- MPP_MODE("mpp46",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ref", "clk_out1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "pcie0", "rstout", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)),
- MPP_MODE("mpp47",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "sata1", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "sata2", "prsnt", V_88F6828),
MPP_VAR_FUNCTION(5, "sata3", "prsnt", V_88F6828)),
- MPP_MODE("mpp48",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "dram", "vttctrl", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "tdm", "pclk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "audio", "mclk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "sd0", "d4", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "pcie0", "clkreq", V_88F6810_PLUS)),
- MPP_MODE("mpp49",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "sata2", "prsnt", V_88F6828),
MPP_VAR_FUNCTION(2, "sata3", "prsnt", V_88F6828),
MPP_VAR_FUNCTION(3, "tdm", "fsync", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "audio", "lrclk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "sd0", "d5", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "pcie1", "clkreq", V_88F6820_PLUS)),
- MPP_MODE("mpp50",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "pcie0", "rstout", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "tdm", "drx", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "audio", "extclk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "sd0", "cmd", V_88F6810_PLUS)),
- MPP_MODE("mpp51",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "tdm", "dtx", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "audio", "sdo", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "dram", "deccerr", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ptp", "trig", V_88F6810_PLUS)),
- MPP_MODE("mpp52",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "pcie0", "rstout", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "tdm", "int", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "audio", "sdi", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "sd0", "d6", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ptp", "clk", V_88F6810_PLUS)),
- MPP_MODE("mpp53",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "sata1", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "sata0", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "tdm", "rst", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "audio", "bclk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "sd0", "d7", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ptp", "evreq", V_88F6810_PLUS)),
- MPP_MODE("mpp54",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "sata1", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "pcie0", "rstout", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "ge0", "txerr", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "sd0", "d3", V_88F6810_PLUS)),
- MPP_MODE("mpp55",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ua1", "cts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge", "mdio", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "pcie1", "clkreq", V_88F6820_PLUS),
MPP_VAR_FUNCTION(4, "spi1", "cs1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "sd0", "d0", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)),
- MPP_MODE("mpp56",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ua1", "rts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ge", "mdc", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "dram", "deccerr", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi1", "mosi", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)),
- MPP_MODE("mpp57",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi1", "sck", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "sd0", "clk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)),
- MPP_MODE("mpp58",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "pcie1", "clkreq", V_88F6820_PLUS),
MPP_VAR_FUNCTION(2, "i2c1", "sck", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "pcie2", "clkreq", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi1", "miso", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "sd0", "d1", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)),
- MPP_MODE("mpp59",
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "pcie0", "rstout", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "i2c1", "sda", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "spi1", "cs0", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "sd0", "d2", V_88F6810_PLUS)),
+};
+static const char * const armada_38x_mpp_function_names[] = {
- "gpio", /* make gpio always as function 0 */
- "audio",
- "dev",
- "dram",
- "ge",
- "ge0",
- "ge1",
- "i2c0",
- "i2c1",
- "nand",
- "pcie0",
- "pcie1",
- "pcie2",
- "pcie3",
- "ptp",
- "ref",
- "sata0",
- "sata1",
- "sata2",
- "sata3",
- "sd0",
- "spi0",
- "spi1",
- "tdm",
- "ua0",
- "ua1",
+};
+struct armada_38x_pinctrl {
- void __iomem *base;
- u8 variant;
+};
+static int armada_38x_pinctrl_get_pins_count(struct udevice *dev) +{
- return ARRAY_SIZE(armada_38x_mpp_modes);
+}
+static const char *armada_38x_pinctrl_get_pin_name(struct udevice *dev, unsigned int selector) +{
- return armada_38x_mpp_modes[selector].name;
+}
+static int armada_38x_pinctrl_get_functions_count(struct udevice *dev) +{
- return ARRAY_SIZE(armada_38x_mpp_function_names);
+}
+static const char *armada_38x_pinctrl_get_function_name(struct udevice *dev, unsigned int selector) +{
- return armada_38x_mpp_function_names[selector];
+}
+static int armada_38x_pinctrl_get_pin_muxing(struct udevice *dev, unsigned int selector,
char *buf, int size)
+{
- struct armada_38x_pinctrl *info = dev_get_priv(dev);
- unsigned int off = (selector / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
- unsigned int shift = (selector % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
- const char *func_name = NULL;
- const char *sub_name = NULL;
- unsigned long config;
- int i;
- config = (readl(info->base + off) >> shift) & MVEBU_MPP_MASK;
- for (i = 0; i < armada_38x_mpp_modes[selector].nsettings; i++) {
if (armada_38x_mpp_modes[selector].settings[i].val == config)
break;
- }
- if (i < armada_38x_mpp_modes[selector].nsettings) {
func_name = armada_38x_mpp_modes[selector].settings[i].name;
sub_name = armada_38x_mpp_modes[selector].settings[i].subname;
- }
- snprintf(buf, size, "%s%s%s",
func_name ? func_name : "unknown",
sub_name ? "_" : "",
sub_name ? sub_name : "");
- return 0;
+}
+static int armada_38x_pinctrl_pinmux_set(struct udevice *dev, unsigned int pin_selector,
unsigned int func_selector)
+{
- struct armada_38x_pinctrl *info = dev_get_priv(dev);
- unsigned int off = (pin_selector / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
- unsigned int shift = (pin_selector % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
- const char *func_name = armada_38x_mpp_function_names[func_selector];
- unsigned long config, reg;
- int i;
- for (i = 0; i < armada_38x_mpp_modes[pin_selector].nsettings; i++) {
if (strcmp(armada_38x_mpp_modes[pin_selector].settings[i].name, func_name) == 0)
break;
- }
- if (i >= armada_38x_mpp_modes[pin_selector].nsettings)
return -EINVAL;
- if (!(info->variant & armada_38x_mpp_modes[pin_selector].settings[i].variant))
return -EINVAL;
- reg = readl(info->base + off) & ~(MVEBU_MPP_MASK << shift);
- config = armada_38x_mpp_modes[pin_selector].settings[i].val;
- writel(reg | (config << shift), info->base + off);
- return 0;
+}
+static int armada_38x_pinctrl_gpio_request_enable(struct udevice *dev, unsigned int selector) +{
- char buf[20];
- armada_38x_pinctrl_get_pin_muxing(dev, selector, buf, sizeof(buf));
- if (strcmp(buf, "gpio") != 0)
printf("Warning: Changing mpp%u function from %s to gpio...\n", selector, buf);
- return armada_38x_pinctrl_pinmux_set(dev, selector, 0); /* gpio is always function 0 */
+}
+static int armada_38x_pinctrl_gpio_disable_free(struct udevice *dev, unsigned int selector) +{
- /* nothing to do */
- return 0;
+}
+static int armada_38x_pinctrl_set_state(struct udevice *dev, struct udevice *config) +{
- return pinctrl_generic_set_state_prefix(dev, config, "marvell,");
+}
+static int armada_38x_pinctrl_probe(struct udevice *dev) +{
- struct armada_38x_pinctrl *info = dev_get_priv(dev);
- info->variant = (u8)dev_get_driver_data(dev);
- info->base = dev_read_addr_ptr(dev);
- if (!info->base)
return -EINVAL;
- return 0;
+}
+struct pinctrl_ops armada_37xx_pinctrl_ops = {
- .get_pins_count = armada_38x_pinctrl_get_pins_count,
- .get_pin_name = armada_38x_pinctrl_get_pin_name,
- .get_functions_count = armada_38x_pinctrl_get_functions_count,
- .get_function_name = armada_38x_pinctrl_get_function_name,
- .get_pin_muxing = armada_38x_pinctrl_get_pin_muxing,
- .pinmux_set = armada_38x_pinctrl_pinmux_set,
- .gpio_request_enable = armada_38x_pinctrl_gpio_request_enable,
- .gpio_disable_free = armada_38x_pinctrl_gpio_disable_free,
- .set_state = armada_38x_pinctrl_set_state,
+};
+static const struct udevice_id armada_38x_pinctrl_of_match[] = {
- {
.compatible = "marvell,mv88f6810-pinctrl",
.data = V_88F6810,
- },
- {
.compatible = "marvell,mv88f6820-pinctrl",
.data = V_88F6820,
- },
- {
.compatible = "marvell,mv88f6828-pinctrl",
.data = V_88F6828,
- },
- { },
+};
+U_BOOT_DRIVER(armada_38x_pinctrl) = {
- .name = "armada-38x-pinctrl",
- .id = UCLASS_PINCTRL,
- .of_match = of_match_ptr(armada_38x_pinctrl_of_match),
- .probe = armada_38x_pinctrl_probe,
- .priv_auto = sizeof(struct armada_38x_pinctrl),
- .ops = &armada_37xx_pinctrl_ops,
+};
Viele Grüße, Stefan Roese

This allows U-Boot mvebu-gpio.c driver to switch particular MPP pin into GPIO mode and enable GPIO support.
Signed-off-by: Pali Rohár pali@kernel.org --- arch/arm/dts/armada-38x.dtsi | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/dts/armada-38x.dtsi b/arch/arm/dts/armada-38x.dtsi index 061bd7852081..7d76df3f9ce7 100644 --- a/arch/arm/dts/armada-38x.dtsi +++ b/arch/arm/dts/armada-38x.dtsi @@ -295,6 +295,7 @@ reg-names = "gpio", "pwm"; ngpios = <32>; gpio-controller; + gpio-ranges = <&pinctrl 0 0 32>; #gpio-cells = <2>; #pwm-cells = <2>; interrupt-controller; @@ -313,6 +314,7 @@ reg-names = "gpio", "pwm"; ngpios = <28>; gpio-controller; + gpio-ranges = <&pinctrl 0 32 28>; #gpio-cells = <2>; #pwm-cells = <2>; interrupt-controller;

On 25.07.22 13:56, Pali Rohár wrote:
This allows U-Boot mvebu-gpio.c driver to switch particular MPP pin into GPIO mode and enable GPIO support.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
arch/arm/dts/armada-38x.dtsi | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/dts/armada-38x.dtsi b/arch/arm/dts/armada-38x.dtsi index 061bd7852081..7d76df3f9ce7 100644 --- a/arch/arm/dts/armada-38x.dtsi +++ b/arch/arm/dts/armada-38x.dtsi @@ -295,6 +295,7 @@ reg-names = "gpio", "pwm"; ngpios = <32>; gpio-controller;
gpio-ranges = <&pinctrl 0 0 32>; #gpio-cells = <2>; #pwm-cells = <2>; interrupt-controller;
@@ -313,6 +314,7 @@ reg-names = "gpio", "pwm"; ngpios = <28>; gpio-controller;
gpio-ranges = <&pinctrl 0 32 28>; #gpio-cells = <2>; #pwm-cells = <2>; interrupt-controller;
Viele Grüße, Stefan Roese

This change allows to use pinctrl_gpio_request() function as a direct pointer for dm_gpio_ops's .request callback.
Signed-off-by: Pali Rohár pali@kernel.org --- drivers/pinctrl/pinctrl-uclass.c | 3 ++- include/dm/pinctrl.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 38ce2b5e0ad9..ce2d5ddf6d92 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -222,9 +222,10 @@ pinctrl_gpio_get_pinctrl_and_offset(struct udevice *dev, unsigned offset, * * @dev: GPIO peripheral device * @offset: the GPIO pin offset from the GPIO controller + * @label: the GPIO pin label * @return: 0 on success, or negative error code on failure */ -int pinctrl_gpio_request(struct udevice *dev, unsigned offset) +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label) { const struct pinctrl_ops *ops; struct udevice *pctldev; diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index 5436dc4a9a71..e3e50afeaff0 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -611,10 +611,11 @@ int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf, * pinctrl_gpio_request() - Request a single pin to be used as GPIO * @dev: GPIO peripheral device * @offset: GPIO pin offset from the GPIO controller + * @label: GPIO label * * Return: 0 on success, or negative error code on failure */ -int pinctrl_gpio_request(struct udevice *dev, unsigned offset); +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label);
/** * pinctrl_gpio_free() - Free a single pin used as GPIO

On 25.07.22 13:56, Pali Rohár wrote:
This change allows to use pinctrl_gpio_request() function as a direct pointer for dm_gpio_ops's .request callback.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
drivers/pinctrl/pinctrl-uclass.c | 3 ++- include/dm/pinctrl.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 38ce2b5e0ad9..ce2d5ddf6d92 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -222,9 +222,10 @@ pinctrl_gpio_get_pinctrl_and_offset(struct udevice *dev, unsigned offset,
- @dev: GPIO peripheral device
- @offset: the GPIO pin offset from the GPIO controller
*/
- @label: the GPIO pin label
- @return: 0 on success, or negative error code on failure
-int pinctrl_gpio_request(struct udevice *dev, unsigned offset) +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label) { const struct pinctrl_ops *ops; struct udevice *pctldev; diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index 5436dc4a9a71..e3e50afeaff0 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -611,10 +611,11 @@ int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf,
- pinctrl_gpio_request() - Request a single pin to be used as GPIO
- @dev: GPIO peripheral device
- @offset: GPIO pin offset from the GPIO controller
*/
- @label: GPIO label
- Return: 0 on success, or negative error code on failure
-int pinctrl_gpio_request(struct udevice *dev, unsigned offset); +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label);
/**
- pinctrl_gpio_free() - Free a single pin used as GPIO
Viele Grüße, Stefan Roese

Hi Pali.
On 25.07.22 13:56, Pali Rohár wrote:
This change allows to use pinctrl_gpio_request() function as a direct pointer for dm_gpio_ops's .request callback.
Signed-off-by: Pali Rohár pali@kernel.org
Running a CI build on Azure, I see these errors at least for this target:
rzg2_beacon
drivers/gpio/gpio-rcar.c: In function 'rcar_gpio_request': drivers/gpio/gpio-rcar.c:136:16: error: too few arguments to function 'pinctrl_gpio_request' 136 | return pinctrl_gpio_request(dev, offset); | ^~~~~~~~~~~~~~~~~~~~ In file included from drivers/gpio/gpio-rcar.c:12: include/dm/pinctrl.h:618:5: note: declared here 618 | int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label); | ^~~~~~~~~~~~~~~~~~~~ drivers/gpio/gpio-rcar.c:137:1: warning: control reaches end of non-void function [-Wreturn-type] 137 | } | ^
Please run this (and if possible all more complex) patchset via some world build / CI.
Thanks, Stefan
drivers/pinctrl/pinctrl-uclass.c | 3 ++- include/dm/pinctrl.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 38ce2b5e0ad9..ce2d5ddf6d92 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -222,9 +222,10 @@ pinctrl_gpio_get_pinctrl_and_offset(struct udevice *dev, unsigned offset,
- @dev: GPIO peripheral device
- @offset: the GPIO pin offset from the GPIO controller
*/
- @label: the GPIO pin label
- @return: 0 on success, or negative error code on failure
-int pinctrl_gpio_request(struct udevice *dev, unsigned offset) +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label) { const struct pinctrl_ops *ops; struct udevice *pctldev; diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index 5436dc4a9a71..e3e50afeaff0 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -611,10 +611,11 @@ int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf,
- pinctrl_gpio_request() - Request a single pin to be used as GPIO
- @dev: GPIO peripheral device
- @offset: GPIO pin offset from the GPIO controller
*/
- @label: GPIO label
- Return: 0 on success, or negative error code on failure
-int pinctrl_gpio_request(struct udevice *dev, unsigned offset); +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label);
/**
- pinctrl_gpio_free() - Free a single pin used as GPIO
Viele Grüße, Stefan Roese

On Thursday 28 July 2022 15:07:51 Stefan Roese wrote:
Hi Pali.
On 25.07.22 13:56, Pali Rohár wrote:
This change allows to use pinctrl_gpio_request() function as a direct pointer for dm_gpio_ops's .request callback.
Signed-off-by: Pali Rohár pali@kernel.org
Running a CI build on Azure, I see these errors at least for this target:
rzg2_beacon
drivers/gpio/gpio-rcar.c: In function 'rcar_gpio_request': drivers/gpio/gpio-rcar.c:136:16: error: too few arguments to function 'pinctrl_gpio_request' 136 | return pinctrl_gpio_request(dev, offset); | ^~~~~~~~~~~~~~~~~~~~ In file included from drivers/gpio/gpio-rcar.c:12: include/dm/pinctrl.h:618:5: note: declared here 618 | int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label); | ^~~~~~~~~~~~~~~~~~~~ drivers/gpio/gpio-rcar.c:137:1: warning: control reaches end of non-void function [-Wreturn-type] 137 | } | ^
Ou... I think that this fixup should fix this error:
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 76f47027a3ea..138801850d3e 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -133,7 +133,7 @@ static int rcar_gpio_get_function(struct udevice *dev, unsigned offset) static int rcar_gpio_request(struct udevice *dev, unsigned offset, const char *label) { - return pinctrl_gpio_request(dev, offset); + return pinctrl_gpio_request(dev, offset, label); }
static int rcar_gpio_free(struct udevice *dev, unsigned offset)
Please run this (and if possible all more complex) patchset via some world build / CI.
I opened pull request on github, it should run CI tests: https://github.com/u-boot/u-boot/pull/202
I included there also above fixup.
Thanks, Stefan
drivers/pinctrl/pinctrl-uclass.c | 3 ++- include/dm/pinctrl.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 38ce2b5e0ad9..ce2d5ddf6d92 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -222,9 +222,10 @@ pinctrl_gpio_get_pinctrl_and_offset(struct udevice *dev, unsigned offset,
- @dev: GPIO peripheral device
- @offset: the GPIO pin offset from the GPIO controller
*/
- @label: the GPIO pin label
- @return: 0 on success, or negative error code on failure
-int pinctrl_gpio_request(struct udevice *dev, unsigned offset) +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label) { const struct pinctrl_ops *ops; struct udevice *pctldev; diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index 5436dc4a9a71..e3e50afeaff0 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -611,10 +611,11 @@ int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf,
- pinctrl_gpio_request() - Request a single pin to be used as GPIO
- @dev: GPIO peripheral device
- @offset: GPIO pin offset from the GPIO controller
*/
- @label: GPIO label
- Return: 0 on success, or negative error code on failure
-int pinctrl_gpio_request(struct udevice *dev, unsigned offset); +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label); /**
- pinctrl_gpio_free() - Free a single pin used as GPIO
Viele Grüße, Stefan Roese
-- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr@denx.de

On 28.07.22 15:15, Pali Rohár wrote:
On Thursday 28 July 2022 15:07:51 Stefan Roese wrote:
Hi Pali.
On 25.07.22 13:56, Pali Rohár wrote:
This change allows to use pinctrl_gpio_request() function as a direct pointer for dm_gpio_ops's .request callback.
Signed-off-by: Pali Rohár pali@kernel.org
Running a CI build on Azure, I see these errors at least for this target:
rzg2_beacon
drivers/gpio/gpio-rcar.c: In function 'rcar_gpio_request': drivers/gpio/gpio-rcar.c:136:16: error: too few arguments to function 'pinctrl_gpio_request' 136 | return pinctrl_gpio_request(dev, offset); | ^~~~~~~~~~~~~~~~~~~~ In file included from drivers/gpio/gpio-rcar.c:12: include/dm/pinctrl.h:618:5: note: declared here 618 | int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label); | ^~~~~~~~~~~~~~~~~~~~ drivers/gpio/gpio-rcar.c:137:1: warning: control reaches end of non-void function [-Wreturn-type] 137 | } | ^
Ou... I think that this fixup should fix this error:
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 76f47027a3ea..138801850d3e 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -133,7 +133,7 @@ static int rcar_gpio_get_function(struct udevice *dev, unsigned offset) static int rcar_gpio_request(struct udevice *dev, unsigned offset, const char *label) {
- return pinctrl_gpio_request(dev, offset);
return pinctrl_gpio_request(dev, offset, label); }
static int rcar_gpio_free(struct udevice *dev, unsigned offset)
Please run this (and if possible all more complex) patchset via some world build / CI.
I opened pull request on github, it should run CI tests: https://github.com/u-boot/u-boot/pull/202
I included there also above fixup.
Thanks. Let's see, if this now runs fine.
Thanks, Stefan
Thanks, Stefan
drivers/pinctrl/pinctrl-uclass.c | 3 ++- include/dm/pinctrl.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 38ce2b5e0ad9..ce2d5ddf6d92 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -222,9 +222,10 @@ pinctrl_gpio_get_pinctrl_and_offset(struct udevice *dev, unsigned offset, * * @dev: GPIO peripheral device * @offset: the GPIO pin offset from the GPIO controller
- @label: the GPIO pin label
*/
- @return: 0 on success, or negative error code on failure
-int pinctrl_gpio_request(struct udevice *dev, unsigned offset) +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label) { const struct pinctrl_ops *ops; struct udevice *pctldev; diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index 5436dc4a9a71..e3e50afeaff0 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -611,10 +611,11 @@ int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf, * pinctrl_gpio_request() - Request a single pin to be used as GPIO * @dev: GPIO peripheral device * @offset: GPIO pin offset from the GPIO controller
- @label: GPIO label
*/
- Return: 0 on success, or negative error code on failure
-int pinctrl_gpio_request(struct udevice *dev, unsigned offset); +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label); /** * pinctrl_gpio_free() - Free a single pin used as GPIO
Viele Grüße, Stefan Roese
-- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr@denx.de
Viele Grüße, Stefan Roese

On Thursday 28 July 2022 15:18:46 Stefan Roese wrote:
On 28.07.22 15:15, Pali Rohár wrote:
On Thursday 28 July 2022 15:07:51 Stefan Roese wrote:
Hi Pali.
On 25.07.22 13:56, Pali Rohár wrote:
This change allows to use pinctrl_gpio_request() function as a direct pointer for dm_gpio_ops's .request callback.
Signed-off-by: Pali Rohár pali@kernel.org
Running a CI build on Azure, I see these errors at least for this target:
rzg2_beacon
drivers/gpio/gpio-rcar.c: In function 'rcar_gpio_request': drivers/gpio/gpio-rcar.c:136:16: error: too few arguments to function 'pinctrl_gpio_request' 136 | return pinctrl_gpio_request(dev, offset); | ^~~~~~~~~~~~~~~~~~~~ In file included from drivers/gpio/gpio-rcar.c:12: include/dm/pinctrl.h:618:5: note: declared here 618 | int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label); | ^~~~~~~~~~~~~~~~~~~~ drivers/gpio/gpio-rcar.c:137:1: warning: control reaches end of non-void function [-Wreturn-type] 137 | } | ^
Ou... I think that this fixup should fix this error:
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 76f47027a3ea..138801850d3e 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -133,7 +133,7 @@ static int rcar_gpio_get_function(struct udevice *dev, unsigned offset) static int rcar_gpio_request(struct udevice *dev, unsigned offset, const char *label) {
- return pinctrl_gpio_request(dev, offset);
- return pinctrl_gpio_request(dev, offset, label); } static int rcar_gpio_free(struct udevice *dev, unsigned offset)
Please run this (and if possible all more complex) patchset via some world build / CI.
I opened pull request on github, it should run CI tests: https://github.com/u-boot/u-boot/pull/202
I included there also above fixup.
Thanks. Let's see, if this now runs fine.
Tests passed!
Thanks, Stefan
Thanks, Stefan
drivers/pinctrl/pinctrl-uclass.c | 3 ++- include/dm/pinctrl.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 38ce2b5e0ad9..ce2d5ddf6d92 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -222,9 +222,10 @@ pinctrl_gpio_get_pinctrl_and_offset(struct udevice *dev, unsigned offset, * * @dev: GPIO peripheral device * @offset: the GPIO pin offset from the GPIO controller
- @label: the GPIO pin label
*/
- @return: 0 on success, or negative error code on failure
-int pinctrl_gpio_request(struct udevice *dev, unsigned offset) +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label) { const struct pinctrl_ops *ops; struct udevice *pctldev; diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index 5436dc4a9a71..e3e50afeaff0 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -611,10 +611,11 @@ int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf, * pinctrl_gpio_request() - Request a single pin to be used as GPIO * @dev: GPIO peripheral device * @offset: GPIO pin offset from the GPIO controller
- @label: GPIO label
*/
- Return: 0 on success, or negative error code on failure
-int pinctrl_gpio_request(struct udevice *dev, unsigned offset); +int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label); /** * pinctrl_gpio_free() - Free a single pin used as GPIO
Viele Grüße, Stefan Roese
-- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr@denx.de
Viele Grüße, Stefan Roese
-- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr@denx.de

To use particular pin GPIO, it needs to be first switched to GPIO by pinctrl. Use pinctrl_gpio_request() and pinctrl_gpio_free() for this purpose.
Signed-off-by: Pali Rohár pali@kernel.org --- drivers/gpio/mvebu_gpio.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c index 4c1c68ee19ed..888ccfe4d13e 100644 --- a/drivers/gpio/mvebu_gpio.c +++ b/drivers/gpio/mvebu_gpio.c @@ -5,6 +5,7 @@
#include <common.h> #include <dm.h> +#include <dm/pinctrl.h> #include <asm/gpio.h> #include <asm/io.h> #include <errno.h> @@ -99,6 +100,10 @@ static int mvebu_gpio_probe(struct udevice *dev) }
static const struct dm_gpio_ops mvebu_gpio_ops = { +#if CONFIG_IS_ENABLED(PINCTRL_ARMADA_38X) + .request = pinctrl_gpio_request, + .rfree = pinctrl_gpio_free, +#endif .direction_input = mvebu_gpio_direction_input, .direction_output = mvebu_gpio_direction_output, .get_function = mvebu_gpio_get_function,

On 25.07.22 13:56, Pali Rohár wrote:
To use particular pin GPIO, it needs to be first switched to GPIO by pinctrl. Use pinctrl_gpio_request() and pinctrl_gpio_free() for this purpose.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
drivers/gpio/mvebu_gpio.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c index 4c1c68ee19ed..888ccfe4d13e 100644 --- a/drivers/gpio/mvebu_gpio.c +++ b/drivers/gpio/mvebu_gpio.c @@ -5,6 +5,7 @@
#include <common.h> #include <dm.h> +#include <dm/pinctrl.h> #include <asm/gpio.h> #include <asm/io.h> #include <errno.h> @@ -99,6 +100,10 @@ static int mvebu_gpio_probe(struct udevice *dev) }
static const struct dm_gpio_ops mvebu_gpio_ops = { +#if CONFIG_IS_ENABLED(PINCTRL_ARMADA_38X)
- .request = pinctrl_gpio_request,
- .rfree = pinctrl_gpio_free,
+#endif .direction_input = mvebu_gpio_direction_input, .direction_output = mvebu_gpio_direction_output, .get_function = mvebu_gpio_get_function,
Viele Grüße, Stefan Roese

Device tree property "ngpios" contains number of gpios. Use it when available.
Signed-off-by: Pali Rohár pali@kernel.org --- drivers/gpio/mvebu_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c index 888ccfe4d13e..55ed685f70f8 100644 --- a/drivers/gpio/mvebu_gpio.c +++ b/drivers/gpio/mvebu_gpio.c @@ -92,7 +92,7 @@ static int mvebu_gpio_probe(struct udevice *dev) struct mvebu_gpio_priv *priv = dev_get_priv(dev);
priv->regs = dev_read_addr_ptr(dev); - uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK; + uc_priv->gpio_count = dev_read_u32_default(dev, "ngpios", MVEBU_GPIOS_PER_BANK); priv->name[0] = 'A' + dev_seq(dev); uc_priv->bank_name = priv->name;

On 25.07.22 13:56, Pali Rohár wrote:
Device tree property "ngpios" contains number of gpios. Use it when available.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
drivers/gpio/mvebu_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c index 888ccfe4d13e..55ed685f70f8 100644 --- a/drivers/gpio/mvebu_gpio.c +++ b/drivers/gpio/mvebu_gpio.c @@ -92,7 +92,7 @@ static int mvebu_gpio_probe(struct udevice *dev) struct mvebu_gpio_priv *priv = dev_get_priv(dev);
priv->regs = dev_read_addr_ptr(dev);
- uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK;
- uc_priv->gpio_count = dev_read_u32_default(dev, "ngpios", MVEBU_GPIOS_PER_BANK); priv->name[0] = 'A' + dev_seq(dev); uc_priv->bank_name = priv->name;
Viele Grüße, Stefan Roese

Currently bank name is just one alphabetical letter. Change it to mvebu and number.
Signed-off-by: Pali Rohár pali@kernel.org --- drivers/gpio/mvebu_gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c index 55ed685f70f8..f706a6dfa4fe 100644 --- a/drivers/gpio/mvebu_gpio.c +++ b/drivers/gpio/mvebu_gpio.c @@ -23,7 +23,7 @@ struct mvebu_gpio_regs {
struct mvebu_gpio_priv { struct mvebu_gpio_regs *regs; - char name[2]; + char name[sizeof("mvebuX_")]; };
static int mvebu_gpio_direction_input(struct udevice *dev, unsigned int gpio) @@ -93,7 +93,7 @@ static int mvebu_gpio_probe(struct udevice *dev)
priv->regs = dev_read_addr_ptr(dev); uc_priv->gpio_count = dev_read_u32_default(dev, "ngpios", MVEBU_GPIOS_PER_BANK); - priv->name[0] = 'A' + dev_seq(dev); + sprintf(priv->name, "mvebu%d_", dev_seq(dev)); uc_priv->bank_name = priv->name;
return 0;

On 25.07.22 13:56, Pali Rohár wrote:
Currently bank name is just one alphabetical letter. Change it to mvebu and number.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
drivers/gpio/mvebu_gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c index 55ed685f70f8..f706a6dfa4fe 100644 --- a/drivers/gpio/mvebu_gpio.c +++ b/drivers/gpio/mvebu_gpio.c @@ -23,7 +23,7 @@ struct mvebu_gpio_regs {
struct mvebu_gpio_priv { struct mvebu_gpio_regs *regs;
- char name[2];
char name[sizeof("mvebuX_")]; };
static int mvebu_gpio_direction_input(struct udevice *dev, unsigned int gpio)
@@ -93,7 +93,7 @@ static int mvebu_gpio_probe(struct udevice *dev)
priv->regs = dev_read_addr_ptr(dev); uc_priv->gpio_count = dev_read_u32_default(dev, "ngpios", MVEBU_GPIOS_PER_BANK);
- priv->name[0] = 'A' + dev_seq(dev);
sprintf(priv->name, "mvebu%d_", dev_seq(dev)); uc_priv->bank_name = priv->name;
return 0;
Viele Grüße, Stefan Roese

Signed-off-by: Pali Rohár pali@kernel.org --- configs/turris_omnia_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index e2a0449b487b..9b38ba93f767 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -72,7 +72,6 @@ CONFIG_NETCONSOLE=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_AHCI_PCI=y CONFIG_AHCI_MVEBU=y -# CONFIG_MVEBU_GPIO is not set CONFIG_DM_PCA953X=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_MV=y @@ -93,6 +92,9 @@ CONFIG_PCI=y CONFIG_PCI_MVEBU=y CONFIG_DM_RTC=y CONFIG_RTC_ARMADA38X=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_FULL=y +CONFIG_PINCTRL_ARMADA_38X=y CONFIG_SCSI=y CONFIG_SPL_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_SHIFT=2

On 25.07.22 13:56, Pali Rohár wrote:
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
configs/turris_omnia_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index e2a0449b487b..9b38ba93f767 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -72,7 +72,6 @@ CONFIG_NETCONSOLE=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_AHCI_PCI=y CONFIG_AHCI_MVEBU=y -# CONFIG_MVEBU_GPIO is not set CONFIG_DM_PCA953X=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_MV=y @@ -93,6 +92,9 @@ CONFIG_PCI=y CONFIG_PCI_MVEBU=y CONFIG_DM_RTC=y CONFIG_RTC_ARMADA38X=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_FULL=y +CONFIG_PINCTRL_ARMADA_38X=y CONFIG_SCSI=y CONFIG_SPL_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_SHIFT=2
Viele Grüße, Stefan Roese

Hi Pali,
I noticed that PINCTRL_FULL is default to Y already in Kconfig. Is it normal practice to include it in the defconfig anyway?
./drivers/pinctrl/Kconfig
config PINCTRL_FULL bool "Support full pin controllers" depends on PINCTRL && OF_CONTROL default y
All the best, Tony
On Wed, Jul 27, 2022 at 11:29 PM Stefan Roese sr@denx.de wrote:
On 25.07.22 13:56, Pali Rohár wrote:
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
configs/turris_omnia_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index e2a0449b487b..9b38ba93f767 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -72,7 +72,6 @@ CONFIG_NETCONSOLE=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_AHCI_PCI=y CONFIG_AHCI_MVEBU=y -# CONFIG_MVEBU_GPIO is not set CONFIG_DM_PCA953X=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_MV=y @@ -93,6 +92,9 @@ CONFIG_PCI=y CONFIG_PCI_MVEBU=y CONFIG_DM_RTC=y CONFIG_RTC_ARMADA38X=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_FULL=y +CONFIG_PINCTRL_ARMADA_38X=y CONFIG_SCSI=y CONFIG_SPL_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_SHIFT=2
Viele Grüße, Stefan Roese
-- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr@denx.de

On Thursday 28 July 2022 14:42:35 Tony Dinh wrote:
Hi Pali,
I noticed that PINCTRL_FULL is default to Y already in Kconfig. Is it normal practice to include it in the defconfig anyway?
./drivers/pinctrl/Kconfig
config PINCTRL_FULL bool "Support full pin controllers" depends on PINCTRL && OF_CONTROL default y
Ou, I probably forgot to run make saveconfig. In this case it is not needed and would be automatically removed after running move config (which Tom runs periodically for all boards).
Stefan, should I resend this patch? Or do let it as is?
All the best, Tony
On Wed, Jul 27, 2022 at 11:29 PM Stefan Roese sr@denx.de wrote:
On 25.07.22 13:56, Pali Rohár wrote:
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
configs/turris_omnia_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index e2a0449b487b..9b38ba93f767 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -72,7 +72,6 @@ CONFIG_NETCONSOLE=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_AHCI_PCI=y CONFIG_AHCI_MVEBU=y -# CONFIG_MVEBU_GPIO is not set CONFIG_DM_PCA953X=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_MV=y @@ -93,6 +92,9 @@ CONFIG_PCI=y CONFIG_PCI_MVEBU=y CONFIG_DM_RTC=y CONFIG_RTC_ARMADA38X=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_FULL=y +CONFIG_PINCTRL_ARMADA_38X=y CONFIG_SCSI=y CONFIG_SPL_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_SHIFT=2
Viele Grüße, Stefan Roese
-- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr@denx.de

On 29.07.22 09:38, Pali Rohár wrote:
On Thursday 28 July 2022 14:42:35 Tony Dinh wrote:
Hi Pali,
I noticed that PINCTRL_FULL is default to Y already in Kconfig. Is it normal practice to include it in the defconfig anyway?
./drivers/pinctrl/Kconfig
config PINCTRL_FULL bool "Support full pin controllers" depends on PINCTRL && OF_CONTROL default y
Ou, I probably forgot to run make saveconfig. In this case it is not needed and would be automatically removed after running move config (which Tom runs periodically for all boards).
Stefan, should I resend this patch? Or do let it as is?
No need. I'll handle this by running savedefconfig and squashing it.
Thanks, Stefan
All the best, Tony
On Wed, Jul 27, 2022 at 11:29 PM Stefan Roese sr@denx.de wrote:
On 25.07.22 13:56, Pali Rohár wrote:
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
configs/turris_omnia_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index e2a0449b487b..9b38ba93f767 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -72,7 +72,6 @@ CONFIG_NETCONSOLE=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_AHCI_PCI=y CONFIG_AHCI_MVEBU=y -# CONFIG_MVEBU_GPIO is not set CONFIG_DM_PCA953X=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_MV=y @@ -93,6 +92,9 @@ CONFIG_PCI=y CONFIG_PCI_MVEBU=y CONFIG_DM_RTC=y CONFIG_RTC_ARMADA38X=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_FULL=y +CONFIG_PINCTRL_ARMADA_38X=y CONFIG_SCSI=y CONFIG_SPL_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_SHIFT=2
Viele Grüße, Stefan Roese
-- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr@denx.de
Viele Grüße, Stefan Roese

Hi Pali,
After correcting my MPP configuration in board_early_init, I ran the test again with this patch series. Everything works (upon u-boot startup) : Ethernet, SPI, SATA and USB.
Board: Synology DS116, Armada 385 (out-of-tree u-boot) Tested-by: Tony Dinh mibodhi@gmail.com
Thanks, Tony
On Mon, Jul 25, 2022 at 4:56 AM Pali Rohár pali@kernel.org wrote:
This patch series add support for configuring pin muxing on Armada 38x via device tree properties used by Linux kernel. It extends also mvebu gpio driver to properly set pin function to gpio prior assigning pins and enable gpio and pinmux support on Turris Omnia.
Pali Rohár (8): pinctrl: Add new function pinctrl_generic_set_state_prefix() mvebu: pinctrl: Add Armada 38x driver arm: mvebu: Add gpio-ranges into Armada 38x device tree file pinctrl: Add third argument label for pinctrl_gpio_request() function gpio: mvebu_gpio: Add .request and .rfree methods for Armada 38x gpio: mvebu_gpio: Read number of gpios from DT gpio: mvebu_gpio: Set bank name to mvebu%d arm: mvebu: turris_omnia: Enable a38x pinctrl and gpio support
arch/arm/dts/armada-38x.dtsi | 2 + configs/turris_omnia_defconfig | 4 +- drivers/gpio/mvebu_gpio.c | 11 +- drivers/pinctrl/mvebu/Kconfig | 7 + drivers/pinctrl/mvebu/Makefile | 1 + drivers/pinctrl/mvebu/pinctrl-armada-38x.c | 589 +++++++++++++++++++++ drivers/pinctrl/pinctrl-generic.c | 100 +++- drivers/pinctrl/pinctrl-uclass.c | 3 +- include/dm/pinctrl.h | 5 +- 9 files changed, 699 insertions(+), 23 deletions(-) create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-38x.c
-- 2.20.1

On 25.07.22 13:56, Pali Rohár wrote:
This patch series add support for configuring pin muxing on Armada 38x via device tree properties used by Linux kernel. It extends also mvebu gpio driver to properly set pin function to gpio prior assigning pins and enable gpio and pinmux support on Turris Omnia.
Pali Rohár (8): pinctrl: Add new function pinctrl_generic_set_state_prefix() mvebu: pinctrl: Add Armada 38x driver arm: mvebu: Add gpio-ranges into Armada 38x device tree file pinctrl: Add third argument label for pinctrl_gpio_request() function gpio: mvebu_gpio: Add .request and .rfree methods for Armada 38x gpio: mvebu_gpio: Read number of gpios from DT gpio: mvebu_gpio: Set bank name to mvebu%d arm: mvebu: turris_omnia: Enable a38x pinctrl and gpio support
arch/arm/dts/armada-38x.dtsi | 2 + configs/turris_omnia_defconfig | 4 +- drivers/gpio/mvebu_gpio.c | 11 +- drivers/pinctrl/mvebu/Kconfig | 7 + drivers/pinctrl/mvebu/Makefile | 1 + drivers/pinctrl/mvebu/pinctrl-armada-38x.c | 589 +++++++++++++++++++++ drivers/pinctrl/pinctrl-generic.c | 100 +++- drivers/pinctrl/pinctrl-uclass.c | 3 +- include/dm/pinctrl.h | 5 +- 9 files changed, 699 insertions(+), 23 deletions(-) create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-38x.c
Applied to u-boot-marvell/master
Thanks, Stefan
participants (3)
-
Pali Rohár
-
Stefan Roese
-
Tony Dinh