summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/meson/pinctrl-amlogic-a4.c')
-rw-r--r--drivers/pinctrl/meson/pinctrl-amlogic-a4.c83
1 files changed, 77 insertions, 6 deletions
diff --git a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
index d9e3a8d5932a..dfa32b11555c 100644
--- a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
+++ b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
@@ -24,6 +24,7 @@
#include <dt-bindings/pinctrl/amlogic,pinctrl.h>
#include "../core.h"
+#include "../pinctrl-utils.h"
#include "../pinconf.h"
#define gpio_chip_to_bank(chip) \
@@ -672,11 +673,79 @@ static void aml_pin_dbg_show(struct pinctrl_dev *pcdev, struct seq_file *s,
seq_printf(s, " %s", dev_name(pcdev->dev));
}
+static int aml_dt_node_to_map_pinmux(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map,
+ unsigned int *num_maps)
+{
+ struct device *dev = pctldev->dev;
+ struct device_node *pnode;
+ unsigned long *configs = NULL;
+ unsigned int num_configs = 0;
+ struct property *prop;
+ unsigned int reserved_maps;
+ int reserve;
+ int ret;
+
+ prop = of_find_property(np, "pinmux", NULL);
+ if (!prop) {
+ dev_info(dev, "Missing pinmux property\n");
+ return -ENOENT;
+ }
+
+ pnode = of_get_parent(np);
+ if (!pnode) {
+ dev_info(dev, "Missing function node\n");
+ return -EINVAL;
+ }
+
+ reserved_maps = 0;
+ *map = NULL;
+ *num_maps = 0;
+
+ ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
+ &num_configs);
+ if (ret < 0) {
+ dev_err(dev, "%pOF: could not parse node property\n", np);
+ return ret;
+ }
+
+ reserve = 1;
+ if (num_configs)
+ reserve++;
+
+ ret = pinctrl_utils_reserve_map(pctldev, map, &reserved_maps,
+ num_maps, reserve);
+ if (ret < 0)
+ goto exit;
+
+ ret = pinctrl_utils_add_map_mux(pctldev, map,
+ &reserved_maps, num_maps, np->name,
+ pnode->name);
+ if (ret < 0)
+ goto exit;
+
+ if (num_configs) {
+ ret = pinctrl_utils_add_map_configs(pctldev, map, &reserved_maps,
+ num_maps, np->name, configs,
+ num_configs, PIN_MAP_TYPE_CONFIGS_GROUP);
+ if (ret < 0)
+ goto exit;
+ }
+
+exit:
+ kfree(configs);
+ if (ret)
+ pinctrl_utils_free_map(pctldev, *map, *num_maps);
+
+ return ret;
+}
+
static const struct pinctrl_ops aml_pctrl_ops = {
.get_groups_count = aml_get_groups_count,
.get_group_name = aml_get_group_name,
.get_group_pins = aml_get_group_pins,
- .dt_node_to_map = pinconf_generic_dt_node_to_map_pinmux,
+ .dt_node_to_map = aml_dt_node_to_map_pinmux,
.dt_free_map = pinconf_generic_dt_free_map,
.pin_dbg_show = aml_pin_dbg_show,
};
@@ -725,8 +794,9 @@ static u32 aml_bank_pins(struct device_node *np)
if (of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3,
0, &of_args))
return 0;
- else
- return of_args.args[2];
+
+ of_node_put(of_args.np);
+ return of_args.args[2];
}
static int aml_bank_number(struct device_node *np)
@@ -736,8 +806,9 @@ static int aml_bank_number(struct device_node *np)
if (of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3,
0, &of_args))
return -EINVAL;
- else
- return of_args.args[1] >> 8;
+
+ of_node_put(of_args.np);
+ return of_args.args[1] >> 8;
}
static unsigned int aml_count_pins(struct device_node *np)
@@ -893,7 +964,7 @@ static const struct gpio_chip aml_gpio_template = {
.direction_input = aml_gpio_direction_input,
.direction_output = aml_gpio_direction_output,
.get_direction = aml_gpio_get_direction,
- .can_sleep = false,
+ .can_sleep = true,
};
static void init_bank_register_bit(struct aml_pinctrl *info,