1 /* 2 * Core driver for the generic pin config portions of the pin control subsystem 3 * 4 * Copyright (C) 2011 ST-Ericsson SA 5 * Written on behalf of Linaro for ST-Ericsson 6 * 7 * Author: Linus Walleij <linus.walleij@linaro.org> 8 * 9 * License terms: GNU General Public License (GPL) version 2 10 */ 11 12 #define pr_fmt(fmt) "generic pinconfig core: " fmt 13 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/init.h> 17 #include <linux/device.h> 18 #include <linux/slab.h> 19 #include <linux/debugfs.h> 20 #include <linux/seq_file.h> 21 #include <linux/pinctrl/pinctrl.h> 22 #include <linux/pinctrl/pinconf.h> 23 #include <linux/pinctrl/pinconf-generic.h> 24 #include "core.h" 25 #include "pinconf.h" 26 27 #ifdef CONFIG_DEBUG_FS 28 29 struct pin_config_item { 30 const enum pin_config_param param; 31 const char * const display; 32 const char * const format; 33 }; 34 35 #define PCONFDUMP(a, b, c) { .param = a, .display = b, .format = c } 36 37 static struct pin_config_item conf_items[] = { 38 PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL), 39 PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL), 40 PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL), 41 PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL), 42 PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL), 43 PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL), 44 PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL), 45 PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_ENABLE, "input schmitt enabled", NULL), 46 PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL), 47 PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"), 48 PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector"), 49 PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL), 50 PCONFDUMP(PIN_CONFIG_LOW_POWER_MODE, "pin low power", "mode"), 51 PCONFDUMP(PIN_CONFIG_OUTPUT, "pin output", "level"), 52 }; 53 54 void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev, 55 struct seq_file *s, unsigned pin) 56 { 57 const struct pinconf_ops *ops = pctldev->desc->confops; 58 int i; 59 60 if (!ops->is_generic) 61 return; 62 63 for (i = 0; i < ARRAY_SIZE(conf_items); i++) { 64 unsigned long config; 65 int ret; 66 67 /* We want to check out this parameter */ 68 config = pinconf_to_config_packed(conf_items[i].param, 0); 69 ret = pin_config_get_for_pin(pctldev, pin, &config); 70 /* These are legal errors */ 71 if (ret == -EINVAL || ret == -ENOTSUPP) 72 continue; 73 if (ret) { 74 seq_printf(s, "ERROR READING CONFIG SETTING %d ", i); 75 continue; 76 } 77 /* Space between multiple configs */ 78 seq_puts(s, " "); 79 seq_puts(s, conf_items[i].display); 80 /* Print unit if available */ 81 if (conf_items[i].format && 82 pinconf_to_config_argument(config) != 0) 83 seq_printf(s, " (%u %s)", 84 pinconf_to_config_argument(config), 85 conf_items[i].format); 86 } 87 } 88 89 void pinconf_generic_dump_group(struct pinctrl_dev *pctldev, 90 struct seq_file *s, const char *gname) 91 { 92 const struct pinconf_ops *ops = pctldev->desc->confops; 93 int i; 94 95 if (!ops->is_generic) 96 return; 97 98 for (i = 0; i < ARRAY_SIZE(conf_items); i++) { 99 unsigned long config; 100 int ret; 101 102 /* We want to check out this parameter */ 103 config = pinconf_to_config_packed(conf_items[i].param, 0); 104 ret = pin_config_group_get(dev_name(pctldev->dev), gname, 105 &config); 106 /* These are legal errors */ 107 if (ret == -EINVAL || ret == -ENOTSUPP) 108 continue; 109 if (ret) { 110 seq_printf(s, "ERROR READING CONFIG SETTING %d ", i); 111 continue; 112 } 113 /* Space between multiple configs */ 114 seq_puts(s, " "); 115 seq_puts(s, conf_items[i].display); 116 /* Print unit if available */ 117 if (conf_items[i].format && config != 0) 118 seq_printf(s, " (%u %s)", 119 pinconf_to_config_argument(config), 120 conf_items[i].format); 121 } 122 } 123 124 void pinconf_generic_dump_config(struct pinctrl_dev *pctldev, 125 struct seq_file *s, unsigned long config) 126 { 127 int i; 128 129 for (i = 0; i < ARRAY_SIZE(conf_items); i++) { 130 if (pinconf_to_config_param(config) != conf_items[i].param) 131 continue; 132 seq_printf(s, "%s: 0x%x", conf_items[i].display, 133 pinconf_to_config_argument(config)); 134 } 135 } 136 EXPORT_SYMBOL_GPL(pinconf_generic_dump_config); 137 #endif 138