aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/drivers/pinctrl/meson/pinctrl-meson-gx-pmx.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/drivers/pinctrl/meson/pinctrl-meson-gx-pmx.c')
-rw-r--r--roms/u-boot/drivers/pinctrl/meson/pinctrl-meson-gx-pmx.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/pinctrl/meson/pinctrl-meson-gx-pmx.c b/roms/u-boot/drivers/pinctrl/meson/pinctrl-meson-gx-pmx.c
new file mode 100644
index 000000000..159f3406a
--- /dev/null
+++ b/roms/u-boot/drivers/pinctrl/meson/pinctrl-meson-gx-pmx.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 - Beniamino Galvani <b.galvani@gmail.com>
+ */
+
+#include <log.h>
+#include <asm/gpio.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include "pinctrl-meson-gx.h"
+
+static void meson_gx_pinmux_disable_other_groups(struct meson_pinctrl *priv,
+ unsigned int pin,
+ int sel_group)
+{
+ struct meson_pmx_group *group;
+ struct meson_gx_pmx_data *pmx_data;
+ void __iomem *addr;
+ int i, j;
+
+ for (i = 0; i < priv->data->num_groups; i++) {
+ group = &priv->data->groups[i];
+ pmx_data = (struct meson_gx_pmx_data *)group->data;
+ if (pmx_data->is_gpio || i == sel_group)
+ continue;
+
+ for (j = 0; j < group->num_pins; j++) {
+ if (group->pins[j] == pin) {
+ /* We have found a group using the pin */
+ debug("pinmux: disabling %s\n", group->name);
+ addr = priv->reg_mux + pmx_data->reg * 4;
+ writel(readl(addr) & ~BIT(pmx_data->bit), addr);
+ }
+ }
+ }
+}
+
+static int meson_gx_pinmux_group_set(struct udevice *dev,
+ unsigned int group_selector,
+ unsigned int func_selector)
+{
+ struct meson_pinctrl *priv = dev_get_priv(dev);
+ const struct meson_pmx_group *group;
+ const struct meson_pmx_func *func;
+ struct meson_gx_pmx_data *pmx_data;
+ void __iomem *addr;
+ int i;
+
+ group = &priv->data->groups[group_selector];
+ pmx_data = (struct meson_gx_pmx_data *)group->data;
+ func = &priv->data->funcs[func_selector];
+
+ debug("pinmux: set group %s func %s\n", group->name, func->name);
+
+ /*
+ * Disable groups using the same pins.
+ * The selected group is not disabled to avoid glitches.
+ */
+ for (i = 0; i < group->num_pins; i++) {
+ meson_gx_pinmux_disable_other_groups(priv,
+ group->pins[i],
+ group_selector);
+ }
+
+ /* Function 0 (GPIO) doesn't need any additional setting */
+ if (func_selector) {
+ addr = priv->reg_mux + pmx_data->reg * 4;
+ writel(readl(addr) | BIT(pmx_data->bit), addr);
+ }
+
+ return 0;
+}
+
+static int meson_gx_pinmux_get(struct udevice *dev,
+ unsigned int selector,
+ char *buf, int size)
+{
+ struct meson_pinctrl *priv = dev_get_priv(dev);
+ struct meson_pmx_group *group;
+ struct meson_gx_pmx_data *pmx_data;
+ void __iomem *addr;
+ int i, j, pos = 0;
+ unsigned int pin;
+ u32 reg;
+
+ pin = selector + priv->data->pin_base;
+
+ for (i = 0; i < priv->data->num_groups; i++) {
+ group = &priv->data->groups[i];
+ pmx_data = (struct meson_gx_pmx_data *)group->data;
+ if (pmx_data->is_gpio)
+ continue;
+
+ for (j = 0; j < group->num_pins; j++) {
+ if (group->pins[j] == pin) {
+ /* We have found a group using the pin */
+ addr = priv->reg_mux + pmx_data->reg * 4;
+ reg = readl(addr) & BIT(pmx_data->bit);
+ if (reg) {
+ pos += snprintf(buf + pos, size - pos,
+ "%s ", group->name) - 1;
+ return 0;
+ }
+ }
+ }
+ }
+
+ /* Fallback, must be used as GPIO */
+ snprintf(buf, size, "%s or Unknown",
+ priv->data->groups[selector].name);
+
+ return 0;
+}
+
+const struct pinconf_param meson_gx_pinconf_params[] = {
+ { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+ { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+ { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+};
+
+const struct pinctrl_ops meson_gx_pinctrl_ops = {
+ .get_groups_count = meson_pinctrl_get_groups_count,
+ .get_group_name = meson_pinctrl_get_group_name,
+ .get_functions_count = meson_pinmux_get_functions_count,
+ .get_function_name = meson_pinmux_get_function_name,
+ .pinmux_group_set = meson_gx_pinmux_group_set,
+ .set_state = pinctrl_generic_set_state,
+ .pinconf_params = meson_gx_pinconf_params,
+ .pinconf_num_params = ARRAY_SIZE(meson_gx_pinconf_params),
+ .pinconf_set = meson_pinconf_set,
+ .pinconf_group_set = meson_pinconf_group_set,
+ .get_pin_name = meson_pinctrl_get_pin_name,
+ .get_pins_count = meson_pinctrl_get_pins_count,
+ .get_pin_muxing = meson_gx_pinmux_get,
+};
+
+static const struct dm_gpio_ops meson_gx_gpio_ops = {
+ .set_value = meson_gpio_set,
+ .get_value = meson_gpio_get,
+ .get_function = meson_gpio_get_direction,
+ .direction_input = meson_gpio_direction_input,
+ .direction_output = meson_gpio_direction_output,
+};
+
+const struct driver meson_gx_gpio_driver = {
+ .name = "meson-gx-gpio",
+ .id = UCLASS_GPIO,
+ .probe = meson_gpio_probe,
+ .ops = &meson_gx_gpio_ops,
+};