pinctrl/lantiq: add pin_config_group_set support
authorJohn Crispin <blogic@openwrt.org>
Fri, 1 Feb 2013 12:04:57 +0000 (13:04 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Tue, 5 Feb 2013 15:17:22 +0000 (16:17 +0100)
While converting all the boards supported by OpenWrt to OF
I noticed that this feature is missing. Adding it makes the
devicetrees more readable.

Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/pinctrl-lantiq.c
drivers/pinctrl/pinctrl-xway.c

index 15f501d..7d11072 100644 (file)
@@ -64,11 +64,13 @@ static void ltq_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
        seq_printf(s, " %s", dev_name(pctldev->dev));
 }
 
-static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+static void ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
                                struct device_node *np,
                                struct pinctrl_map **map)
 {
        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
+       struct property *pins = of_find_property(np, "lantiq,pins", NULL);
+       struct property *groups = of_find_property(np, "lantiq,groups", NULL);
        unsigned long configs[3];
        unsigned num_configs = 0;
        struct property *prop;
@@ -76,8 +78,20 @@ static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
        const char *function;
        int ret, i;
 
+       if (!pins && !groups) {
+               dev_err(pctldev->dev, "%s defines neither pins nor groups\n",
+                       np->name);
+               return;
+       }
+
+       if (pins && groups) {
+               dev_err(pctldev->dev, "%s defines both pins and groups\n",
+                       np->name);
+               return;
+       }
+
        ret = of_property_read_string(np, "lantiq,function", &function);
-       if (!ret) {
+       if (groups && !ret) {
                of_property_for_each_string(np, "lantiq,groups", prop, group) {
                        (*map)->type = PIN_MAP_TYPE_MUX_GROUP;
                        (*map)->name = function;
@@ -85,11 +99,6 @@ static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
                        (*map)->data.mux.function = function;
                        (*map)++;
                }
-               if (of_find_property(np, "lantiq,pins", NULL))
-                       dev_err(pctldev->dev,
-                               "%s mixes pins and groups settings\n",
-                               np->name);
-               return 0;
        }
 
        for (i = 0; i < info->num_params; i++) {
@@ -103,7 +112,7 @@ static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
        }
 
        if (!num_configs)
-               return -EINVAL;
+               return;
 
        of_property_for_each_string(np, "lantiq,pins", prop, pin) {
                (*map)->data.configs.configs = kmemdup(configs,
@@ -115,7 +124,16 @@ static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
                (*map)->data.configs.num_configs = num_configs;
                (*map)++;
        }
-       return 0;
+       of_property_for_each_string(np, "lantiq,groups", prop, group) {
+               (*map)->data.configs.configs = kmemdup(configs,
+                                       num_configs * sizeof(unsigned long),
+                                       GFP_KERNEL);
+               (*map)->type = PIN_MAP_TYPE_CONFIGS_GROUP;
+               (*map)->name = group;
+               (*map)->data.configs.group_or_pin = group;
+               (*map)->data.configs.num_configs = num_configs;
+               (*map)++;
+       }
 }
 
 static int ltq_pinctrl_dt_subnode_size(struct device_node *np)
@@ -135,23 +153,19 @@ static int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 {
        struct pinctrl_map *tmp;
        struct device_node *np;
-       int ret;
+       int max_maps = 0;
 
-       *num_maps = 0;
        for_each_child_of_node(np_config, np)
-               *num_maps += ltq_pinctrl_dt_subnode_size(np);
-       *map = kzalloc(*num_maps * sizeof(struct pinctrl_map), GFP_KERNEL);
+               max_maps += ltq_pinctrl_dt_subnode_size(np);
+       *map = kzalloc(max_maps * sizeof(struct pinctrl_map) * 2, GFP_KERNEL);
        if (!*map)
                return -ENOMEM;
        tmp = *map;
 
-       for_each_child_of_node(np_config, np) {
-               ret = ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp);
-               if (ret < 0) {
-                       ltq_pinctrl_dt_free_map(pctldev, *map, *num_maps);
-                       return ret;
-               }
-       }
+       for_each_child_of_node(np_config, np)
+               ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp);
+       *num_maps = ((int)(tmp - *map));
+
        return 0;
 }
 
index c49c9db..aa4c8b8 100644 (file)
@@ -522,9 +522,24 @@ static int xway_pinconf_set(struct pinctrl_dev *pctldev,
        return 0;
 }
 
+int xway_pinconf_group_set(struct pinctrl_dev *pctldev,
+                       unsigned selector,
+                       unsigned long config)
+{
+       struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
+       int i, ret = 0;
+
+       for (i = 0; i < info->grps[selector].npins && !ret; i++)
+               ret = xway_pinconf_set(pctldev,
+                               info->grps[selector].pins[i], config);
+
+       return ret;
+}
+
 static struct pinconf_ops xway_pinconf_ops = {
        .pin_config_get = xway_pinconf_get,
        .pin_config_set = xway_pinconf_set,
+       .pin_config_group_set = xway_pinconf_group_set,
 };
 
 static struct pinctrl_desc xway_pctrl_desc = {