aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-lantiq.c
diff options
context:
space:
mode:
authorJohn Crispin <blogic@openwrt.org>2013-02-01 07:04:57 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-02-05 10:17:22 -0500
commit3a6b04ca33a225dd64fcd5f4469b7b1088f16c37 (patch)
tree0d0d77a81897a81fdbe2f065f65d833927e7ac06 /drivers/pinctrl/pinctrl-lantiq.c
parent7541083fc4d9b24f63ea2e8e7726aeb5b2786176 (diff)
pinctrl/lantiq: add pin_config_group_set support
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>
Diffstat (limited to 'drivers/pinctrl/pinctrl-lantiq.c')
-rw-r--r--drivers/pinctrl/pinctrl-lantiq.c54
1 files changed, 34 insertions, 20 deletions
diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c
index 15f501d89026..7d110722dfd1 100644
--- a/drivers/pinctrl/pinctrl-lantiq.c
+++ b/drivers/pinctrl/pinctrl-lantiq.c
@@ -64,11 +64,13 @@ static void ltq_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
64 seq_printf(s, " %s", dev_name(pctldev->dev)); 64 seq_printf(s, " %s", dev_name(pctldev->dev));
65} 65}
66 66
67static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, 67static void ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
68 struct device_node *np, 68 struct device_node *np,
69 struct pinctrl_map **map) 69 struct pinctrl_map **map)
70{ 70{
71 struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev); 71 struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
72 struct property *pins = of_find_property(np, "lantiq,pins", NULL);
73 struct property *groups = of_find_property(np, "lantiq,groups", NULL);
72 unsigned long configs[3]; 74 unsigned long configs[3];
73 unsigned num_configs = 0; 75 unsigned num_configs = 0;
74 struct property *prop; 76 struct property *prop;
@@ -76,8 +78,20 @@ static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
76 const char *function; 78 const char *function;
77 int ret, i; 79 int ret, i;
78 80
81 if (!pins && !groups) {
82 dev_err(pctldev->dev, "%s defines neither pins nor groups\n",
83 np->name);
84 return;
85 }
86
87 if (pins && groups) {
88 dev_err(pctldev->dev, "%s defines both pins and groups\n",
89 np->name);
90 return;
91 }
92
79 ret = of_property_read_string(np, "lantiq,function", &function); 93 ret = of_property_read_string(np, "lantiq,function", &function);
80 if (!ret) { 94 if (groups && !ret) {
81 of_property_for_each_string(np, "lantiq,groups", prop, group) { 95 of_property_for_each_string(np, "lantiq,groups", prop, group) {
82 (*map)->type = PIN_MAP_TYPE_MUX_GROUP; 96 (*map)->type = PIN_MAP_TYPE_MUX_GROUP;
83 (*map)->name = function; 97 (*map)->name = function;
@@ -85,11 +99,6 @@ static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
85 (*map)->data.mux.function = function; 99 (*map)->data.mux.function = function;
86 (*map)++; 100 (*map)++;
87 } 101 }
88 if (of_find_property(np, "lantiq,pins", NULL))
89 dev_err(pctldev->dev,
90 "%s mixes pins and groups settings\n",
91 np->name);
92 return 0;
93 } 102 }
94 103
95 for (i = 0; i < info->num_params; i++) { 104 for (i = 0; i < info->num_params; i++) {
@@ -103,7 +112,7 @@ static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
103 } 112 }
104 113
105 if (!num_configs) 114 if (!num_configs)
106 return -EINVAL; 115 return;
107 116
108 of_property_for_each_string(np, "lantiq,pins", prop, pin) { 117 of_property_for_each_string(np, "lantiq,pins", prop, pin) {
109 (*map)->data.configs.configs = kmemdup(configs, 118 (*map)->data.configs.configs = kmemdup(configs,
@@ -115,7 +124,16 @@ static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
115 (*map)->data.configs.num_configs = num_configs; 124 (*map)->data.configs.num_configs = num_configs;
116 (*map)++; 125 (*map)++;
117 } 126 }
118 return 0; 127 of_property_for_each_string(np, "lantiq,groups", prop, group) {
128 (*map)->data.configs.configs = kmemdup(configs,
129 num_configs * sizeof(unsigned long),
130 GFP_KERNEL);
131 (*map)->type = PIN_MAP_TYPE_CONFIGS_GROUP;
132 (*map)->name = group;
133 (*map)->data.configs.group_or_pin = group;
134 (*map)->data.configs.num_configs = num_configs;
135 (*map)++;
136 }
119} 137}
120 138
121static int ltq_pinctrl_dt_subnode_size(struct device_node *np) 139static 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,
135{ 153{
136 struct pinctrl_map *tmp; 154 struct pinctrl_map *tmp;
137 struct device_node *np; 155 struct device_node *np;
138 int ret; 156 int max_maps = 0;
139 157
140 *num_maps = 0;
141 for_each_child_of_node(np_config, np) 158 for_each_child_of_node(np_config, np)
142 *num_maps += ltq_pinctrl_dt_subnode_size(np); 159 max_maps += ltq_pinctrl_dt_subnode_size(np);
143 *map = kzalloc(*num_maps * sizeof(struct pinctrl_map), GFP_KERNEL); 160 *map = kzalloc(max_maps * sizeof(struct pinctrl_map) * 2, GFP_KERNEL);
144 if (!*map) 161 if (!*map)
145 return -ENOMEM; 162 return -ENOMEM;
146 tmp = *map; 163 tmp = *map;
147 164
148 for_each_child_of_node(np_config, np) { 165 for_each_child_of_node(np_config, np)
149 ret = ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp); 166 ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp);
150 if (ret < 0) { 167 *num_maps = ((int)(tmp - *map));
151 ltq_pinctrl_dt_free_map(pctldev, *map, *num_maps); 168
152 return ret;
153 }
154 }
155 return 0; 169 return 0;
156} 170}
157 171