0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define pr_fmt(fmt) "generic pinconfig core: " fmt
0012
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/init.h>
0016 #include <linux/device.h>
0017 #include <linux/slab.h>
0018 #include <linux/debugfs.h>
0019 #include <linux/seq_file.h>
0020 #include <linux/pinctrl/pinctrl.h>
0021 #include <linux/pinctrl/pinconf.h>
0022 #include <linux/pinctrl/pinconf-generic.h>
0023 #include <linux/of.h>
0024 #include "core.h"
0025 #include "pinconf.h"
0026 #include "pinctrl-utils.h"
0027
0028 #ifdef CONFIG_DEBUG_FS
0029 static const struct pin_config_item conf_items[] = {
0030 PCONFDUMP(PIN_CONFIG_BIAS_BUS_HOLD, "input bias bus hold", NULL, false),
0031 PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL, false),
0032 PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL, false),
0033 PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", "ohms", true),
0034 PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
0035 "input bias pull to pin specific state", "ohms", true),
0036 PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", "ohms", true),
0037 PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL, false),
0038 PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL, false),
0039 PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL, false),
0040 PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH, "output drive strength", "mA", true),
0041 PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH_UA, "output drive strength", "uA", true),
0042 PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "usec", true),
0043 PCONFDUMP(PIN_CONFIG_INPUT_ENABLE, "input enabled", NULL, false),
0044 PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL, false),
0045 PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_ENABLE, "input schmitt enabled", NULL, false),
0046 PCONFDUMP(PIN_CONFIG_MODE_LOW_POWER, "pin low power", "mode", true),
0047 PCONFDUMP(PIN_CONFIG_OUTPUT_ENABLE, "output enabled", NULL, false),
0048 PCONFDUMP(PIN_CONFIG_OUTPUT, "pin output", "level", true),
0049 PCONFDUMP(PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS, "output impedance", "ohms", true),
0050 PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector", true),
0051 PCONFDUMP(PIN_CONFIG_SLEEP_HARDWARE_STATE, "sleep hardware state", NULL, false),
0052 PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL, true),
0053 PCONFDUMP(PIN_CONFIG_SKEW_DELAY, "skew delay", NULL, true),
0054 };
0055
0056 static void pinconf_generic_dump_one(struct pinctrl_dev *pctldev,
0057 struct seq_file *s, const char *gname,
0058 unsigned pin,
0059 const struct pin_config_item *items,
0060 int nitems, int *print_sep)
0061 {
0062 int i;
0063
0064 for (i = 0; i < nitems; i++) {
0065 unsigned long config;
0066 int ret;
0067
0068
0069 config = pinconf_to_config_packed(items[i].param, 0);
0070 if (gname)
0071 ret = pin_config_group_get(dev_name(pctldev->dev),
0072 gname, &config);
0073 else
0074 ret = pin_config_get_for_pin(pctldev, pin, &config);
0075
0076 if (ret == -EINVAL || ret == -ENOTSUPP)
0077 continue;
0078 if (ret) {
0079 seq_printf(s, "ERROR READING CONFIG SETTING %d ", i);
0080 continue;
0081 }
0082
0083 if (*print_sep)
0084 seq_puts(s, ", ");
0085 *print_sep = 1;
0086 seq_puts(s, items[i].display);
0087
0088 if (items[i].has_arg) {
0089 seq_printf(s, " (%u",
0090 pinconf_to_config_argument(config));
0091 if (items[i].format)
0092 seq_printf(s, " %s)", items[i].format);
0093 else
0094 seq_puts(s, ")");
0095 }
0096 }
0097 }
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110 void pinconf_generic_dump_pins(struct pinctrl_dev *pctldev, struct seq_file *s,
0111 const char *gname, unsigned pin)
0112 {
0113 const struct pinconf_ops *ops = pctldev->desc->confops;
0114 int print_sep = 0;
0115
0116 if (!ops->is_generic)
0117 return;
0118
0119
0120 pinconf_generic_dump_one(pctldev, s, gname, pin, conf_items,
0121 ARRAY_SIZE(conf_items), &print_sep);
0122
0123 if (pctldev->desc->num_custom_params &&
0124 pctldev->desc->custom_conf_items)
0125 pinconf_generic_dump_one(pctldev, s, gname, pin,
0126 pctldev->desc->custom_conf_items,
0127 pctldev->desc->num_custom_params,
0128 &print_sep);
0129 }
0130
0131 void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
0132 struct seq_file *s, unsigned long config)
0133 {
0134 int i;
0135
0136 for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
0137 if (pinconf_to_config_param(config) != conf_items[i].param)
0138 continue;
0139 seq_printf(s, "%s: 0x%x", conf_items[i].display,
0140 pinconf_to_config_argument(config));
0141 }
0142
0143 if (!pctldev->desc->num_custom_params ||
0144 !pctldev->desc->custom_conf_items)
0145 return;
0146
0147 for (i = 0; i < pctldev->desc->num_custom_params; i++) {
0148 if (pinconf_to_config_param(config) !=
0149 pctldev->desc->custom_conf_items[i].param)
0150 continue;
0151 seq_printf(s, "%s: 0x%x",
0152 pctldev->desc->custom_conf_items[i].display,
0153 pinconf_to_config_argument(config));
0154 }
0155 }
0156 EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
0157 #endif
0158
0159 #ifdef CONFIG_OF
0160 static const struct pinconf_generic_params dt_params[] = {
0161 { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
0162 { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
0163 { "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
0164 { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
0165 { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
0166 { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
0167 { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
0168 { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
0169 { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
0170 { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
0171 { "drive-strength-microamp", PIN_CONFIG_DRIVE_STRENGTH_UA, 0 },
0172 { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
0173 { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
0174 { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
0175 { "input-schmitt", PIN_CONFIG_INPUT_SCHMITT, 0 },
0176 { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
0177 { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
0178 { "low-power-disable", PIN_CONFIG_MODE_LOW_POWER, 0 },
0179 { "low-power-enable", PIN_CONFIG_MODE_LOW_POWER, 1 },
0180 { "output-disable", PIN_CONFIG_OUTPUT_ENABLE, 0 },
0181 { "output-enable", PIN_CONFIG_OUTPUT_ENABLE, 1 },
0182 { "output-high", PIN_CONFIG_OUTPUT, 1, },
0183 { "output-impedance-ohms", PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS, 0 },
0184 { "output-low", PIN_CONFIG_OUTPUT, 0, },
0185 { "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
0186 { "sleep-hardware-state", PIN_CONFIG_SLEEP_HARDWARE_STATE, 0 },
0187 { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
0188 { "skew-delay", PIN_CONFIG_SKEW_DELAY, 0 },
0189 };
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204 static void parse_dt_cfg(struct device_node *np,
0205 const struct pinconf_generic_params *params,
0206 unsigned int count, unsigned long *cfg,
0207 unsigned int *ncfg)
0208 {
0209 int i;
0210
0211 for (i = 0; i < count; i++) {
0212 u32 val;
0213 int ret;
0214 const struct pinconf_generic_params *par = ¶ms[i];
0215
0216 ret = of_property_read_u32(np, par->property, &val);
0217
0218
0219 if (ret == -EINVAL)
0220 continue;
0221
0222
0223 if (ret)
0224 val = par->default_value;
0225
0226 pr_debug("found %s with value %u\n", par->property, val);
0227 cfg[*ncfg] = pinconf_to_config_packed(par->param, val);
0228 (*ncfg)++;
0229 }
0230 }
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 int pinconf_generic_parse_dt_config(struct device_node *np,
0242 struct pinctrl_dev *pctldev,
0243 unsigned long **configs,
0244 unsigned int *nconfigs)
0245 {
0246 unsigned long *cfg;
0247 unsigned int max_cfg, ncfg = 0;
0248 int ret;
0249
0250 if (!np)
0251 return -EINVAL;
0252
0253
0254 max_cfg = ARRAY_SIZE(dt_params);
0255 if (pctldev)
0256 max_cfg += pctldev->desc->num_custom_params;
0257 cfg = kcalloc(max_cfg, sizeof(*cfg), GFP_KERNEL);
0258 if (!cfg)
0259 return -ENOMEM;
0260
0261 parse_dt_cfg(np, dt_params, ARRAY_SIZE(dt_params), cfg, &ncfg);
0262 if (pctldev && pctldev->desc->num_custom_params &&
0263 pctldev->desc->custom_params)
0264 parse_dt_cfg(np, pctldev->desc->custom_params,
0265 pctldev->desc->num_custom_params, cfg, &ncfg);
0266
0267 ret = 0;
0268
0269
0270 if (ncfg == 0) {
0271 *configs = NULL;
0272 *nconfigs = 0;
0273 goto out;
0274 }
0275
0276
0277
0278
0279
0280 *configs = kmemdup(cfg, ncfg * sizeof(unsigned long), GFP_KERNEL);
0281 if (!*configs) {
0282 ret = -ENOMEM;
0283 goto out;
0284 }
0285
0286 *nconfigs = ncfg;
0287
0288 out:
0289 kfree(cfg);
0290 return ret;
0291 }
0292 EXPORT_SYMBOL_GPL(pinconf_generic_parse_dt_config);
0293
0294 int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
0295 struct device_node *np, struct pinctrl_map **map,
0296 unsigned *reserved_maps, unsigned *num_maps,
0297 enum pinctrl_map_type type)
0298 {
0299 int ret;
0300 const char *function;
0301 struct device *dev = pctldev->dev;
0302 unsigned long *configs = NULL;
0303 unsigned num_configs = 0;
0304 unsigned reserve, strings_count;
0305 struct property *prop;
0306 const char *group;
0307 const char *subnode_target_type = "pins";
0308
0309 ret = of_property_count_strings(np, "pins");
0310 if (ret < 0) {
0311 ret = of_property_count_strings(np, "groups");
0312 if (ret < 0)
0313
0314 return 0;
0315 if (type == PIN_MAP_TYPE_INVALID)
0316 type = PIN_MAP_TYPE_CONFIGS_GROUP;
0317 subnode_target_type = "groups";
0318 } else {
0319 if (type == PIN_MAP_TYPE_INVALID)
0320 type = PIN_MAP_TYPE_CONFIGS_PIN;
0321 }
0322 strings_count = ret;
0323
0324 ret = of_property_read_string(np, "function", &function);
0325 if (ret < 0) {
0326
0327 if (ret != -EINVAL)
0328 dev_err(dev, "%pOF: could not parse property function\n",
0329 np);
0330 function = NULL;
0331 }
0332
0333 ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
0334 &num_configs);
0335 if (ret < 0) {
0336 dev_err(dev, "%pOF: could not parse node property\n", np);
0337 return ret;
0338 }
0339
0340 reserve = 0;
0341 if (function != NULL)
0342 reserve++;
0343 if (num_configs)
0344 reserve++;
0345
0346 reserve *= strings_count;
0347
0348 ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps,
0349 num_maps, reserve);
0350 if (ret < 0)
0351 goto exit;
0352
0353 of_property_for_each_string(np, subnode_target_type, prop, group) {
0354 if (function) {
0355 ret = pinctrl_utils_add_map_mux(pctldev, map,
0356 reserved_maps, num_maps, group,
0357 function);
0358 if (ret < 0)
0359 goto exit;
0360 }
0361
0362 if (num_configs) {
0363 ret = pinctrl_utils_add_map_configs(pctldev, map,
0364 reserved_maps, num_maps, group, configs,
0365 num_configs, type);
0366 if (ret < 0)
0367 goto exit;
0368 }
0369 }
0370 ret = 0;
0371
0372 exit:
0373 kfree(configs);
0374 return ret;
0375 }
0376 EXPORT_SYMBOL_GPL(pinconf_generic_dt_subnode_to_map);
0377
0378 int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev,
0379 struct device_node *np_config, struct pinctrl_map **map,
0380 unsigned *num_maps, enum pinctrl_map_type type)
0381 {
0382 unsigned reserved_maps;
0383 struct device_node *np;
0384 int ret;
0385
0386 reserved_maps = 0;
0387 *map = NULL;
0388 *num_maps = 0;
0389
0390 ret = pinconf_generic_dt_subnode_to_map(pctldev, np_config, map,
0391 &reserved_maps, num_maps, type);
0392 if (ret < 0)
0393 goto exit;
0394
0395 for_each_available_child_of_node(np_config, np) {
0396 ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map,
0397 &reserved_maps, num_maps, type);
0398 if (ret < 0)
0399 goto exit;
0400 }
0401 return 0;
0402
0403 exit:
0404 pinctrl_utils_free_map(pctldev, *map, *num_maps);
0405 return ret;
0406 }
0407 EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map);
0408
0409 void pinconf_generic_dt_free_map(struct pinctrl_dev *pctldev,
0410 struct pinctrl_map *map,
0411 unsigned num_maps)
0412 {
0413 pinctrl_utils_free_map(pctldev, map, num_maps);
0414 }
0415 EXPORT_SYMBOL_GPL(pinconf_generic_dt_free_map);
0416
0417 #endif