aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinconf.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2012-03-02 15:05:48 -0500
committerLinus Walleij <linus.walleij@linaro.org>2012-03-05 05:25:11 -0500
commit1e2082b520721734c358f776d34a069867214c8e (patch)
tree4d11e15a4127ad69faf7555864480a6fafe5422c /drivers/pinctrl/pinconf.c
parent6e5e959dde0d92d177f035652aeaa77f9330c9c6 (diff)
pinctrl: enhance mapping table to support pin config operations
The pinctrl mapping table can now contain entries to: * Set the mux function of a pin group * Apply a set of pin config options to a pin or a group This allows pinctrl_select_state() to apply pin configs settings as well as mux settings. v3: Fix find_pinctrl() to iterate over the correct list. s/_MUX_CONFIGS_/_CONFIGS_/ in mapping table macros. Fix documentation to use correct mapping table macro. v2: Added numerous extra PIN_MAP_*() special-case macros. Fixed kerneldoc typo. Delete pinctrl_get_pin_id() and replace it with pin_get_from_name(). Various minor fixes. Updates due to rebase. Signed-off-by: Stephen Warren <swarren@nvidia.com> Acked-by: Dong Aisheng <dong.aisheng@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinconf.c')
-rw-r--r--drivers/pinctrl/pinconf.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index e0a453790a40..84869f28b101 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -36,6 +36,24 @@ int pinconf_check_ops(struct pinctrl_dev *pctldev)
36 return 0; 36 return 0;
37} 37}
38 38
39int pinconf_validate_map(struct pinctrl_map const *map, int i)
40{
41 if (!map->data.configs.group_or_pin) {
42 pr_err("failed to register map %s (%d): no group/pin given\n",
43 map->name, i);
44 return -EINVAL;
45 }
46
47 if (map->data.configs.num_configs &&
48 !map->data.configs.configs) {
49 pr_err("failed to register map %s (%d): no configs ptr given\n",
50 map->name, i);
51 return -EINVAL;
52 }
53
54 return 0;
55}
56
39static int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, 57static int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
40 unsigned long *config) 58 unsigned long *config)
41{ 59{
@@ -260,8 +278,155 @@ unlock:
260} 278}
261EXPORT_SYMBOL(pin_config_group_set); 279EXPORT_SYMBOL(pin_config_group_set);
262 280
281int pinconf_map_to_setting(struct pinctrl_map const *map,
282 struct pinctrl_setting *setting)
283{
284 struct pinctrl_dev *pctldev = setting->pctldev;
285
286 switch (setting->type) {
287 case PIN_MAP_TYPE_CONFIGS_PIN:
288 setting->data.configs.group_or_pin =
289 pin_get_from_name(pctldev,
290 map->data.configs.group_or_pin);
291 if (setting->data.configs.group_or_pin < 0)
292 return setting->data.configs.group_or_pin;
293 break;
294 case PIN_MAP_TYPE_CONFIGS_GROUP:
295 setting->data.configs.group_or_pin =
296 pinctrl_get_group_selector(pctldev,
297 map->data.configs.group_or_pin);
298 if (setting->data.configs.group_or_pin < 0)
299 return setting->data.configs.group_or_pin;
300 break;
301 default:
302 return -EINVAL;
303 }
304
305 setting->data.configs.num_configs = map->data.configs.num_configs;
306 setting->data.configs.configs = map->data.configs.configs;
307
308 return 0;
309}
310
311void pinconf_free_setting(struct pinctrl_setting const *setting)
312{
313}
314
315int pinconf_apply_setting(struct pinctrl_setting const *setting)
316{
317 struct pinctrl_dev *pctldev = setting->pctldev;
318 const struct pinconf_ops *ops = pctldev->desc->confops;
319 int i, ret;
320
321 if (!ops) {
322 dev_err(pctldev->dev, "missing confops\n");
323 return -EINVAL;
324 }
325
326 switch (setting->type) {
327 case PIN_MAP_TYPE_CONFIGS_PIN:
328 if (!ops->pin_config_set) {
329 dev_err(pctldev->dev, "missing pin_config_set op\n");
330 return -EINVAL;
331 }
332 for (i = 0; i < setting->data.configs.num_configs; i++) {
333 ret = ops->pin_config_set(pctldev,
334 setting->data.configs.group_or_pin,
335 setting->data.configs.configs[i]);
336 if (ret < 0) {
337 dev_err(pctldev->dev,
338 "pin_config_set op failed for pin %d config %08lx\n",
339 setting->data.configs.group_or_pin,
340 setting->data.configs.configs[i]);
341 return ret;
342 }
343 }
344 break;
345 case PIN_MAP_TYPE_CONFIGS_GROUP:
346 if (!ops->pin_config_group_set) {
347 dev_err(pctldev->dev,
348 "missing pin_config_group_set op\n");
349 return -EINVAL;
350 }
351 for (i = 0; i < setting->data.configs.num_configs; i++) {
352 ret = ops->pin_config_group_set(pctldev,
353 setting->data.configs.group_or_pin,
354 setting->data.configs.configs[i]);
355 if (ret < 0) {
356 dev_err(pctldev->dev,
357 "pin_config_group_set op failed for group %d config %08lx\n",
358 setting->data.configs.group_or_pin,
359 setting->data.configs.configs[i]);
360 return ret;
361 }
362 }
363 break;
364 default:
365 return -EINVAL;
366 }
367
368 return 0;
369}
370
263#ifdef CONFIG_DEBUG_FS 371#ifdef CONFIG_DEBUG_FS
264 372
373void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
374{
375 int i;
376
377 switch (map->type) {
378 case PIN_MAP_TYPE_CONFIGS_PIN:
379 seq_printf(s, "pin ");
380 break;
381 case PIN_MAP_TYPE_CONFIGS_GROUP:
382 seq_printf(s, "group ");
383 break;
384 default:
385 break;
386 }
387
388 seq_printf(s, "%s\n", map->data.configs.group_or_pin);
389
390 for (i = 0; i < map->data.configs.num_configs; i++)
391 seq_printf(s, "config %08lx\n", map->data.configs.configs[i]);
392}
393
394void pinconf_show_setting(struct seq_file *s,
395 struct pinctrl_setting const *setting)
396{
397 struct pinctrl_dev *pctldev = setting->pctldev;
398 const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
399 struct pin_desc *desc;
400 int i;
401
402 switch (setting->type) {
403 case PIN_MAP_TYPE_CONFIGS_PIN:
404 desc = pin_desc_get(setting->pctldev,
405 setting->data.configs.group_or_pin);
406 seq_printf(s, "pin %s (%d)",
407 desc->name ? desc->name : "unnamed",
408 setting->data.configs.group_or_pin);
409 break;
410 case PIN_MAP_TYPE_CONFIGS_GROUP:
411 seq_printf(s, "group %s (%d)",
412 pctlops->get_group_name(pctldev,
413 setting->data.configs.group_or_pin),
414 setting->data.configs.group_or_pin);
415 break;
416 default:
417 break;
418 }
419
420 /*
421 * FIXME: We should really get the pin controler to dump the config
422 * values, so they can be decoded to something meaningful.
423 */
424 for (i = 0; i < setting->data.configs.num_configs; i++)
425 seq_printf(s, " %08lx", setting->data.configs.configs[i]);
426
427 seq_printf(s, "\n");
428}
429
265static void pinconf_dump_pin(struct pinctrl_dev *pctldev, 430static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
266 struct seq_file *s, int pin) 431 struct seq_file *s, int pin)
267{ 432{