pinconf.c (9527B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Core driver for the pin config portions of the pin control subsystem 4 * 5 * Copyright (C) 2011 ST-Ericsson SA 6 * Written on behalf of Linaro for ST-Ericsson 7 * 8 * Author: Linus Walleij <linus.walleij@linaro.org> 9 */ 10#define pr_fmt(fmt) "pinconfig core: " fmt 11 12#include <linux/kernel.h> 13#include <linux/module.h> 14#include <linux/init.h> 15#include <linux/device.h> 16#include <linux/slab.h> 17#include <linux/debugfs.h> 18#include <linux/seq_file.h> 19#include <linux/pinctrl/machine.h> 20#include <linux/pinctrl/pinctrl.h> 21#include <linux/pinctrl/pinconf.h> 22#include "core.h" 23#include "pinconf.h" 24 25int pinconf_check_ops(struct pinctrl_dev *pctldev) 26{ 27 const struct pinconf_ops *ops = pctldev->desc->confops; 28 29 /* We have to be able to config the pins in SOME way */ 30 if (!ops->pin_config_set && !ops->pin_config_group_set) { 31 dev_err(pctldev->dev, 32 "pinconf has to be able to set a pins config\n"); 33 return -EINVAL; 34 } 35 return 0; 36} 37 38int pinconf_validate_map(const struct pinctrl_map *map, int i) 39{ 40 if (!map->data.configs.group_or_pin) { 41 pr_err("failed to register map %s (%d): no group/pin given\n", 42 map->name, i); 43 return -EINVAL; 44 } 45 46 if (!map->data.configs.num_configs || 47 !map->data.configs.configs) { 48 pr_err("failed to register map %s (%d): no configs given\n", 49 map->name, i); 50 return -EINVAL; 51 } 52 53 return 0; 54} 55 56int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, 57 unsigned long *config) 58{ 59 const struct pinconf_ops *ops = pctldev->desc->confops; 60 61 if (!ops || !ops->pin_config_get) { 62 dev_dbg(pctldev->dev, 63 "cannot get pin configuration, .pin_config_get missing in driver\n"); 64 return -ENOTSUPP; 65 } 66 67 return ops->pin_config_get(pctldev, pin, config); 68} 69 70int pin_config_group_get(const char *dev_name, const char *pin_group, 71 unsigned long *config) 72{ 73 struct pinctrl_dev *pctldev; 74 const struct pinconf_ops *ops; 75 int selector, ret; 76 77 pctldev = get_pinctrl_dev_from_devname(dev_name); 78 if (!pctldev) { 79 ret = -EINVAL; 80 return ret; 81 } 82 83 mutex_lock(&pctldev->mutex); 84 85 ops = pctldev->desc->confops; 86 87 if (!ops || !ops->pin_config_group_get) { 88 dev_dbg(pctldev->dev, 89 "cannot get configuration for pin group, missing group config get function in driver\n"); 90 ret = -ENOTSUPP; 91 goto unlock; 92 } 93 94 selector = pinctrl_get_group_selector(pctldev, pin_group); 95 if (selector < 0) { 96 ret = selector; 97 goto unlock; 98 } 99 100 ret = ops->pin_config_group_get(pctldev, selector, config); 101 102unlock: 103 mutex_unlock(&pctldev->mutex); 104 return ret; 105} 106 107int pinconf_map_to_setting(const struct pinctrl_map *map, 108 struct pinctrl_setting *setting) 109{ 110 struct pinctrl_dev *pctldev = setting->pctldev; 111 int pin; 112 113 switch (setting->type) { 114 case PIN_MAP_TYPE_CONFIGS_PIN: 115 pin = pin_get_from_name(pctldev, 116 map->data.configs.group_or_pin); 117 if (pin < 0) { 118 dev_err(pctldev->dev, "could not map pin config for \"%s\"", 119 map->data.configs.group_or_pin); 120 return pin; 121 } 122 setting->data.configs.group_or_pin = pin; 123 break; 124 case PIN_MAP_TYPE_CONFIGS_GROUP: 125 pin = pinctrl_get_group_selector(pctldev, 126 map->data.configs.group_or_pin); 127 if (pin < 0) { 128 dev_err(pctldev->dev, "could not map group config for \"%s\"", 129 map->data.configs.group_or_pin); 130 return pin; 131 } 132 setting->data.configs.group_or_pin = pin; 133 break; 134 default: 135 return -EINVAL; 136 } 137 138 setting->data.configs.num_configs = map->data.configs.num_configs; 139 setting->data.configs.configs = map->data.configs.configs; 140 141 return 0; 142} 143 144void pinconf_free_setting(const struct pinctrl_setting *setting) 145{ 146} 147 148int pinconf_apply_setting(const struct pinctrl_setting *setting) 149{ 150 struct pinctrl_dev *pctldev = setting->pctldev; 151 const struct pinconf_ops *ops = pctldev->desc->confops; 152 int ret; 153 154 if (!ops) { 155 dev_err(pctldev->dev, "missing confops\n"); 156 return -EINVAL; 157 } 158 159 switch (setting->type) { 160 case PIN_MAP_TYPE_CONFIGS_PIN: 161 if (!ops->pin_config_set) { 162 dev_err(pctldev->dev, "missing pin_config_set op\n"); 163 return -EINVAL; 164 } 165 ret = ops->pin_config_set(pctldev, 166 setting->data.configs.group_or_pin, 167 setting->data.configs.configs, 168 setting->data.configs.num_configs); 169 if (ret < 0) { 170 dev_err(pctldev->dev, 171 "pin_config_set op failed for pin %d\n", 172 setting->data.configs.group_or_pin); 173 return ret; 174 } 175 break; 176 case PIN_MAP_TYPE_CONFIGS_GROUP: 177 if (!ops->pin_config_group_set) { 178 dev_err(pctldev->dev, 179 "missing pin_config_group_set op\n"); 180 return -EINVAL; 181 } 182 ret = ops->pin_config_group_set(pctldev, 183 setting->data.configs.group_or_pin, 184 setting->data.configs.configs, 185 setting->data.configs.num_configs); 186 if (ret < 0) { 187 dev_err(pctldev->dev, 188 "pin_config_group_set op failed for group %d\n", 189 setting->data.configs.group_or_pin); 190 return ret; 191 } 192 break; 193 default: 194 return -EINVAL; 195 } 196 197 return 0; 198} 199 200int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin, 201 unsigned long *configs, size_t nconfigs) 202{ 203 const struct pinconf_ops *ops; 204 205 ops = pctldev->desc->confops; 206 if (!ops || !ops->pin_config_set) 207 return -ENOTSUPP; 208 209 return ops->pin_config_set(pctldev, pin, configs, nconfigs); 210} 211 212#ifdef CONFIG_DEBUG_FS 213 214static void pinconf_show_config(struct seq_file *s, struct pinctrl_dev *pctldev, 215 unsigned long *configs, unsigned num_configs) 216{ 217 const struct pinconf_ops *confops; 218 int i; 219 220 if (pctldev) 221 confops = pctldev->desc->confops; 222 else 223 confops = NULL; 224 225 for (i = 0; i < num_configs; i++) { 226 seq_puts(s, "config "); 227 if (confops && confops->pin_config_config_dbg_show) 228 confops->pin_config_config_dbg_show(pctldev, s, 229 configs[i]); 230 else 231 seq_printf(s, "%08lx", configs[i]); 232 seq_putc(s, '\n'); 233 } 234} 235 236void pinconf_show_map(struct seq_file *s, const struct pinctrl_map *map) 237{ 238 struct pinctrl_dev *pctldev; 239 240 pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name); 241 242 switch (map->type) { 243 case PIN_MAP_TYPE_CONFIGS_PIN: 244 seq_puts(s, "pin "); 245 break; 246 case PIN_MAP_TYPE_CONFIGS_GROUP: 247 seq_puts(s, "group "); 248 break; 249 default: 250 break; 251 } 252 253 seq_printf(s, "%s\n", map->data.configs.group_or_pin); 254 255 pinconf_show_config(s, pctldev, map->data.configs.configs, 256 map->data.configs.num_configs); 257} 258 259void pinconf_show_setting(struct seq_file *s, 260 const struct pinctrl_setting *setting) 261{ 262 struct pinctrl_dev *pctldev = setting->pctldev; 263 const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; 264 struct pin_desc *desc; 265 266 switch (setting->type) { 267 case PIN_MAP_TYPE_CONFIGS_PIN: 268 desc = pin_desc_get(setting->pctldev, 269 setting->data.configs.group_or_pin); 270 seq_printf(s, "pin %s (%d)", desc->name, 271 setting->data.configs.group_or_pin); 272 break; 273 case PIN_MAP_TYPE_CONFIGS_GROUP: 274 seq_printf(s, "group %s (%d)", 275 pctlops->get_group_name(pctldev, 276 setting->data.configs.group_or_pin), 277 setting->data.configs.group_or_pin); 278 break; 279 default: 280 break; 281 } 282 283 /* 284 * FIXME: We should really get the pin controller to dump the config 285 * values, so they can be decoded to something meaningful. 286 */ 287 pinconf_show_config(s, pctldev, setting->data.configs.configs, 288 setting->data.configs.num_configs); 289} 290 291static void pinconf_dump_pin(struct pinctrl_dev *pctldev, 292 struct seq_file *s, int pin) 293{ 294 const struct pinconf_ops *ops = pctldev->desc->confops; 295 296 /* no-op when not using generic pin config */ 297 pinconf_generic_dump_pins(pctldev, s, NULL, pin); 298 if (ops && ops->pin_config_dbg_show) 299 ops->pin_config_dbg_show(pctldev, s, pin); 300} 301 302static int pinconf_pins_show(struct seq_file *s, void *what) 303{ 304 struct pinctrl_dev *pctldev = s->private; 305 unsigned i, pin; 306 307 seq_puts(s, "Pin config settings per pin\n"); 308 seq_puts(s, "Format: pin (name): configs\n"); 309 310 mutex_lock(&pctldev->mutex); 311 312 /* The pin number can be retrived from the pin controller descriptor */ 313 for (i = 0; i < pctldev->desc->npins; i++) { 314 struct pin_desc *desc; 315 316 pin = pctldev->desc->pins[i].number; 317 desc = pin_desc_get(pctldev, pin); 318 /* Skip if we cannot search the pin */ 319 if (!desc) 320 continue; 321 322 seq_printf(s, "pin %d (%s): ", pin, desc->name); 323 324 pinconf_dump_pin(pctldev, s, pin); 325 seq_putc(s, '\n'); 326 } 327 328 mutex_unlock(&pctldev->mutex); 329 330 return 0; 331} 332 333static void pinconf_dump_group(struct pinctrl_dev *pctldev, 334 struct seq_file *s, unsigned selector, 335 const char *gname) 336{ 337 const struct pinconf_ops *ops = pctldev->desc->confops; 338 339 /* no-op when not using generic pin config */ 340 pinconf_generic_dump_pins(pctldev, s, gname, 0); 341 if (ops && ops->pin_config_group_dbg_show) 342 ops->pin_config_group_dbg_show(pctldev, s, selector); 343} 344 345static int pinconf_groups_show(struct seq_file *s, void *what) 346{ 347 struct pinctrl_dev *pctldev = s->private; 348 const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; 349 unsigned ngroups = pctlops->get_groups_count(pctldev); 350 unsigned selector = 0; 351 352 seq_puts(s, "Pin config settings per pin group\n"); 353 seq_puts(s, "Format: group (name): configs\n"); 354 355 while (selector < ngroups) { 356 const char *gname = pctlops->get_group_name(pctldev, selector); 357 358 seq_printf(s, "%u (%s): ", selector, gname); 359 pinconf_dump_group(pctldev, s, selector, gname); 360 seq_putc(s, '\n'); 361 selector++; 362 } 363 364 return 0; 365} 366 367DEFINE_SHOW_ATTRIBUTE(pinconf_pins); 368DEFINE_SHOW_ATTRIBUTE(pinconf_groups); 369 370void pinconf_init_device_debugfs(struct dentry *devroot, 371 struct pinctrl_dev *pctldev) 372{ 373 debugfs_create_file("pinconf-pins", 0444, 374 devroot, pctldev, &pinconf_pins_fops); 375 debugfs_create_file("pinconf-groups", 0444, 376 devroot, pctldev, &pinconf_groups_fops); 377} 378 379#endif