aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/sh-pfc/pinctrl.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2013-06-17 14:50:03 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-06-18 04:57:59 -0400
commit12f3ad8df7f58c61ff16ea851541583693d965e1 (patch)
tree8842483822ff6fd4c60b769088452e7d113b47bb /drivers/pinctrl/sh-pfc/pinctrl.c
parentfe1c9a822ce72c6ec8476a2501c412265ee2172c (diff)
sh-pfc: Add pinconf support to DT bindings
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Acked-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/sh-pfc/pinctrl.c')
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c109
1 files changed, 97 insertions, 12 deletions
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index 7e32bb8c08dd..2cf23476adf8 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -74,6 +74,27 @@ static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
74 seq_printf(s, "%s", DRV_NAME); 74 seq_printf(s, "%s", DRV_NAME);
75} 75}
76 76
77static int sh_pfc_map_add_config(struct pinctrl_map *map,
78 const char *group_or_pin,
79 enum pinctrl_map_type type,
80 unsigned long *configs,
81 unsigned int num_configs)
82{
83 unsigned long *cfgs;
84
85 cfgs = kmemdup(configs, num_configs * sizeof(*cfgs),
86 GFP_KERNEL);
87 if (cfgs == NULL)
88 return -ENOMEM;
89
90 map->type = type;
91 map->data.configs.group_or_pin = group_or_pin;
92 map->data.configs.configs = cfgs;
93 map->data.configs.num_configs = num_configs;
94
95 return 0;
96}
97
77static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np, 98static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
78 struct pinctrl_map **map, 99 struct pinctrl_map **map,
79 unsigned int *num_maps, unsigned int *index) 100 unsigned int *num_maps, unsigned int *index)
@@ -81,9 +102,14 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
81 struct pinctrl_map *maps = *map; 102 struct pinctrl_map *maps = *map;
82 unsigned int nmaps = *num_maps; 103 unsigned int nmaps = *num_maps;
83 unsigned int idx = *index; 104 unsigned int idx = *index;
105 unsigned int num_configs;
84 const char *function = NULL; 106 const char *function = NULL;
107 unsigned long *configs;
85 struct property *prop; 108 struct property *prop;
109 unsigned int num_groups;
110 unsigned int num_pins;
86 const char *group; 111 const char *group;
112 const char *pin;
87 int ret; 113 int ret;
88 114
89 /* Parse the function and configuration properties. At least a function 115 /* Parse the function and configuration properties. At least a function
@@ -95,25 +121,47 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
95 return ret; 121 return ret;
96 } 122 }
97 123
98 if (!function) { 124 ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs);
99 dev_err(dev, "DT node must contain at least one function\n"); 125 if (ret < 0)
126 return ret;
127
128 if (!function && num_configs == 0) {
129 dev_err(dev,
130 "DT node must contain at least a function or config\n");
100 goto done; 131 goto done;
101 } 132 }
102 133
103 /* Count the number of groups and reallocate mappings. */ 134 /* Count the number of pins and groups and reallocate mappings. */
135 ret = of_property_count_strings(np, "renesas,pins");
136 if (ret == -EINVAL) {
137 num_pins = 0;
138 } else if (ret < 0) {
139 dev_err(dev, "Invalid pins list in DT\n");
140 goto done;
141 } else {
142 num_pins = ret;
143 }
144
104 ret = of_property_count_strings(np, "renesas,groups"); 145 ret = of_property_count_strings(np, "renesas,groups");
105 if (ret < 0 && ret != -EINVAL) { 146 if (ret == -EINVAL) {
147 num_groups = 0;
148 } else if (ret < 0) {
106 dev_err(dev, "Invalid pin groups list in DT\n"); 149 dev_err(dev, "Invalid pin groups list in DT\n");
107 goto done; 150 goto done;
151 } else {
152 num_groups = ret;
108 } 153 }
109 154
110 if (!ret) { 155 if (!num_pins && !num_groups) {
111 dev_err(dev, "No group provided in DT node\n"); 156 dev_err(dev, "No pin or group provided in DT node\n");
112 ret = -ENODEV; 157 ret = -ENODEV;
113 goto done; 158 goto done;
114 } 159 }
115 160
116 nmaps += ret; 161 if (function)
162 nmaps += num_groups;
163 if (configs)
164 nmaps += num_pins + num_groups;
117 165
118 maps = krealloc(maps, sizeof(*maps) * nmaps, GFP_KERNEL); 166 maps = krealloc(maps, sizeof(*maps) * nmaps, GFP_KERNEL);
119 if (maps == NULL) { 167 if (maps == NULL) {
@@ -126,22 +174,59 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
126 174
127 /* Iterate over pins and groups and create the mappings. */ 175 /* Iterate over pins and groups and create the mappings. */
128 of_property_for_each_string(np, "renesas,groups", prop, group) { 176 of_property_for_each_string(np, "renesas,groups", prop, group) {
129 maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; 177 if (function) {
130 maps[idx].data.mux.group = group; 178 maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
131 maps[idx].data.mux.function = function; 179 maps[idx].data.mux.group = group;
132 idx++; 180 maps[idx].data.mux.function = function;
181 idx++;
182 }
183
184 if (configs) {
185 ret = sh_pfc_map_add_config(&maps[idx], group,
186 PIN_MAP_TYPE_CONFIGS_GROUP,
187 configs, num_configs);
188 if (ret < 0)
189 goto done;
190
191 idx++;
192 }
133 } 193 }
134 194
135 ret = 0; 195 if (!configs) {
196 ret = 0;
197 goto done;
198 }
199
200 of_property_for_each_string(np, "renesas,pins", prop, pin) {
201 ret = sh_pfc_map_add_config(&maps[idx], pin,
202 PIN_MAP_TYPE_CONFIGS_PIN,
203 configs, num_configs);
204 if (ret < 0)
205 goto done;
206
207 idx++;
208 }
136 209
137done: 210done:
138 *index = idx; 211 *index = idx;
212 kfree(configs);
139 return ret; 213 return ret;
140} 214}
141 215
142static void sh_pfc_dt_free_map(struct pinctrl_dev *pctldev, 216static void sh_pfc_dt_free_map(struct pinctrl_dev *pctldev,
143 struct pinctrl_map *map, unsigned num_maps) 217 struct pinctrl_map *map, unsigned num_maps)
144{ 218{
219 unsigned int i;
220
221 if (map == NULL)
222 return;
223
224 for (i = 0; i < num_maps; ++i) {
225 if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP ||
226 map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
227 kfree(map[i].data.configs.configs);
228 }
229
145 kfree(map); 230 kfree(map);
146} 231}
147 232