From 92c4a95ec7986a31f37dbf540dd8fda5927ac659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 13:56:08 +0200 Subject: [PATCH 01/26] pinctrl: Add new function pinctrl_generic_set_state_prefix() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Stefan Roese --- drivers/pinctrl/pinctrl-generic.c | 126 +++++++++++++++++++++++------- include/dm/pinctrl.h | 2 + 2 files changed, 98 insertions(+), 30 deletions(-) diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c index 3c8e24088c..ec21d4ff83 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,29 @@ 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; + } + + return 0; +} + +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, 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, prefix); if (ret) return ret; } @@ -401,20 +482,5 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev, int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config) { - struct udevice *child; - int ret; - - ret = pinctrl_generic_set_state_subnode(dev, config); - 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); - if (ret) - return ret; - } - - return 0; + return pinctrl_generic_set_state_prefix(dev, config, NULL); } diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index a09b242fd9..5436dc4a9a 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) From 35c50a709e0ecf62cb254c6496f77c186e471046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 13:56:09 +0200 Subject: [PATCH 02/26] mvebu: pinctrl: Add Armada 38x driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Stefan Roese --- 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 07d4f3e216..574fb4dfb0 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 c2df96bf5b..15303d83a7 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 0000000000..252151f3e5 --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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, +}; From 319b62880cd21c0187081ef5c6b27d888bcbbbe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 13:56:10 +0200 Subject: [PATCH 03/26] arm: mvebu: Add gpio-ranges into Armada 38x device tree file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Stefan Roese --- 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 061bd78520..7d76df3f9c 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; From a1de1035b228f634241c80c60fcb39daae6116f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 13:56:11 +0200 Subject: [PATCH 04/26] pinctrl: Add third argument label for pinctrl_gpio_request() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Stefan Roese --- drivers/gpio/gpio-rcar.c | 2 +- drivers/pinctrl/pinctrl-uclass.c | 3 ++- include/dm/pinctrl.h | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 76f47027a3..138801850d 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) diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 38ce2b5e0a..ce2d5ddf6d 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 5436dc4a9a..e3e50afeaf 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 From 7d8bb89d569b18899011c44f8129a6b95a1424a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 13:56:12 +0200 Subject: [PATCH 05/26] gpio: mvebu_gpio: Add .request and .rfree methods for Armada 38x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Stefan Roese --- 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 4c1c68ee19..888ccfe4d1 100644 --- a/drivers/gpio/mvebu_gpio.c +++ b/drivers/gpio/mvebu_gpio.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -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, From dc986c600ff738f35f6c29f8901bc40250d36734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 13:56:13 +0200 Subject: [PATCH 06/26] gpio: mvebu_gpio: Read number of gpios from DT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Device tree property "ngpios" contains number of gpios. Use it when available. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- 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 888ccfe4d1..55ed685f70 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; From da76996a1a09de7522eb8af192730425a1f7842a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 13:56:14 +0200 Subject: [PATCH 07/26] gpio: mvebu_gpio: Set bank name to mvebu%d MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently bank name is just one alphabetical letter. Change it to mvebu and number. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- 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 55ed685f70..f706a6dfa4 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; From cab406edab1500770f2fadd2a06ed2422b6986f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 13:56:15 +0200 Subject: [PATCH 08/26] arm: mvebu: turris_omnia: Enable a38x pinctrl and gpio support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- configs/turris_omnia_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index 66c4959180..ff16825fb4 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -80,7 +80,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 @@ -99,6 +98,8 @@ CONFIG_MVMDIO=y CONFIG_NVME_PCI=y CONFIG_PCI=y CONFIG_PCI_MVEBU=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_ARMADA_38X=y CONFIG_DM_RTC=y CONFIG_RTC_ARMADA38X=y CONFIG_SCSI=y From bd913a7233f0781e601ce0756a5783dede7f872a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 14:08:58 +0200 Subject: [PATCH 09/26] arm64: a37xx: pinctrl: Remove unused grp->pins fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit grp->pins is just filled and never used. Remove it. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index e76ef153e6..610535fa23 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -65,7 +65,6 @@ DECLARE_GLOBAL_DATA_PTR; * belonging to the group * @npins: Number of pins included in the second optional range * @funcs: A list of pinmux functions that can be selected for this group. - * @pins: List of the pins included in the group */ struct armada_37xx_pin_group { const char *name; @@ -76,7 +75,6 @@ struct armada_37xx_pin_group { unsigned int extra_pin; unsigned int extra_npins; const char *funcs[NB_FUNCS]; - unsigned int *pins; }; struct armada_37xx_pin_data { @@ -354,19 +352,7 @@ static int armada_37xx_fill_group(struct armada_37xx_pinctrl *info) for (n = 0; n < info->ngroups; n++) { struct armada_37xx_pin_group *grp = &info->groups[n]; - int i, j, f; - - grp->pins = devm_kzalloc(info->dev, - (grp->npins + grp->extra_npins) * - sizeof(*grp->pins), GFP_KERNEL); - if (!grp->pins) - return -ENOMEM; - - for (i = 0; i < grp->npins; i++) - grp->pins[i] = grp->start_pin + i; - - for (j = 0; j < grp->extra_npins; j++) - grp->pins[i+j] = grp->extra_pin + j; + int f; for (f = 0; (f < NB_FUNCS) && grp->funcs[f]; f++) { int ret; From 33893e5278734343beda2a6be7dd0b7644da482e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 14:08:59 +0200 Subject: [PATCH 10/26] arm64: a37xx: pinctrl: Remove duplicate info->groups and info->ngroups fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They are available in pin_data structure. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index 610535fa23..e1cde53a02 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -95,8 +95,6 @@ struct armada_37xx_pinctrl { const struct armada_37xx_pin_data *data; struct udevice *dev; struct pinctrl_dev *pctl_dev; - struct armada_37xx_pin_group *groups; - unsigned int ngroups; struct armada_37xx_pmx_func *funcs; unsigned int nfuncs; }; @@ -235,7 +233,7 @@ static int armada_37xx_pmx_get_groups_count(struct udevice *dev) { struct armada_37xx_pinctrl *info = dev_get_priv(dev); - return info->ngroups; + return info->data->ngroups; } static const char *armada_37xx_pmx_dummy_name = "_dummy"; @@ -245,10 +243,10 @@ static const char *armada_37xx_pmx_get_group_name(struct udevice *dev, { struct armada_37xx_pinctrl *info = dev_get_priv(dev); - if (!info->groups[selector].name) + if (!info->data->groups[selector].name) return armada_37xx_pmx_dummy_name; - return info->groups[selector].name; + return info->data->groups[selector].name; } static int armada_37xx_pmx_get_funcs_count(struct udevice *dev) @@ -295,7 +293,7 @@ static int armada_37xx_pmx_group_set(struct udevice *dev, unsigned func_selector) { struct armada_37xx_pinctrl *info = dev_get_priv(dev); - struct armada_37xx_pin_group *grp = &info->groups[group_selector]; + struct armada_37xx_pin_group *grp = &info->data->groups[group_selector]; const char *name = info->funcs[func_selector].name; return armada_37xx_pmx_set_by_name(dev, name, grp); @@ -350,8 +348,8 @@ static int armada_37xx_fill_group(struct armada_37xx_pinctrl *info) { int n, num = 0, funcsize = info->data->nr_pins; - for (n = 0; n < info->ngroups; n++) { - struct armada_37xx_pin_group *grp = &info->groups[n]; + for (n = 0; n < info->data->ngroups; n++) { + struct armada_37xx_pin_group *grp = &info->data->groups[n]; int f; for (f = 0; (f < NB_FUNCS) && grp->funcs[f]; f++) { @@ -402,8 +400,8 @@ static int armada_37xx_fill_func(struct armada_37xx_pinctrl *info) groups = funcs[n].groups; - for (g = 0; g < info->ngroups; g++) { - struct armada_37xx_pin_group *gp = &info->groups[g]; + for (g = 0; g < info->data->ngroups; g++) { + struct armada_37xx_pin_group *gp = &info->data->groups[g]; int f; for (f = 0; (f < NB_FUNCS) && gp->funcs[f]; f++) { @@ -584,9 +582,6 @@ int armada_37xx_pinctrl_probe(struct udevice *dev) return -ENODEV; } - info->groups = pin_data->groups; - info->ngroups = pin_data->ngroups; - /* * we allocate functions for number of pins and hope there are * fewer unique functions than pins available From ffab049520a59e5ab1c2bf3fe606fdd6b46f8123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 14:09:00 +0200 Subject: [PATCH 11/26] arm64: a37xx: pinctrl: Mark all functions and structures as static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index e1cde53a02..e0445e3e2b 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -193,14 +193,14 @@ static struct armada_37xx_pin_group armada_37xx_sb_groups[] = { "mii", "mii_err"), }; -const struct armada_37xx_pin_data armada_37xx_pin_nb = { +static const struct armada_37xx_pin_data armada_37xx_pin_nb = { .nr_pins = 36, .name = "GPIO1", .groups = armada_37xx_nb_groups, .ngroups = ARRAY_SIZE(armada_37xx_nb_groups), }; -const struct armada_37xx_pin_data armada_37xx_pin_sb = { +static const struct armada_37xx_pin_data armada_37xx_pin_sb = { .nr_pins = 30, .name = "GPIO2", .groups = armada_37xx_sb_groups, @@ -558,7 +558,7 @@ static int armada_37xx_gpiochip_register(struct udevice *parent, return 0; } -const struct pinctrl_ops armada_37xx_pinctrl_ops = { +static const struct pinctrl_ops armada_37xx_pinctrl_ops = { .get_groups_count = armada_37xx_pmx_get_groups_count, .get_group_name = armada_37xx_pmx_get_group_name, .get_functions_count = armada_37xx_pmx_get_funcs_count, @@ -567,7 +567,7 @@ const struct pinctrl_ops armada_37xx_pinctrl_ops = { .set_state = pinctrl_generic_set_state, }; -int armada_37xx_pinctrl_probe(struct udevice *dev) +static int armada_37xx_pinctrl_probe(struct udevice *dev) { struct armada_37xx_pinctrl *info = dev_get_priv(dev); const struct armada_37xx_pin_data *pin_data; From 3d98071dbb1a204aaff5004b409abd4f7deb45e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 14:09:01 +0200 Subject: [PATCH 12/26] arm64: a37xx: pinctrl: Add missing pinmuxes into the list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index e0445e3e2b..d2abe67fe5 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -109,6 +109,16 @@ struct armada_37xx_pinctrl { .funcs = {_func1, _func2} \ } +#define PIN_GRP_GPIO_0(_name, _start, _nr) \ + { \ + .name = _name, \ + .start_pin = _start, \ + .npins = _nr, \ + .reg_mask = 0, \ + .val = {0}, \ + .funcs = {"gpio"} \ + } + #define PIN_GRP_GPIO(_name, _start, _nr, _mask, _func1) \ { \ .name = _name, \ @@ -166,6 +176,7 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = { "pwm", "led"), PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"), PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"), + PIN_GRP_GPIO_0("gpio1_5", 5, 1), PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"), PIN_GRP_GPIO("i2c1", 0, 2, BIT(10), "i2c"), PIN_GRP_GPIO("spi_cs1", 17, 1, BIT(12), "spi"), @@ -182,10 +193,13 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = { static struct armada_37xx_pin_group armada_37xx_sb_groups[] = { PIN_GRP_GPIO("usb32_drvvbus0", 0, 1, BIT(0), "drvbus"), PIN_GRP_GPIO("usb2_drvvbus1", 1, 1, BIT(1), "drvbus"), + PIN_GRP_GPIO_0("gpio2_2", 2, 1), PIN_GRP_GPIO("sdio_sb", 24, 6, BIT(2), "sdio"), PIN_GRP_GPIO("rgmii", 6, 12, BIT(3), "mii"), PIN_GRP_GPIO("smi", 18, 2, BIT(4), "smi"), - PIN_GRP_GPIO("pcie1", 3, 3, BIT(5) | BIT(9) | BIT(10), "pcie"), + PIN_GRP_GPIO("pcie1", 3, 1, BIT(5), "pcie"), /* this actually controls "pcie1_reset" */ + PIN_GRP_GPIO("pcie1_clkreq", 4, 1, BIT(9), "pcie"), + PIN_GRP_GPIO("pcie1_wakeup", 5, 1, BIT(10), "pcie"), PIN_GRP_GPIO("ptp", 20, 3, BIT(11) | BIT(12) | BIT(13), "ptp"), PIN_GRP("ptp_clk", 21, 1, BIT(6), "ptp", "mii"), PIN_GRP("ptp_trig", 22, 1, BIT(7), "ptp", "mii"), From 140ebcdb9a760a9ffb59cd9587bdf2ec82aa11fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 14:09:02 +0200 Subject: [PATCH 13/26] arm64: a37xx: pinctrl: Implement gpio_request_enable for gpio functionality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To automatically enable GPIO functionality of some MPP pin, it is required to implement .gpio_request_enable and .gpio_disable_free callbacks in pinctrl driver and set .request and .rfree callbacks in GPIO driver to pinctrl_gpio_request / pinctrl_gpio_free functions. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 50 +++++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index d2abe67fe5..74d915950a 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -280,12 +280,13 @@ static const char *armada_37xx_pmx_get_func_name(struct udevice *dev, static int armada_37xx_pmx_set_by_name(struct udevice *dev, const char *name, - struct armada_37xx_pin_group *grp) + struct armada_37xx_pin_group *grp, + bool warn_on_change) { struct armada_37xx_pinctrl *info = dev_get_priv(dev); unsigned int reg = SELECTION; unsigned int mask = grp->reg_mask; - int func, val; + int func, val, old_func; dev_dbg(info->dev, "enable function %s group %s\n", name, grp->name); @@ -297,6 +298,18 @@ static int armada_37xx_pmx_set_by_name(struct udevice *dev, val = grp->val[func]; + if (warn_on_change && val != (readl(info->base + reg) & mask)) { + for (old_func = 0; (old_func < NB_FUNCS) && grp->funcs[old_func]; old_func++) { + if (grp->val[old_func] == val) + break; + } + dev_warn(info->dev, "Warning: Changing MPPs %u-%u function from %s to %s...\n", + grp->start_pin, grp->start_pin + grp->npins - 1, + ((old_func < NB_FUNCS && grp->funcs[old_func]) ? + grp->funcs[old_func] : "unknown"), + name); + } + clrsetbits_le32(info->base + reg, mask, val); return 0; @@ -310,7 +323,34 @@ static int armada_37xx_pmx_group_set(struct udevice *dev, struct armada_37xx_pin_group *grp = &info->data->groups[group_selector]; const char *name = info->funcs[func_selector].name; - return armada_37xx_pmx_set_by_name(dev, name, grp); + return armada_37xx_pmx_set_by_name(dev, name, grp, false); +} + +static int armada_37xx_pmx_gpio_request_enable(struct udevice *dev, unsigned int selector) +{ + struct armada_37xx_pinctrl *info = dev_get_priv(dev); + int ret = -ENOTSUPP; + int n; + + /* Find all groups where is requested selector pin and set each group to gpio function */ + for (n = 0; n < info->data->ngroups; n++) { + struct armada_37xx_pin_group *grp = &info->data->groups[n]; + + if ((selector >= grp->start_pin && selector < grp->start_pin + grp->npins) || + (selector >= grp->extra_pin && selector < grp->extra_pin + grp->extra_npins)) { + ret = armada_37xx_pmx_set_by_name(dev, "gpio", grp, true); + if (ret) + return ret; + } + } + + return ret; +} + +static int armada_37xx_pmx_gpio_disable_free(struct udevice *dev, unsigned int selector) +{ + /* nothing to do */ + return 0; } /** @@ -520,6 +560,8 @@ static int armada_37xx_gpio_probe(struct udevice *dev) } static const struct dm_gpio_ops armada_37xx_gpio_ops = { + .request = pinctrl_gpio_request, + .rfree = pinctrl_gpio_free, .set_value = armada_37xx_gpio_set, .get_value = armada_37xx_gpio_get, .get_function = armada_37xx_gpio_get_direction, @@ -578,6 +620,8 @@ static const struct pinctrl_ops armada_37xx_pinctrl_ops = { .get_functions_count = armada_37xx_pmx_get_funcs_count, .get_function_name = armada_37xx_pmx_get_func_name, .pinmux_group_set = armada_37xx_pmx_group_set, + .gpio_request_enable = armada_37xx_pmx_gpio_request_enable, + .gpio_disable_free = armada_37xx_pmx_gpio_disable_free, .set_state = pinctrl_generic_set_state, }; From e34d8afd7219b7c2b8e7bf83225d09f79fd3f0b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 25 Jul 2022 14:09:03 +0200 Subject: [PATCH 14/26] arm64: a37xx: pinctrl: Implement get_pins_count, get_pin_name and get_pin_muxing functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These functions are required for 'pinmux status -a' command to print current configuration of each MPP pin. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 78 +++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index 74d915950a..bb7a76baed 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -353,6 +353,81 @@ static int armada_37xx_pmx_gpio_disable_free(struct udevice *dev, unsigned int s return 0; } +static int armada_37xx_pmx_get_pins_count(struct udevice *dev) +{ + struct armada_37xx_pinctrl *info = dev_get_priv(dev); + + return info->data->nr_pins; +} + +static const char *armada_37xx_pmx_get_pin_name(struct udevice *dev, unsigned int selector) +{ + struct armada_37xx_pinctrl *info = dev_get_priv(dev); + static char buf[sizeof("MPPx_XX")]; + + sprintf(buf, "MPP%c_%u", info->data->name[4], selector); + return buf; +} + +static int armada_37xx_pmx_get_pin_muxing(struct udevice *dev, unsigned int selector, + char *buf, int size) +{ + struct armada_37xx_pinctrl *info = dev_get_priv(dev); + int n; + + /* + * First check if selected pin is in some extra pin group. + * Function in extra pin group is active only when it is not gpio. + */ + for (n = 0; n < info->data->ngroups; n++) { + struct armada_37xx_pin_group *grp = &info->data->groups[n]; + + if (selector >= grp->extra_pin && selector < grp->extra_pin + grp->extra_npins) { + unsigned int reg = SELECTION; + unsigned int mask = grp->reg_mask; + int f, val; + + val = (readl(info->base + reg) & mask); + + for (f = 0; f < NB_FUNCS && grp->funcs[f]; f++) { + if (grp->val[f] == val) { + if (strcmp(grp->funcs[f], "gpio") != 0) { + strlcpy(buf, grp->funcs[f], size); + return 0; + } + break; + } + } + } + } + + /* If pin is not active in some extra pin group then check regular groups. */ + for (n = 0; n < info->data->ngroups; n++) { + struct armada_37xx_pin_group *grp = &info->data->groups[n]; + + if (selector >= grp->start_pin && selector < grp->start_pin + grp->npins) { + unsigned int reg = SELECTION; + unsigned int mask = grp->reg_mask; + int f, val; + + val = (readl(info->base + reg) & mask); + + for (f = 0; f < NB_FUNCS && grp->funcs[f]; f++) { + if (grp->val[f] == val) { + strlcpy(buf, grp->funcs[f], size); + return 0; + } + } + + strlcpy(buf, "unknown", size); + return 0; + } + } + + strlcpy(buf, "unknown", size); + return 0; +} + /** * armada_37xx_add_function() - Add a new function to the list * @funcs: array of function to add the new one @@ -615,6 +690,9 @@ static int armada_37xx_gpiochip_register(struct udevice *parent, } static const struct pinctrl_ops armada_37xx_pinctrl_ops = { + .get_pins_count = armada_37xx_pmx_get_pins_count, + .get_pin_name = armada_37xx_pmx_get_pin_name, + .get_pin_muxing = armada_37xx_pmx_get_pin_muxing, .get_groups_count = armada_37xx_pmx_get_groups_count, .get_group_name = armada_37xx_pmx_get_group_name, .get_functions_count = armada_37xx_pmx_get_funcs_count, From ef6fcab85f2f924f44f9a504302343bf248ab2fe Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Mon, 25 Jul 2022 14:13:02 +0200 Subject: [PATCH 15/26] mvebu: pinctrl: apply SDHCI PHY config for A7K Current pin control driver applies SDHCI PHY MUX selection when board DT calls for eMMC function on MPP wires. However, for CP side eMMC, only the "armada-8k-cpm-pinctrl" compatibility string is taken into account, which causes CP-SDHCI on Armada-7K boards to fail. This patch adds "armada-7k-pinctrl" compatibility string handling for the CP-SDHCI PHY configuration case. Signed-off-by: Konstantin Porotchkin Reviewed-by: Igal Liberman Reviewed-by: Stefan Roese --- drivers/pinctrl/mvebu/pinctrl-mvebu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index 536c6aff96..fd49a97b5b 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -52,7 +52,9 @@ void mvebu_pinctl_emmc_set_mux(struct udevice *dev, u32 pin, u32 func) EMMC_PHY_CTRL_SDPHY_EN); } } else if (!fdt_node_check_compatible(blob, node, - "marvell,armada-8k-cpm-pinctrl")) { + "marvell,armada-8k-cpm-pinctrl") || + !fdt_node_check_compatible(blob, node, + "marvell,armada-7k-pinctrl")) { if ((pin == CP110_EMMC_CLK_PIN_ID) && (func == CP110_EMMC_CLK_FUNC)) { clrbits_le32(priv->base_reg + CP_EMMC_PHY_CTRL_REG, From 5e4d24ccc115215be9aa4cd20cda585e2792e7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Thu, 28 Jul 2022 13:06:24 +0200 Subject: [PATCH 16/26] gpio: Add Turris Omnia MCU driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver registers GPIO controller and allows U-Boot to control GPIO pins on MCU which is connected to Turris Omnia via i2c. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- board/CZ.NIC/turris_omnia/MAINTAINERS | 1 + drivers/gpio/Kconfig | 7 + drivers/gpio/Makefile | 1 + drivers/gpio/turris_omnia_mcu.c | 309 ++++++++++++++++++++++++++ 4 files changed, 318 insertions(+) create mode 100644 drivers/gpio/turris_omnia_mcu.c diff --git a/board/CZ.NIC/turris_omnia/MAINTAINERS b/board/CZ.NIC/turris_omnia/MAINTAINERS index 8258f4fc5b..8bff97cc27 100644 --- a/board/CZ.NIC/turris_omnia/MAINTAINERS +++ b/board/CZ.NIC/turris_omnia/MAINTAINERS @@ -6,4 +6,5 @@ F: arch/arm/dts/armada-385-turris-omnia*.dts* F: board/CZ.NIC/turris_atsha_otp.* F: board/CZ.NIC/turris_omnia/ F: configs/turris_omnia_defconfig +F: drivers/gpio/turris_omnia_mcu.c F: include/configs/turris_omnia.h diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index aaa152fae7..82a8bca270 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -598,4 +598,11 @@ config SLG7XL45106_I2C_GPO 8-bit gpo expander, all gpo lines are controlled by writing value into data register. +config TURRIS_OMNIA_MCU + bool "Turris Omnia MCU GPIO driver" + depends on DM_GPIO + default y if TARGET_TURRIS_OMNIA + help + Support for GPIOs on MCU connected to Turris Omnia via i2c. + endif diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d7552762d0..219f37e0e4 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -75,3 +75,4 @@ obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o +obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU) += turris_omnia_mcu.o diff --git a/drivers/gpio/turris_omnia_mcu.c b/drivers/gpio/turris_omnia_mcu.c new file mode 100644 index 0000000000..3e5d74e62c --- /dev/null +++ b/drivers/gpio/turris_omnia_mcu.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: GPL-2.0+ +// (C) 2022 Pali Rohár + +#include +#include +#include +#include +#include + +enum commands_e { + CMD_GET_STATUS_WORD = 0x01, + CMD_GENERAL_CONTROL = 0x02, + + /* available if STS_FEATURES_SUPPORTED bit set in status word */ + CMD_GET_FEATURES = 0x10, + + /* available if FEAT_EXT_CMDS bit is set in features */ + CMD_GET_EXT_STATUS_DWORD = 0x11, + CMD_EXT_CONTROL = 0x12, + CMD_GET_EXT_CONTROL_STATUS = 0x13, +}; + +/* CMD_GET_STATUS_WORD */ +enum sts_word_e { + STS_MCU_TYPE_MASK = GENMASK(1, 0), + STS_MCU_TYPE_STM32 = 0, + STS_MCU_TYPE_GD32 = 1, + STS_MCU_TYPE_MKL = 2, + STS_FEATURES_SUPPORTED = BIT(2), + STS_USER_REGULATOR_NOT_SUPPORTED = BIT(3), + STS_CARD_DET = BIT(4), + STS_MSATA_IND = BIT(5), + STS_USB30_OVC = BIT(6), + STS_USB31_OVC = BIT(7), + STS_USB30_PWRON = BIT(8), + STS_USB31_PWRON = BIT(9), + STS_ENABLE_4V5 = BIT(10), + STS_BUTTON_MODE = BIT(11), + STS_BUTTON_PRESSED = BIT(12), + STS_BUTTON_COUNTER_MASK = GENMASK(15, 13) +}; + +/* CMD_GENERAL_CONTROL */ +enum ctl_byte_e { + CTL_LIGHT_RST = BIT(0), + CTL_HARD_RST = BIT(1), + /*CTL_RESERVED = BIT(2),*/ + CTL_USB30_PWRON = BIT(3), + CTL_USB31_PWRON = BIT(4), + CTL_ENABLE_4V5 = BIT(5), + CTL_BUTTON_MODE = BIT(6), + CTL_BOOTLOADER = BIT(7) +}; + +/* CMD_GET_FEATURES */ +enum features_e { + FEAT_EXT_CMDS = BIT(1), +}; + +struct turris_omnia_mcu_info { + u16 features; +}; + +static int turris_omnia_mcu_get_function(struct udevice *dev, uint offset) +{ + struct turris_omnia_mcu_info *info = dev_get_plat(dev); + + switch (offset) { + /* bank 0 */ + case 0 ... 15: + switch (offset) { + case ilog2(STS_USB30_PWRON): + case ilog2(STS_USB31_PWRON): + case ilog2(STS_ENABLE_4V5): + case ilog2(STS_BUTTON_MODE): + return GPIOF_OUTPUT; + default: + return GPIOF_INPUT; + } + + /* bank 1 - supported only when FEAT_EXT_CMDS is set */ + case (16 + 0) ... (16 + 31): + if (!(info->features & FEAT_EXT_CMDS)) + return -EINVAL; + return GPIOF_INPUT; + + /* bank 2 - supported only when FEAT_EXT_CMDS is set */ + case (16 + 32 + 0) ... (16 + 32 + 15): + if (!(info->features & FEAT_EXT_CMDS)) + return -EINVAL; + return GPIOF_OUTPUT; + + default: + return -EINVAL; + } +} + +static int turris_omnia_mcu_get_value(struct udevice *dev, uint offset) +{ + struct turris_omnia_mcu_info *info = dev_get_plat(dev); + u8 val16[2]; + u8 val32[4]; + int ret; + + switch (offset) { + /* bank 0 */ + case 0 ... 15: + ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, val16, 2); + if (ret) + return ret; + return ((((u16)val16[1] << 8) | val16[0]) >> offset) & 0x1; + + /* bank 1 - supported only when FEAT_EXT_CMDS is set */ + case (16 + 0) ... (16 + 31): + if (!(info->features & FEAT_EXT_CMDS)) + return -EINVAL; + ret = dm_i2c_read(dev, CMD_GET_EXT_STATUS_DWORD, val32, 4); + if (ret) + return ret; + return ((((u32)val32[3] << 24) | ((u32)val32[2] << 16) | + ((u32)val32[1] << 8) | val32[0]) >> (offset - 16)) & 0x1; + + /* bank 2 - supported only when FEAT_EXT_CMDS is set */ + case (16 + 32 + 0) ... (16 + 32 + 15): + if (!(info->features & FEAT_EXT_CMDS)) + return -EINVAL; + ret = dm_i2c_read(dev, CMD_GET_EXT_CONTROL_STATUS, val16, 2); + if (ret) + return ret; + return ((((u16)val16[1] << 8) | val16[0]) >> (offset - 16 - 32)) & 0x1; + + default: + return -EINVAL; + } +} + +static int turris_omnia_mcu_set_value(struct udevice *dev, uint offset, int value) +{ + struct turris_omnia_mcu_info *info = dev_get_plat(dev); + u8 val[2]; + int ret; + u8 reg; + + switch (offset) { + /* bank 0 */ + case ilog2(STS_USB30_PWRON): + reg = CMD_GENERAL_CONTROL; + val[1] = CTL_USB30_PWRON; + break; + case ilog2(STS_USB31_PWRON): + reg = CMD_GENERAL_CONTROL; + val[1] = CTL_USB31_PWRON; + break; + case ilog2(STS_ENABLE_4V5): + reg = CMD_GENERAL_CONTROL; + val[1] = CTL_ENABLE_4V5; + break; + case ilog2(STS_BUTTON_MODE): + reg = CMD_GENERAL_CONTROL; + val[1] = CTL_BUTTON_MODE; + break; + + /* bank 2 - supported only when FEAT_EXT_CMDS is set */ + case (16 + 32 + 0) ... (16 + 32 + 15): + if (!(info->features & FEAT_EXT_CMDS)) + return -EINVAL; + reg = CMD_EXT_CONTROL; + val[1] = BIT(offset - 16 - 32); + break; + + default: + return -EINVAL; + } + + val[0] = value ? val[1] : 0; + + ret = dm_i2c_write(dev, reg, val, 2); + if (ret) + return ret; + + return 0; +} + +static int turris_omnia_mcu_direction_input(struct udevice *dev, uint offset) +{ + int ret; + + ret = turris_omnia_mcu_get_function(dev, offset); + if (ret < 0) + return ret; + else if (ret != GPIOF_INPUT) + return -EOPNOTSUPP; + + return 0; +} + +static int turris_omnia_mcu_direction_output(struct udevice *dev, uint offset, int value) +{ + int ret; + + ret = turris_omnia_mcu_get_function(dev, offset); + if (ret < 0) + return ret; + else if (ret != GPIOF_OUTPUT) + return -EOPNOTSUPP; + + return turris_omnia_mcu_set_value(dev, offset, value); +} + +static int turris_omnia_mcu_xlate(struct udevice *dev, struct gpio_desc *desc, + struct ofnode_phandle_args *args) +{ + uint bank, gpio, flags, offset; + int ret; + + if (args->args_count != 3) + return -EINVAL; + + bank = args->args[0]; + gpio = args->args[1]; + flags = args->args[2]; + + switch (bank) { + case 0: + if (gpio >= 16) + return -EINVAL; + offset = gpio; + break; + case 1: + if (gpio >= 32) + return -EINVAL; + offset = 16 + gpio; + break; + case 2: + if (gpio >= 16) + return -EINVAL; + offset = 16 + 32 + gpio; + break; + default: + return -EINVAL; + } + + ret = turris_omnia_mcu_get_function(dev, offset); + if (ret < 0) + return ret; + + desc->offset = offset; + desc->flags = gpio_flags_xlate(flags); + + return 0; +} + +static const struct dm_gpio_ops turris_omnia_mcu_ops = { + .direction_input = turris_omnia_mcu_direction_input, + .direction_output = turris_omnia_mcu_direction_output, + .get_value = turris_omnia_mcu_get_value, + .set_value = turris_omnia_mcu_set_value, + .get_function = turris_omnia_mcu_get_function, + .xlate = turris_omnia_mcu_xlate, +}; + +static int turris_omnia_mcu_probe(struct udevice *dev) +{ + struct turris_omnia_mcu_info *info = dev_get_plat(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + u16 status; + u8 val[2]; + int ret; + + ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, val, 2); + if (ret) { + printf("Error: turris_omnia_mcu CMD_GET_STATUS_WORD failed: %d\n", ret); + return ret; + } + + status = ((u16)val[1] << 8) | val[0]; + + if (status & STS_FEATURES_SUPPORTED) { + ret = dm_i2c_read(dev, CMD_GET_FEATURES, val, 2); + if (ret) { + printf("Error: turris_omnia_mcu CMD_GET_FEATURES failed: %d\n", ret); + return ret; + } + info->features = ((u16)val[1] << 8) | val[0]; + } + + uc_priv->bank_name = "mcu_"; + + if (info->features & FEAT_EXT_CMDS) + uc_priv->gpio_count = 16 + 32 + 16; + else + uc_priv->gpio_count = 16; + + return 0; +} + +static const struct udevice_id turris_omnia_mcu_ids[] = { + { .compatible = "cznic,turris-omnia-mcu" }, + { } +}; + +U_BOOT_DRIVER(turris_omnia_mcu) = { + .name = "turris-omnia-mcu", + .id = UCLASS_GPIO, + .ops = &turris_omnia_mcu_ops, + .probe = turris_omnia_mcu_probe, + .plat_auto = sizeof(struct turris_omnia_mcu_info), + .of_match = turris_omnia_mcu_ids, +}; From 832738974806e6264a3d0ac2aaa92d0f662fd128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Thu, 28 Jul 2022 13:06:25 +0200 Subject: [PATCH 17/26] arm: mvebu: turris_omnia: Add mcu node with gpio-controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows U-Boot to register new Turris Omnia MCU driver. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- arch/arm/dts/armada-385-turris-omnia.dts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/armada-385-turris-omnia.dts b/arch/arm/dts/armada-385-turris-omnia.dts index 7f1478edfd..86904de816 100644 --- a/arch/arm/dts/armada-385-turris-omnia.dts +++ b/arch/arm/dts/armada-385-turris-omnia.dts @@ -173,7 +173,14 @@ #size-cells = <0>; reg = <0>; - /* STM32F0 command interface at address 0x2a */ + /* MCU command i2c API */ + mcu: mcu@2a { + compatible = "cznic,turris-omnia-mcu"; + reg = <0x2a>; + gpio-controller; + #gpio-cells = <3>; + }; + /* leds device (in STM32F0) at address 0x2b */ eeprom@54 { From 5d2f7d306cecaf454569fd787855ba1106499400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 26 Jul 2022 16:11:56 +0200 Subject: [PATCH 18/26] cmd: mvebu/bubt: Verify image type for all 32-bit Aramda SoCs and Armada 3700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current image type verification code is specific to 32-bit Armada SoCs but used only for Armada 38x. Implement image type verification for Armada 3700 and enable Armada 38x image verification for all 32-bit Armada SoCs. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- cmd/mvebu/bubt.c | 78 +++++++++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index 1362c03bce..a05e22a547 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -56,6 +56,21 @@ struct mvebu_image_header { #define IMAGE_VERSION_3_6_0 0x030600 #define IMAGE_VERSION_3_5_0 0x030500 +struct tim_boot_flash_sign { + unsigned int id; + const char *name; +}; + +struct tim_boot_flash_sign tim_boot_flash_signs[] = { + { 0x454d4d08, "mmc" }, + { 0x454d4d0b, "mmc" }, + { 0x5350490a, "spi" }, + { 0x5350491a, "nand" }, + { 0x55415223, "uart" }, + { 0x53415432, "sata" }, + {}, +}; + struct common_tim_data { u32 version; u32 identifier; @@ -83,7 +98,7 @@ struct mvebu_image_info { u32 encrypt_start_offset; u32 encrypt_size; }; -#endif +#elif defined(CONFIG_ARMADA_32BIT) /* Structure of the main header, version 1 (Armada 370/XP/375/38x/39x) */ struct a38x_main_hdr_v1 { @@ -123,6 +138,8 @@ struct a38x_boot_mode a38x_boot_modes[] = { {}, }; +#endif + struct bubt_dev { char name[8]; size_t (*read)(const char *file_name); @@ -635,7 +652,7 @@ static int check_image_header(void) return 0; } -#elif defined(CONFIG_ARMADA_38X) +#elif defined(CONFIG_ARMADA_32BIT) static size_t a38x_header_size(const struct a38x_main_hdr_v1 *h) { if (h->version == 1) @@ -691,34 +708,39 @@ static int check_image_header(void) static int bubt_check_boot_mode(const struct bubt_dev *dst) { - if (IS_ENABLED(CONFIG_ARMADA_38X)) { - int mode; - const struct a38x_main_hdr_v1 *hdr = - (struct a38x_main_hdr_v1 *)get_load_addr(); +#if defined(CONFIG_ARMADA_3700) || defined(CONFIG_ARMADA_32BIT) + int mode; +#if defined(CONFIG_ARMADA_3700) + const struct tim_boot_flash_sign *boot_modes = tim_boot_flash_signs; + const struct common_tim_data *hdr = + (struct common_tim_data *)get_load_addr(); + u32 id = hdr->boot_flash_sign; +#elif defined(CONFIG_ARMADA_32BIT) + const struct a38x_boot_mode *boot_modes = a38x_boot_modes; + const struct a38x_main_hdr_v1 *hdr = + (struct a38x_main_hdr_v1 *)get_load_addr(); + u32 id = hdr->blockid; +#endif - for (mode = 0; mode < ARRAY_SIZE(a38x_boot_modes); mode++) { - if (strcmp(a38x_boot_modes[mode].name, dst->name) == 0) - break; - } - - if (a38x_boot_modes[mode].id == hdr->blockid) - return 0; - - for (int i = 0; i < ARRAY_SIZE(a38x_boot_modes); i++) { - if (a38x_boot_modes[i].id == hdr->blockid) { - printf("Error: A38x image meant to be booted from " - "\"%s\", not \"%s\"!\n", - a38x_boot_modes[i].name, dst->name); - return -ENOEXEC; - } - } - - printf("Error: unknown boot device in A38x image header: " - "0x%x\n", hdr->blockid); - return -ENOEXEC; - } else { - return 0; + for (mode = 0; boot_modes[mode].name; mode++) { + if (boot_modes[mode].id == id) + break; } + + if (!boot_modes[mode].name) { + printf("Error: unknown boot device in image header: 0x%x\n", id); + return -ENOEXEC; + } + + if (strcmp(boot_modes[mode].name, dst->name) == 0) + return 0; + + printf("Error: image meant to be booted from \"%s\", not \"%s\"!\n", + boot_modes[mode].name, dst->name); + return -ENOEXEC; +#else + return 0; +#endif } static int bubt_verify(const struct bubt_dev *dst) From 4b9521f2421cef5d93682879e86933d25f8ac294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 26 Jul 2022 16:11:57 +0200 Subject: [PATCH 19/26] cmd: mvebu/bubt: Correctly propagate failure during tftp transport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net_loop() returns signed int type and negative value represents error. tftp_read_file() returns unsigned size_t type and zero value represents error. Casting signed negative value to unsigned size_t type cause losing information about error and bubt thinks that no error happened, and continue erasing SPI-NOR which cause malfunction device. Fix this issue by correctly propagating failure during tftp transport. With this change when there is no eth link, bubt does not erase SPI-NOR anymore. => bubt Burning U-Boot image "flash-image.bin" from "tftp" to "spi" ethernet@30000 Waiting for PHY auto negotiation to complete......... TIMEOUT ! ethernet@30000: No link. Error: Failed to read file flash-image.bin from tftp Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- cmd/mvebu/bubt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index a05e22a547..2924b1539f 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -455,11 +455,14 @@ static int is_usb_active(void) #ifdef CONFIG_CMD_NET static size_t tftp_read_file(const char *file_name) { + int ret; + /* * update global variable image_load_addr before tftp file from network */ image_load_addr = get_load_addr(); - return net_loop(TFTPGET); + ret = net_loop(TFTPGET); + return ret > 0 ? ret : 0; } static int is_tftp_active(void) From 93c1358bcd6b249260f239042fba025764b4a89e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 26 Jul 2022 16:11:58 +0200 Subject: [PATCH 20/26] cmd: mvebu/bubt: Add support for sha512 checksum validation for Armada 3700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Armada 3700 BootROM supports also images with sha512 checksums and mox-imager tool [1] generates such bootable images. Without sha512 support U-Boot bubt command just prints error message: Error: Unsupported hash_algorithm_id = 64 Error: Image header verification failed This patch adds support for sha512 checksum validation for Armada 3700 images. With it bubt prints: Image checksum...OK! [1] - https://gitlab.nic.cz/turris/mox-boot-builder.git Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- cmd/mvebu/Kconfig | 1 + cmd/mvebu/bubt.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/cmd/mvebu/Kconfig b/cmd/mvebu/Kconfig index 39963db82c..120397d6d4 100644 --- a/cmd/mvebu/Kconfig +++ b/cmd/mvebu/Kconfig @@ -4,6 +4,7 @@ depends on ARCH_MVEBU config CMD_MVEBU_BUBT bool "bubt" select SHA256 if ARMADA_3700 + select SHA512 if ARMADA_3700 help bubt - Burn a u-boot image to flash For details about bubt command please see the documentation diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index 2924b1539f..276069a0ef 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -26,6 +26,7 @@ #endif #include #include +#include #if defined(CONFIG_ARMADA_8K) #define MAIN_HDR_MAGIC 0xB105B002 @@ -566,8 +567,10 @@ static int check_image_header(void) int image_num; u8 hash_160_output[SHA1_SUM_LEN]; u8 hash_256_output[SHA256_SUM_LEN]; + u8 hash_512_output[SHA512_SUM_LEN]; sha1_context hash1_text; sha256_context hash256_text; + sha512_context hash512_text; u8 *hash_output; u32 hash_algorithm_id; u32 image_size_to_hash; @@ -637,6 +640,12 @@ static int check_image_header(void) sha256_finish(&hash256_text, hash_256_output); hash_output = hash_256_output; break; + case SHA512_SUM_LEN: + sha512_starts(&hash512_text); + sha512_update(&hash512_text, buff, image_size_to_hash); + sha512_finish(&hash512_text, hash_512_output); + hash_output = hash_512_output; + break; default: printf("Error: Unsupported hash_algorithm_id = %d\n", hash_algorithm_id); From 09b0e20d73e371a7cba2db3a95c4173bd8209555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 26 Jul 2022 16:11:59 +0200 Subject: [PATCH 21/26] cmd: mvebu/bubt: Fix cmd main return value on error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Negative return value from cmd main function cause U-Boot to print criplic error message: exit not allowed from main input shell. Set return value on error to 1. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- cmd/mvebu/bubt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index 276069a0ef..ffa05bc201 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -870,11 +870,11 @@ int do_bubt_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) dst = find_bubt_dev(dst_dev_name); if (!dst) { printf("Error: Unknown destination \"%s\"\n", dst_dev_name); - return -EINVAL; + return 1; } if (!bubt_is_dev_active(dst)) - return -ENODEV; + return 1; /* Figure out the source device */ src = find_bubt_dev(src_dev_name); @@ -891,15 +891,15 @@ int do_bubt_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) image_size = bubt_read_file(src); if (!image_size) - return -EIO; + return 1; err = bubt_verify(dst); if (err) - return err; + return 1; err = bubt_write_file(dst, image_size); if (err) - return err; + return 1; return 0; } From 204b8707cd1ba5369f6c7c984de166a880bb2b5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 27 Jul 2022 14:47:35 +0200 Subject: [PATCH 22/26] arm: mvebu: Fix compatible string for nand controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux kernel uses compatible string "marvell,armada370-nand-controller" for nand controllers on Armada 370/XP/38x. U-Boot currently uses mix of "marvell,armada370-nand" and "marvell,mvebu-pxa3xx-nand". So unify it and use just Linux kernel compatible string. Signed-off-by: Pali Rohár Acked-by: Michael Trimarchi Reviewed-by: Stefan Roese --- arch/arm/dts/armada-370-xp.dtsi | 2 +- arch/arm/dts/armada-375.dtsi | 2 +- arch/arm/dts/armada-38x.dtsi | 2 +- arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi | 2 +- drivers/mtd/nand/raw/pxa3xx_nand.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/dts/armada-370-xp.dtsi b/arch/arm/dts/armada-370-xp.dtsi index 50fc0be9f7..4cd168c957 100644 --- a/arch/arm/dts/armada-370-xp.dtsi +++ b/arch/arm/dts/armada-370-xp.dtsi @@ -246,7 +246,7 @@ }; nand@d0000 { - compatible = "marvell,armada370-nand"; + compatible = "marvell,armada370-nand-controller"; reg = <0xd0000 0x54>; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/dts/armada-375.dtsi b/arch/arm/dts/armada-375.dtsi index ff0ad7a9c7..fcb9245fd4 100644 --- a/arch/arm/dts/armada-375.dtsi +++ b/arch/arm/dts/armada-375.dtsi @@ -541,7 +541,7 @@ }; nand@d0000 { - compatible = "marvell,armada370-nand"; + compatible = "marvell,armada370-nand-controller"; reg = <0xd0000 0x54>; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/dts/armada-38x.dtsi b/arch/arm/dts/armada-38x.dtsi index 7d76df3f9c..2845b010be 100644 --- a/arch/arm/dts/armada-38x.dtsi +++ b/arch/arm/dts/armada-38x.dtsi @@ -557,7 +557,7 @@ }; nand_controller: nand-controller@d0000 { - compatible = "marvell,armada370-nand","marvell,mvebu-pxa3xx-nand"; + compatible = "marvell,armada370-nand-controller"; reg = <0xd0000 0x54>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi b/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi index 90cad85506..fdbe168a87 100644 --- a/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi +++ b/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi @@ -5,7 +5,7 @@ }; &nand_controller { - compatible="marvell,mvebu-pxa3xx-nand"; + compatible="marvell,armada370-nand-controller"; status = "okay"; label = "pxa3xx_nand-0"; nand-rb = <0>; diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c index 20d1aee7b3..9c29e8a6c2 100644 --- a/drivers/mtd/nand/raw/pxa3xx_nand.c +++ b/drivers/mtd/nand/raw/pxa3xx_nand.c @@ -429,7 +429,7 @@ static struct nand_ecclayout ecc_layout_8KB_bch8bit = { static const struct udevice_id pxa3xx_nand_dt_ids[] = { { - .compatible = "marvell,mvebu-pxa3xx-nand", + .compatible = "marvell,armada370-nand-controller", .data = PXA3XX_NAND_VARIANT_ARMADA370, }, { From 30bbb02a5c3e05f195fa442015ccb29d3b49b31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 27 Jul 2022 14:47:36 +0200 Subject: [PATCH 23/26] arm: mvebu: Synchronize armada-38x.dtsi with Linux v5.20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Replace skeleton.dtsi by explicit #address-cells / #size-cells * Add sdramc@1400 and phy@18300 nodes * Remove (unused) timeout-ms i2c properties * Fix compatible string for UARTs * Add interrupts properties for watchdog Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- arch/arm/dts/armada-38x.dtsi | 55 ++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/arch/arm/dts/armada-38x.dtsi b/arch/arm/dts/armada-38x.dtsi index 2845b010be..3e970097c8 100644 --- a/arch/arm/dts/armada-38x.dtsi +++ b/arch/arm/dts/armada-38x.dtsi @@ -9,13 +9,15 @@ * Thomas Petazzoni */ -#include "skeleton.dtsi" #include #include #define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16)) / { + #address-cells = <1>; + #size-cells = <1>; + model = "Marvell Armada 38x family SoC"; compatible = "marvell,armada380"; @@ -103,6 +105,11 @@ #size-cells = <1>; ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>; + sdramc: sdramc@1400 { + compatible = "marvell,armada-xp-sdram-controller"; + reg = <0x1400 0x500>; + }; + L2: cache-controller@8000 { compatible = "arm,pl310-cache"; reg = <0x8000 0x1000>; @@ -148,7 +155,6 @@ #address-cells = <1>; #size-cells = <0>; interrupts = ; - timeout-ms = <1000>; clocks = <&coreclk 0>; status = "disabled"; }; @@ -159,13 +165,12 @@ #address-cells = <1>; #size-cells = <0>; interrupts = ; - timeout-ms = <1000>; clocks = <&coreclk 0>; status = "disabled"; }; uart0: serial@12000 { - compatible = "snps,dw-apb-uart"; + compatible = "marvell,armada-38x-uart", "ns16550a"; reg = <0x12000 0x100>; reg-shift = <2>; interrupts = ; @@ -175,7 +180,7 @@ }; uart1: serial@12100 { - compatible = "snps,dw-apb-uart"; + compatible = "marvell,armada-38x-uart", "ns16550a"; reg = <0x12100 0x100>; reg-shift = <2>; interrupts = ; @@ -340,6 +345,44 @@ #clock-cells = <1>; }; + comphy: phy@18300 { + compatible = "marvell,armada-380-comphy"; + reg-names = "comphy", "conf"; + reg = <0x18300 0x100>, <0x18460 4>; + #address-cells = <1>; + #size-cells = <0>; + + comphy0: phy@0 { + reg = <0>; + #phy-cells = <1>; + }; + + comphy1: phy@1 { + reg = <1>; + #phy-cells = <1>; + }; + + comphy2: phy@2 { + reg = <2>; + #phy-cells = <1>; + }; + + comphy3: phy@3 { + reg = <3>; + #phy-cells = <1>; + }; + + comphy4: phy@4 { + reg = <4>; + #phy-cells = <1>; + }; + + comphy5: phy@5 { + reg = <5>; + #phy-cells = <1>; + }; + }; + coreclk: mvebu-sar@18600 { compatible = "marvell,armada-380-core-clock"; reg = <0x18600 0x04>; @@ -381,6 +424,8 @@ reg = <0x20300 0x34>, <0x20704 0x4>, <0x18260 0x4>; clocks = <&coreclk 2>, <&refclk>; clock-names = "nbclk", "fixed"; + interrupts-extended = <&gic GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; }; cpurst: cpurst@20800 { From 48223161b54a22444624b4e91e363432cf94b2e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 27 Jul 2022 14:47:37 +0200 Subject: [PATCH 24/26] arm: mvebu: Synchronize armada-385.dtsi with Linux v5.20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Define PCIe interrupts Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- arch/arm/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/arch/arm/dts/armada-385.dtsi b/arch/arm/dts/armada-385.dtsi index 581a7d9bea..48072fc7fd 100644 --- a/arch/arm/dts/armada-385.dtsi +++ b/arch/arm/dts/armada-385.dtsi @@ -69,17 +69,26 @@ reg = <0x0800 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; + interrupt-names = "intx"; + interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; #interrupt-cells = <1>; ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0 0x81000000 0 0 0x81000000 0x1 0 1 0>; bus-range = <0x00 0xff>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie1_intc 0>, + <0 0 0 2 &pcie1_intc 1>, + <0 0 0 3 &pcie1_intc 2>, + <0 0 0 4 &pcie1_intc 3>; marvell,pcie-port = <0>; marvell,pcie-lane = <0>; clocks = <&gateclk 8>; resets = <&systemc 0 0>; status = "disabled"; + pcie1_intc: interrupt-controller { + interrupt-controller; + #interrupt-cells = <1>; + }; }; /* x1 port */ @@ -89,17 +98,26 @@ reg = <0x1000 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; + interrupt-names = "intx"; + interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; #interrupt-cells = <1>; ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0 0x81000000 0 0 0x81000000 0x2 0 1 0>; bus-range = <0x00 0xff>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie2_intc 0>, + <0 0 0 2 &pcie2_intc 1>, + <0 0 0 3 &pcie2_intc 2>, + <0 0 0 4 &pcie2_intc 3>; marvell,pcie-port = <1>; marvell,pcie-lane = <0>; clocks = <&gateclk 5>; resets = <&systemc 0 1>; status = "disabled"; + pcie2_intc: interrupt-controller { + interrupt-controller; + #interrupt-cells = <1>; + }; }; /* x1 port */ @@ -109,17 +127,26 @@ reg = <0x1800 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; + interrupt-names = "intx"; + interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; #interrupt-cells = <1>; ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0 0x81000000 0 0 0x81000000 0x3 0 1 0>; bus-range = <0x00 0xff>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie3_intc 0>, + <0 0 0 2 &pcie3_intc 1>, + <0 0 0 3 &pcie3_intc 2>, + <0 0 0 4 &pcie3_intc 3>; marvell,pcie-port = <2>; marvell,pcie-lane = <0>; clocks = <&gateclk 6>; resets = <&systemc 0 2>; status = "disabled"; + pcie3_intc: interrupt-controller { + interrupt-controller; + #interrupt-cells = <1>; + }; }; /* @@ -132,17 +159,26 @@ reg = <0x2000 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; + interrupt-names = "intx"; + interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; #interrupt-cells = <1>; ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0 0x81000000 0 0 0x81000000 0x4 0 1 0>; bus-range = <0x00 0xff>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie4_intc 0>, + <0 0 0 2 &pcie4_intc 1>, + <0 0 0 3 &pcie4_intc 2>, + <0 0 0 4 &pcie4_intc 3>; marvell,pcie-port = <3>; marvell,pcie-lane = <0>; clocks = <&gateclk 7>; resets = <&systemc 0 3>; status = "disabled"; + pcie4_intc: interrupt-controller { + interrupt-controller; + #interrupt-cells = <1>; + }; }; }; }; From 162311637da4170212f7a9ca4bddbc9374af1d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 27 Jul 2022 14:47:38 +0200 Subject: [PATCH 25/26] arm: mvebu: Synchronize armada-385-turris-omnia with Linux v5.20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add SPDX-License-Identifier * Add SFP and LED nodes * Fix PHY nad NOR nodes * Remove duplicates from u-boot.dtsi file Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- .../dts/armada-385-turris-omnia-u-boot.dtsi | 5 +- arch/arm/dts/armada-385-turris-omnia.dts | 228 ++++++++++++++---- 2 files changed, 183 insertions(+), 50 deletions(-) diff --git a/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi index 5a22cc64a1..ec12298fd4 100644 --- a/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi +++ b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi @@ -28,11 +28,8 @@ i2c@5 { u-boot,dm-pre-reloc; - /* ATSHA204A at address 0x64 */ crypto@64 { u-boot,dm-pre-reloc; - compatible = "atmel,atsha204a"; - reg = <0x64>; }; }; }; @@ -42,7 +39,7 @@ &spi0 { u-boot,dm-pre-reloc; - spi-nor@0 { + flash@0 { u-boot,dm-pre-reloc; partitions { diff --git a/arch/arm/dts/armada-385-turris-omnia.dts b/arch/arm/dts/armada-385-turris-omnia.dts index 86904de816..9980a854e3 100644 --- a/arch/arm/dts/armada-385-turris-omnia.dts +++ b/arch/arm/dts/armada-385-turris-omnia.dts @@ -1,43 +1,10 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) /* * Device Tree file for the Turris Omnia * * Copyright (C) 2016 Uwe Kleine-König * Copyright (C) 2016 Tomas Hlavacek * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without - * any warranty of any kind, whether express or implied. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/* * Schematic available at https://www.turris.cz/doc/_media/rtrom01-schema.pdf */ @@ -45,6 +12,7 @@ #include #include +#include #include "armada-385.dtsi" / { @@ -70,7 +38,8 @@ ranges = ; + MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 + MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; internal-regs { @@ -108,19 +77,48 @@ pcie@1,0 { /* Port 0, Lane 0 */ status = "okay"; + slot-power-limit-milliwatt = <10000>; }; pcie@2,0 { /* Port 1, Lane 0 */ status = "okay"; + slot-power-limit-milliwatt = <10000>; }; pcie@3,0 { /* Port 2, Lane 0 */ status = "okay"; + slot-power-limit-milliwatt = <10000>; }; }; }; + + sfp: sfp { + compatible = "sff,sfp"; + i2c-bus = <&sfp_i2c>; + tx-fault-gpios = <&pcawan 0 GPIO_ACTIVE_HIGH>; + tx-disable-gpios = <&pcawan 1 GPIO_ACTIVE_HIGH>; + rate-select0-gpios = <&pcawan 2 GPIO_ACTIVE_HIGH>; + los-gpios = <&pcawan 3 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&pcawan 4 GPIO_ACTIVE_LOW>; + maximum-power-milliwatt = <3000>; + + /* + * For now this has to be enabled at boot time by U-Boot when + * a SFP module is present. Read more in the comment in the + * eth2 node below. + */ + status = "disabled"; + }; +}; + +&bm { + status = "okay"; +}; + +&bm_bppi { + status = "okay"; }; /* Connected to 88E6176 switch, port 6 */ @@ -129,6 +127,9 @@ pinctrl-0 = <&ge0_rgmii_pins>; status = "okay"; phy-mode = "rgmii"; + buffer-manager = <&bm>; + bm,pool-long = <0>; + bm,pool-short = <3>; fixed-link { speed = <1000>; @@ -142,6 +143,9 @@ pinctrl-0 = <&ge1_rgmii_pins>; status = "okay"; phy-mode = "rgmii"; + buffer-manager = <&bm>; + bm,pool-long = <1>; + bm,pool-short = <3>; fixed-link { speed = <1000>; @@ -151,9 +155,23 @@ /* WAN port */ ð2 { + /* + * eth2 is connected via a multiplexor to both the SFP cage and to + * ethernet-phy@1. The multiplexor switches the signal to SFP cage when + * a SFP module is present, as determined by the mode-def0 GPIO. + * + * Until kernel supports this configuration properly, in case SFP module + * is present, U-Boot has to enable the sfp node above, remove phy + * handle and add managed = "in-band-status" property. + */ status = "okay"; phy-mode = "sgmii"; - phy = <&phy1>; + phy-handle = <&phy1>; + phys = <&comphy5 2>; + sfp = <&sfp>; + buffer-manager = <&bm>; + bm,pool-long = <2>; + bm,pool-short = <3>; }; &i2c0 { @@ -166,7 +184,6 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x70>; - status = "okay"; i2c@0 { #address-cells = <1>; @@ -181,10 +198,114 @@ #gpio-cells = <3>; }; - /* leds device (in STM32F0) at address 0x2b */ + led-controller@2b { + compatible = "cznic,turris-omnia-leds"; + reg = <0x2b>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + /* + * LEDs are controlled by MCU (STM32F0) at + * address 0x2b. + * + * LED functions are not stable yet: + * - there are 3 LEDs connected via MCU to PCIe + * ports. One of these ports supports mSATA. + * There is no mSATA nor PCIe function. + * For now we use LED_FUNCTION_WLAN, since + * in most cases users have wifi cards in + * these slots + * - there are 2 LEDs dedicated for user: A and + * B. Again there is no such function defined. + * For now we use LED_FUNCTION_INDICATOR + */ + + multi-led@0 { + reg = <0x0>; + color = ; + function = LED_FUNCTION_INDICATOR; + function-enumerator = <2>; + }; + + multi-led@1 { + reg = <0x1>; + color = ; + function = LED_FUNCTION_INDICATOR; + function-enumerator = <1>; + }; + + multi-led@2 { + reg = <0x2>; + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <3>; + }; + + multi-led@3 { + reg = <0x3>; + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <2>; + }; + + multi-led@4 { + reg = <0x4>; + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <1>; + }; + + multi-led@5 { + reg = <0x5>; + color = ; + function = LED_FUNCTION_WAN; + }; + + multi-led@6 { + reg = <0x6>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <4>; + }; + + multi-led@7 { + reg = <0x7>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <3>; + }; + + multi-led@8 { + reg = <0x8>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + }; + + multi-led@9 { + reg = <0x9>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + }; + + multi-led@a { + reg = <0xa>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <0>; + }; + + multi-led@b { + reg = <0xb>; + color = ; + function = LED_FUNCTION_POWER; + }; + }; eeprom@54 { - compatible = "at,24c64"; + compatible = "atmel,24c64"; reg = <0x54>; /* The EEPROM contains data for bootloader. @@ -223,7 +344,7 @@ /* routed to PCIe2 connector (CN62A) */ }; - i2c@4 { + sfp_i2c: i2c@4 { #address-cells = <1>; #size-cells = <0>; reg = <4>; @@ -236,7 +357,11 @@ #size-cells = <0>; reg = <5>; - /* ATSHA204A at address 0x64 */ + /* ATSHA204A-MAHDA-T crypto module */ + crypto@64 { + compatible = "atmel,atsha204a"; + reg = <0x64>; + }; }; i2c@6 { @@ -278,23 +403,29 @@ pinctrl-0 = <&mdio_pins>; status = "okay"; - phy1: phy@1 { - status = "okay"; - compatible = "ethernet-phy-id0141.0DD1", "ethernet-phy-ieee802.3-c22"; + phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; reg = <1>; + marvell,reg-init = <3 18 0 0x4985>, + <3 16 0xfff0 0x0001>; /* irq is connected to &pcawan pin 7 */ }; /* Switch MV88E6176 at address 0x10 */ switch@10 { + pinctrl-names = "default"; + pinctrl-0 = <&swint_pins>; compatible = "marvell,mv88e6085"; #address-cells = <1>; #size-cells = <0>; - dsa,member = <0 0>; + dsa,member = <0 0>; reg = <0x10>; + interrupt-parent = <&gpio1>; + interrupts = <13 IRQ_TYPE_LEVEL_LOW>; + ports { #address-cells = <1>; #size-cells = <0>; @@ -347,6 +478,11 @@ marvell,function = "gpio"; }; + swint_pins: swint-pins { + marvell,pins = "mpp45"; + marvell,function = "gpio"; + }; + spi0cs0_pins: spi0cs0-pins { marvell,pins = "mpp25"; marvell,function = "spi0"; @@ -363,7 +499,7 @@ pinctrl-0 = <&spi0_pins &spi0cs0_pins>; status = "okay"; - spi-nor@0 { + flash@0 { compatible = "spansion,s25fl164k", "jedec,spi-nor"; #address-cells = <1>; #size-cells = <1>; From b2d7619e46aa414cba14a1705892b7e249468d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 27 Jul 2022 15:00:27 +0200 Subject: [PATCH 26/26] arm: mvebu: turris_omnia: Fix mpp26 pin name and comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a bug in Turris Omnia's schematics, whereupon the MPP[26] pin, which is routed to CN11 pin header, is documented as SPI CS1, but MPP[26] pin does not support this function. Instead it controls chip select 2 if in "spi0" mode. Fix the name of the pin node in pinctrl node and fix the comment in SPI node. Signed-off-by: Marek Behún --- arch/arm/dts/armada-385-turris-omnia.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/armada-385-turris-omnia.dts b/arch/arm/dts/armada-385-turris-omnia.dts index 9980a854e3..0be55f8bf6 100644 --- a/arch/arm/dts/armada-385-turris-omnia.dts +++ b/arch/arm/dts/armada-385-turris-omnia.dts @@ -488,7 +488,7 @@ marvell,function = "spi0"; }; - spi0cs1_pins: spi0cs1-pins { + spi0cs2_pins: spi0cs2-pins { marvell,pins = "mpp26"; marvell,function = "spi0"; }; @@ -523,7 +523,7 @@ }; }; - /* MISO, MOSI, SCLK and CS1 are routed to pin header CN11 */ + /* MISO, MOSI, SCLK and CS2 are routed to pin header CN11 */ }; &uart0 {