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