From 92c4a95ec7986a31f37dbf540dd8fda5927ac659 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 13:56:08 +0200 Subject: 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 | 100 +++++++++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c index 3c8e24088ce..ec21d4ff838 100644 --- a/drivers/pinctrl/pinctrl-generic.c +++ b/drivers/pinctrl/pinctrl-generic.c @@ -234,6 +234,24 @@ enum pinmux_subnode_type { PST_PINMUX, }; +static const char *alloc_name_with_prefix(const char *name, const char *prefix) +{ + if (prefix) { + char *name_with_prefix = malloc(strlen(prefix) + sizeof("pins")); + if (name_with_prefix) + sprintf(name_with_prefix, "%s%s", prefix, name); + return name_with_prefix; + } else { + return name; + } +} + +static void free_name_with_prefix(const char *name_with_prefix, const char *prefix) +{ + if (prefix) + free((char *)name_with_prefix); +} + /** * pinctrl_generic_set_state_one() - set state for a certain pin/group * Apply all pin multiplexing and pin configurations specified by @config @@ -248,9 +266,11 @@ enum pinmux_subnode_type { */ static int pinctrl_generic_set_state_one(struct udevice *dev, struct udevice *config, + const char *prefix, enum pinmux_subnode_type subnode_type, unsigned selector) { + const char *function_propname; const char *propname; const void *value; struct ofprop property; @@ -259,18 +279,26 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, assert(subnode_type != PST_NONE); + function_propname = alloc_name_with_prefix("function", prefix); + if (!function_propname) + return -ENOMEM; + dev_for_each_property(property, config) { value = dev_read_prop_by_prop(&property, &propname, &len); - if (!value) + if (!value) { + free_name_with_prefix(function_propname, prefix); return -EINVAL; + } /* pinmux subnodes already have their muxing set */ if (subnode_type != PST_PINMUX && - !strcmp(propname, "function")) { + !strcmp(propname, function_propname)) { func_selector = pinmux_func_name_to_selector(dev, value); - if (func_selector < 0) + if (func_selector < 0) { + free_name_with_prefix(function_propname, prefix); return func_selector; + } ret = pinmux_enable_setting(dev, subnode_type == PST_GROUP, selector, @@ -291,10 +319,13 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, selector, param, arg); } - if (ret) + if (ret) { + free_name_with_prefix(function_propname, prefix); return ret; + } } + free_name_with_prefix(function_propname, prefix); return 0; } @@ -309,20 +340,34 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, */ static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice *dev, struct udevice *config, + const char *prefix, int *count) { const struct pinctrl_ops *ops = pinctrl_get_ops(dev); + const char *propname; - *count = dev_read_string_count(config, "pins"); + propname = alloc_name_with_prefix("pins", prefix); + if (!propname) + return -ENOMEM; + *count = dev_read_string_count(config, propname); + free_name_with_prefix(propname, prefix); if (*count >= 0) return PST_PIN; - *count = dev_read_string_count(config, "groups"); + propname = alloc_name_with_prefix("groups", prefix); + if (!propname) + return -ENOMEM; + *count = dev_read_string_count(config, propname); + free_name_with_prefix(propname, prefix); if (*count >= 0) return PST_GROUP; if (ops->pinmux_property_set) { - *count = dev_read_size(config, "pinmux"); + propname = alloc_name_with_prefix("pinmux", prefix); + if (!propname) + return -ENOMEM; + *count = dev_read_size(config, propname); + free_name_with_prefix(propname, prefix); if (*count >= 0 && !(*count % sizeof(u32))) { *count /= sizeof(u32); return PST_PINMUX; @@ -338,23 +383,30 @@ static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice * * @dev: pin controller device * @config: pseudo device pointing to config node + * @prefix: device tree property prefix (e.g. vendor specific) * @return: 0 on success, or negative error code on failure */ static int pinctrl_generic_set_state_subnode(struct udevice *dev, - struct udevice *config) + struct udevice *config, + const char *prefix) { enum pinmux_subnode_type subnode_type; + const char *propname; const char *name; int count, selector, i, ret, scratch; const u32 *pinmux_groups = NULL; /* prevent use-uninitialized warning */ - subnode_type = pinctrl_generic_get_subnode_type(dev, config, &count); + subnode_type = pinctrl_generic_get_subnode_type(dev, config, prefix, &count); debug("%s(%s, %s): count=%d\n", __func__, dev->name, config->name, count); if (subnode_type == PST_PINMUX) { - pinmux_groups = dev_read_prop(config, "pinmux", &scratch); + propname = alloc_name_with_prefix("pinmux", prefix); + if (!propname) + return -ENOMEM; + pinmux_groups = dev_read_prop(config, propname, &scratch); + free_name_with_prefix(propname, prefix); if (!pinmux_groups) return -EINVAL; } @@ -362,13 +414,21 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev, for (i = 0; i < count; i++) { switch (subnode_type) { case PST_PIN: - ret = dev_read_string_index(config, "pins", i, &name); + propname = alloc_name_with_prefix("pins", prefix); + if (!propname) + return -ENOMEM; + ret = dev_read_string_index(config, propname, i, &name); + free_name_with_prefix(propname, prefix); if (ret) return ret; selector = pinctrl_pin_name_to_selector(dev, name); break; case PST_GROUP: - ret = dev_read_string_index(config, "groups", i, &name); + propname = alloc_name_with_prefix("groups", prefix); + if (!propname) + return -ENOMEM; + ret = dev_read_string_index(config, propname, i, &name); + free_name_with_prefix(propname, prefix); if (ret) return ret; selector = pinctrl_group_name_to_selector(dev, name); @@ -390,8 +450,8 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev, if (selector < 0) return selector; - ret = pinctrl_generic_set_state_one(dev, config, subnode_type, - selector); + ret = pinctrl_generic_set_state_one(dev, config, prefix, + subnode_type, selector); if (ret) return ret; } @@ -399,22 +459,28 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev, return 0; } -int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config) +int pinctrl_generic_set_state_prefix(struct udevice *dev, struct udevice *config, + const char *prefix) { struct udevice *child; int ret; - ret = pinctrl_generic_set_state_subnode(dev, config); + ret = pinctrl_generic_set_state_subnode(dev, config, prefix); if (ret) return ret; for (device_find_first_child(config, &child); child; device_find_next_child(&child)) { - ret = pinctrl_generic_set_state_subnode(dev, child); + ret = pinctrl_generic_set_state_subnode(dev, child, prefix); if (ret) return ret; } return 0; } + +int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config) +{ + return pinctrl_generic_set_state_prefix(dev, config, NULL); +} -- cgit v1.3.1 From 35c50a709e0ecf62cb254c6496f77c186e471046 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 13:56:09 +0200 Subject: 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 (limited to 'drivers') diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig index 07d4f3e216a..574fb4dfb07 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 c2df96bf5b1..15303d83a71 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 00000000000..252151f3e5d --- /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, +}; -- cgit v1.3.1 From a1de1035b228f634241c80c60fcb39daae6116f9 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 13:56:11 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 76f47027a3e..138801850d3 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 38ce2b5e0ad..ce2d5ddf6d9 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 5436dc4a9a7..e3e50afeaff 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 -- cgit v1.3.1 From 7d8bb89d569b18899011c44f8129a6b95a1424a6 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 13:56:12 +0200 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c index 4c1c68ee19e..888ccfe4d13 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, -- cgit v1.3.1 From dc986c600ff738f35f6c29f8901bc40250d36734 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 13:56:13 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c index 888ccfe4d13..55ed685f70f 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; -- cgit v1.3.1 From da76996a1a09de7522eb8af192730425a1f7842a Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 13:56:14 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c index 55ed685f70f..f706a6dfa4f 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; -- cgit v1.3.1 From bd913a7233f0781e601ce0756a5783dede7f872a Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 14:08:58 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index e76ef153e60..610535fa239 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; -- cgit v1.3.1 From 33893e5278734343beda2a6be7dd0b7644da482e Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 14:08:59 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index 610535fa239..e1cde53a024 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 -- cgit v1.3.1 From ffab049520a59e5ab1c2bf3fe606fdd6b46f8123 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 14:09:00 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index e1cde53a024..e0445e3e2b3 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; -- cgit v1.3.1 From 3d98071dbb1a204aaff5004b409abd4f7deb45e8 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 14:09:01 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index e0445e3e2b3..d2abe67fe5b 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"), -- cgit v1.3.1 From 140ebcdb9a760a9ffb59cd9587bdf2ec82aa11fc Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 14:09:02 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index d2abe67fe5b..74d915950a6 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, }; -- cgit v1.3.1 From e34d8afd7219b7c2b8e7bf83225d09f79fd3f0b0 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 25 Jul 2022 14:09:03 +0200 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index 74d915950a6..bb7a76baed1 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, -- cgit v1.3.1 From ef6fcab85f2f924f44f9a504302343bf248ab2fe Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Mon, 25 Jul 2022 14:13:02 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index 536c6aff96e..fd49a97b5b0 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, -- cgit v1.3.1 From 5e4d24ccc115215be9aa4cd20cda585e2792e7ff Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Thu, 28 Jul 2022 13:06:24 +0200 Subject: 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 (limited to 'drivers') diff --git a/board/CZ.NIC/turris_omnia/MAINTAINERS b/board/CZ.NIC/turris_omnia/MAINTAINERS index 8258f4fc5b2..8bff97cc273 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 aaa152fae73..82a8bca2700 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 d7552762d06..219f37e0e43 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 00000000000..3e5d74e62cd --- /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, +}; -- cgit v1.3.1 From 204b8707cd1ba5369f6c7c984de166a880bb2b5e Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Wed, 27 Jul 2022 14:47:35 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/arch/arm/dts/armada-370-xp.dtsi b/arch/arm/dts/armada-370-xp.dtsi index 50fc0be9f73..4cd168c9578 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 ff0ad7a9c7f..fcb9245fd49 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 7d76df3f9ce..2845b010be7 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 90cad85506d..fdbe168a873 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 20d1aee7b3e..9c29e8a6c21 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, }, { -- cgit v1.3.1