Blame view
drivers/pinctrl/pinconf.c
15.8 KB
ae6b4d858 pinctrl: add a pi... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/* * Core driver for the pin config portions of the pin control subsystem * * Copyright (C) 2011 ST-Ericsson SA * Written on behalf of Linaro for ST-Ericsson * * Author: Linus Walleij <linus.walleij@linaro.org> * * License terms: GNU General Public License (GPL) version 2 */ #define pr_fmt(fmt) "pinconfig core: " fmt #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/device.h> #include <linux/slab.h> #include <linux/debugfs.h> #include <linux/seq_file.h> |
f07512e61 pinctrl/pinconfig... |
20 |
#include <linux/uaccess.h> |
ae6b4d858 pinctrl: add a pi... |
21 22 23 24 25 |
#include <linux/pinctrl/machine.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinconf.h> #include "core.h" #include "pinconf.h" |
2b6942501 pinctrl: Re-order... |
26 27 28 |
int pinconf_check_ops(struct pinctrl_dev *pctldev) { const struct pinconf_ops *ops = pctldev->desc->confops; |
2b6942501 pinctrl: Re-order... |
29 |
/* We have to be able to config the pins in SOME way */ |
ad6e1107b pinctrl: enhance ... |
30 31 32 33 |
if (!ops->pin_config_set && !ops->pin_config_group_set) { dev_err(pctldev->dev, "pinconf has to be able to set a pins config "); |
2b6942501 pinctrl: Re-order... |
34 |
return -EINVAL; |
ad6e1107b pinctrl: enhance ... |
35 |
} |
2b6942501 pinctrl: Re-order... |
36 37 |
return 0; } |
3f713b7c2 pinctrl: move con... |
38 |
int pinconf_validate_map(const struct pinctrl_map *map, int i) |
1e2082b52 pinctrl: enhance ... |
39 40 41 42 43 44 45 |
{ if (!map->data.configs.group_or_pin) { pr_err("failed to register map %s (%d): no group/pin given ", map->name, i); return -EINVAL; } |
c95df2db2 pinctrl: a minor ... |
46 |
if (!map->data.configs.num_configs || |
1e2082b52 pinctrl: enhance ... |
47 |
!map->data.configs.configs) { |
c95df2db2 pinctrl: a minor ... |
48 49 |
pr_err("failed to register map %s (%d): no configs given ", |
1e2082b52 pinctrl: enhance ... |
50 51 52 53 54 55 |
map->name, i); return -EINVAL; } return 0; } |
394349f77 pinctrl: introduc... |
56 |
int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, |
ae6b4d858 pinctrl: add a pi... |
57 58 59 60 61 |
unsigned long *config) { const struct pinconf_ops *ops = pctldev->desc->confops; if (!ops || !ops->pin_config_get) { |
ca67f10f2 pinctrl: join dev... |
62 63 64 |
dev_dbg(pctldev->dev, "cannot get pin configuration, .pin_config_get missing in driver "); |
c420619d5 pinctrl: pinconf:... |
65 |
return -ENOTSUPP; |
ae6b4d858 pinctrl: add a pi... |
66 67 68 69 |
} return ops->pin_config_get(pctldev, pin, config); } |
43699dea1 pinctrl: pass nam... |
70 |
int pin_config_group_get(const char *dev_name, const char *pin_group, |
ae6b4d858 pinctrl: add a pi... |
71 72 |
unsigned long *config) { |
43699dea1 pinctrl: pass nam... |
73 74 |
struct pinctrl_dev *pctldev; const struct pinconf_ops *ops; |
57b676f9c pinctrl: fix and ... |
75 |
int selector, ret; |
9dfac4fd7 pinctrl: delete r... |
76 |
pctldev = get_pinctrl_dev_from_devname(dev_name); |
57b676f9c pinctrl: fix and ... |
77 78 |
if (!pctldev) { ret = -EINVAL; |
42fed7ba4 pinctrl: move sub... |
79 |
return ret; |
57b676f9c pinctrl: fix and ... |
80 |
} |
42fed7ba4 pinctrl: move sub... |
81 82 |
mutex_lock(&pctldev->mutex); |
43699dea1 pinctrl: pass nam... |
83 |
ops = pctldev->desc->confops; |
ae6b4d858 pinctrl: add a pi... |
84 |
if (!ops || !ops->pin_config_group_get) { |
e4d030509 pinctrl: Combine ... |
85 86 87 |
dev_dbg(pctldev->dev, "cannot get configuration for pin group, missing group config get function in driver "); |
c420619d5 pinctrl: pinconf:... |
88 |
ret = -ENOTSUPP; |
57b676f9c pinctrl: fix and ... |
89 |
goto unlock; |
ae6b4d858 pinctrl: add a pi... |
90 91 92 |
} selector = pinctrl_get_group_selector(pctldev, pin_group); |
57b676f9c pinctrl: fix and ... |
93 94 95 96 |
if (selector < 0) { ret = selector; goto unlock; } |
ae6b4d858 pinctrl: add a pi... |
97 |
|
57b676f9c pinctrl: fix and ... |
98 99 100 |
ret = ops->pin_config_group_get(pctldev, selector, config); unlock: |
42fed7ba4 pinctrl: move sub... |
101 |
mutex_unlock(&pctldev->mutex); |
57b676f9c pinctrl: fix and ... |
102 |
return ret; |
ae6b4d858 pinctrl: add a pi... |
103 |
} |
ae6b4d858 pinctrl: add a pi... |
104 |
|
3f713b7c2 pinctrl: move con... |
105 |
int pinconf_map_to_setting(const struct pinctrl_map *map, |
1e2082b52 pinctrl: enhance ... |
106 107 108 |
struct pinctrl_setting *setting) { struct pinctrl_dev *pctldev = setting->pctldev; |
70b36378d pinctrl: fix erro... |
109 |
int pin; |
1e2082b52 pinctrl: enhance ... |
110 111 112 |
switch (setting->type) { case PIN_MAP_TYPE_CONFIGS_PIN: |
70b36378d pinctrl: fix erro... |
113 114 115 116 117 118 119 120 |
pin = pin_get_from_name(pctldev, map->data.configs.group_or_pin); if (pin < 0) { dev_err(pctldev->dev, "could not map pin config for \"%s\"", map->data.configs.group_or_pin); return pin; } setting->data.configs.group_or_pin = pin; |
1e2082b52 pinctrl: enhance ... |
121 122 |
break; case PIN_MAP_TYPE_CONFIGS_GROUP: |
70b36378d pinctrl: fix erro... |
123 124 125 126 127 128 129 130 |
pin = pinctrl_get_group_selector(pctldev, map->data.configs.group_or_pin); if (pin < 0) { dev_err(pctldev->dev, "could not map group config for \"%s\"", map->data.configs.group_or_pin); return pin; } setting->data.configs.group_or_pin = pin; |
1e2082b52 pinctrl: enhance ... |
131 132 133 134 135 136 137 138 139 140 |
break; default: return -EINVAL; } setting->data.configs.num_configs = map->data.configs.num_configs; setting->data.configs.configs = map->data.configs.configs; return 0; } |
3f713b7c2 pinctrl: move con... |
141 |
void pinconf_free_setting(const struct pinctrl_setting *setting) |
1e2082b52 pinctrl: enhance ... |
142 143 |
{ } |
3f713b7c2 pinctrl: move con... |
144 |
int pinconf_apply_setting(const struct pinctrl_setting *setting) |
1e2082b52 pinctrl: enhance ... |
145 146 147 |
{ struct pinctrl_dev *pctldev = setting->pctldev; const struct pinconf_ops *ops = pctldev->desc->confops; |
03b054e96 pinctrl: Pass all... |
148 |
int ret; |
1e2082b52 pinctrl: enhance ... |
149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
if (!ops) { dev_err(pctldev->dev, "missing confops "); return -EINVAL; } switch (setting->type) { case PIN_MAP_TYPE_CONFIGS_PIN: if (!ops->pin_config_set) { dev_err(pctldev->dev, "missing pin_config_set op "); return -EINVAL; } |
03b054e96 pinctrl: Pass all... |
163 164 165 166 167 168 169 170 171 172 |
ret = ops->pin_config_set(pctldev, setting->data.configs.group_or_pin, setting->data.configs.configs, setting->data.configs.num_configs); if (ret < 0) { dev_err(pctldev->dev, "pin_config_set op failed for pin %d ", setting->data.configs.group_or_pin); return ret; |
1e2082b52 pinctrl: enhance ... |
173 174 175 176 177 178 179 180 181 |
} break; case PIN_MAP_TYPE_CONFIGS_GROUP: if (!ops->pin_config_group_set) { dev_err(pctldev->dev, "missing pin_config_group_set op "); return -EINVAL; } |
03b054e96 pinctrl: Pass all... |
182 183 184 185 186 187 188 189 190 191 |
ret = ops->pin_config_group_set(pctldev, setting->data.configs.group_or_pin, setting->data.configs.configs, setting->data.configs.num_configs); if (ret < 0) { dev_err(pctldev->dev, "pin_config_group_set op failed for group %d ", setting->data.configs.group_or_pin); return ret; |
1e2082b52 pinctrl: enhance ... |
192 193 194 195 196 197 198 199 |
} break; default: return -EINVAL; } return 0; } |
15381bc7c pinctrl: Allow co... |
200 201 202 203 204 205 |
int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin, unsigned long *configs, size_t nconfigs) { const struct pinconf_ops *ops; ops = pctldev->desc->confops; |
17a512486 pinctrl: check op... |
206 |
if (!ops || !ops->pin_config_set) |
15381bc7c pinctrl: Allow co... |
207 208 209 210 |
return -ENOTSUPP; return ops->pin_config_set(pctldev, pin, configs, nconfigs); } |
ae6b4d858 pinctrl: add a pi... |
211 |
#ifdef CONFIG_DEBUG_FS |
6de52c151 pinctrl: pinconf:... |
212 |
static void pinconf_show_config(struct seq_file *s, struct pinctrl_dev *pctldev, |
d96310aed pinctrl: pinconf:... |
213 |
unsigned long *configs, unsigned num_configs) |
1e2082b52 pinctrl: enhance ... |
214 |
{ |
6cb415875 pinctrl: allow pc... |
215 |
const struct pinconf_ops *confops; |
1e2082b52 pinctrl: enhance ... |
216 |
int i; |
6cb415875 pinctrl: allow pc... |
217 218 219 220 |
if (pctldev) confops = pctldev->desc->confops; else confops = NULL; |
d96310aed pinctrl: pinconf:... |
221 222 223 224 225 226 227 |
for (i = 0; i < num_configs; i++) { seq_puts(s, "config "); if (confops && confops->pin_config_config_dbg_show) confops->pin_config_config_dbg_show(pctldev, s, configs[i]); else seq_printf(s, "%08lx", configs[i]); |
47352a637 pinctrl: Use seq_... |
228 229 |
seq_putc(s, ' '); |
d96310aed pinctrl: pinconf:... |
230 231 |
} } |
3f713b7c2 pinctrl: move con... |
232 |
void pinconf_show_map(struct seq_file *s, const struct pinctrl_map *map) |
d96310aed pinctrl: pinconf:... |
233 234 235 236 |
{ struct pinctrl_dev *pctldev; pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name); |
1e2082b52 pinctrl: enhance ... |
237 238 |
switch (map->type) { case PIN_MAP_TYPE_CONFIGS_PIN: |
de2eae26d pinctrl: Replace ... |
239 |
seq_puts(s, "pin "); |
1e2082b52 pinctrl: enhance ... |
240 241 |
break; case PIN_MAP_TYPE_CONFIGS_GROUP: |
de2eae26d pinctrl: Replace ... |
242 |
seq_puts(s, "group "); |
1e2082b52 pinctrl: enhance ... |
243 244 245 246 247 248 249 |
break; default: break; } seq_printf(s, "%s ", map->data.configs.group_or_pin); |
d96310aed pinctrl: pinconf:... |
250 251 |
pinconf_show_config(s, pctldev, map->data.configs.configs, map->data.configs.num_configs); |
1e2082b52 pinctrl: enhance ... |
252 253 254 |
} void pinconf_show_setting(struct seq_file *s, |
3f713b7c2 pinctrl: move con... |
255 |
const struct pinctrl_setting *setting) |
1e2082b52 pinctrl: enhance ... |
256 257 258 259 |
{ struct pinctrl_dev *pctldev = setting->pctldev; const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; struct pin_desc *desc; |
1e2082b52 pinctrl: enhance ... |
260 261 262 263 264 |
switch (setting->type) { case PIN_MAP_TYPE_CONFIGS_PIN: desc = pin_desc_get(setting->pctldev, setting->data.configs.group_or_pin); |
cf9d994dc pinctrl: do not c... |
265 |
seq_printf(s, "pin %s (%d)", desc->name, |
1e2082b52 pinctrl: enhance ... |
266 267 268 269 270 271 272 273 274 275 276 277 278 |
setting->data.configs.group_or_pin); break; case PIN_MAP_TYPE_CONFIGS_GROUP: seq_printf(s, "group %s (%d)", pctlops->get_group_name(pctldev, setting->data.configs.group_or_pin), setting->data.configs.group_or_pin); break; default: break; } /* |
3ec440e33 pinctrl: Fix spel... |
279 |
* FIXME: We should really get the pin controller to dump the config |
1e2082b52 pinctrl: enhance ... |
280 281 |
* values, so they can be decoded to something meaningful. */ |
d96310aed pinctrl: pinconf:... |
282 283 |
pinconf_show_config(s, pctldev, setting->data.configs.configs, setting->data.configs.num_configs); |
1e2082b52 pinctrl: enhance ... |
284 |
} |
ae6b4d858 pinctrl: add a pi... |
285 286 287 288 |
static void pinconf_dump_pin(struct pinctrl_dev *pctldev, struct seq_file *s, int pin) { const struct pinconf_ops *ops = pctldev->desc->confops; |
394349f77 pinctrl: introduc... |
289 |
/* no-op when not using generic pin config */ |
dd4d01f7b pinctrl: pinconf-... |
290 |
pinconf_generic_dump_pins(pctldev, s, NULL, pin); |
ae6b4d858 pinctrl: add a pi... |
291 292 293 294 295 296 297 |
if (ops && ops->pin_config_dbg_show) ops->pin_config_dbg_show(pctldev, s, pin); } static int pinconf_pins_show(struct seq_file *s, void *what) { struct pinctrl_dev *pctldev = s->private; |
706e8520e pinctrl: correct ... |
298 |
unsigned i, pin; |
ae6b4d858 pinctrl: add a pi... |
299 300 301 |
seq_puts(s, "Pin config settings per pin "); |
2aeefe023 pinctrl: a minor ... |
302 303 |
seq_puts(s, "Format: pin (name): configs "); |
ae6b4d858 pinctrl: add a pi... |
304 |
|
42fed7ba4 pinctrl: move sub... |
305 |
mutex_lock(&pctldev->mutex); |
57b676f9c pinctrl: fix and ... |
306 |
|
706e8520e pinctrl: correct ... |
307 |
/* The pin number can be retrived from the pin controller descriptor */ |
546edd83a pinctrl: fix pinc... |
308 |
for (i = 0; i < pctldev->desc->npins; i++) { |
ae6b4d858 pinctrl: add a pi... |
309 |
struct pin_desc *desc; |
706e8520e pinctrl: correct ... |
310 |
pin = pctldev->desc->pins[i].number; |
ae6b4d858 pinctrl: add a pi... |
311 |
desc = pin_desc_get(pctldev, pin); |
706e8520e pinctrl: correct ... |
312 |
/* Skip if we cannot search the pin */ |
76ce37f05 pinctrl: Adjust f... |
313 |
if (!desc) |
ae6b4d858 pinctrl: add a pi... |
314 |
continue; |
a672eb5e2 pinctrl: pinconf:... |
315 |
seq_printf(s, "pin %d (%s): ", pin, desc->name); |
ae6b4d858 pinctrl: add a pi... |
316 317 |
pinconf_dump_pin(pctldev, s, pin); |
47352a637 pinctrl: Use seq_... |
318 319 |
seq_putc(s, ' '); |
ae6b4d858 pinctrl: add a pi... |
320 |
} |
42fed7ba4 pinctrl: move sub... |
321 |
mutex_unlock(&pctldev->mutex); |
57b676f9c pinctrl: fix and ... |
322 |
|
ae6b4d858 pinctrl: add a pi... |
323 324 325 326 327 328 329 330 |
return 0; } static void pinconf_dump_group(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned selector, const char *gname) { const struct pinconf_ops *ops = pctldev->desc->confops; |
394349f77 pinctrl: introduc... |
331 |
/* no-op when not using generic pin config */ |
dd4d01f7b pinctrl: pinconf-... |
332 |
pinconf_generic_dump_pins(pctldev, s, gname, 0); |
ae6b4d858 pinctrl: add a pi... |
333 334 335 336 337 338 339 340 |
if (ops && ops->pin_config_group_dbg_show) ops->pin_config_group_dbg_show(pctldev, s, selector); } static int pinconf_groups_show(struct seq_file *s, void *what) { struct pinctrl_dev *pctldev = s->private; const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; |
d1e90e9e7 pinctrl: replace ... |
341 |
unsigned ngroups = pctlops->get_groups_count(pctldev); |
ae6b4d858 pinctrl: add a pi... |
342 |
unsigned selector = 0; |
ae6b4d858 pinctrl: add a pi... |
343 344 |
seq_puts(s, "Pin config settings per pin group "); |
2aeefe023 pinctrl: a minor ... |
345 346 |
seq_puts(s, "Format: group (name): configs "); |
ae6b4d858 pinctrl: add a pi... |
347 |
|
d1e90e9e7 pinctrl: replace ... |
348 |
while (selector < ngroups) { |
ae6b4d858 pinctrl: add a pi... |
349 |
const char *gname = pctlops->get_group_name(pctldev, selector); |
a672eb5e2 pinctrl: pinconf:... |
350 |
seq_printf(s, "%u (%s): ", selector, gname); |
ae6b4d858 pinctrl: add a pi... |
351 |
pinconf_dump_group(pctldev, s, selector, gname); |
47352a637 pinctrl: Use seq_... |
352 353 |
seq_putc(s, ' '); |
ae6b4d858 pinctrl: add a pi... |
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
selector++; } return 0; } static int pinconf_pins_open(struct inode *inode, struct file *file) { return single_open(file, pinconf_pins_show, inode->i_private); } static int pinconf_groups_open(struct inode *inode, struct file *file) { return single_open(file, pinconf_groups_show, inode->i_private); } static const struct file_operations pinconf_pins_ops = { .open = pinconf_pins_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static const struct file_operations pinconf_groups_ops = { .open = pinconf_groups_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; |
f07512e61 pinctrl/pinconfig... |
383 384 385 386 |
#define MAX_NAME_LEN 15 struct dbg_cfg { enum pinctrl_map_type map_type; |
e8c5d759d pinctrl: Add spac... |
387 388 389 |
char dev_name[MAX_NAME_LEN + 1]; char state_name[MAX_NAME_LEN + 1]; char pin_name[MAX_NAME_LEN + 1]; |
f07512e61 pinctrl/pinconfig... |
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
}; /* * Goal is to keep this structure as global in order to simply read the * pinconf-config file after a write to check config is as expected */ static struct dbg_cfg pinconf_dbg_conf; /** * pinconf_dbg_config_print() - display the pinctrl config from the pinctrl * map, of the dev/pin/state that was last written to pinconf-config file. * @s: string filled in with config description * @d: not used */ static int pinconf_dbg_config_print(struct seq_file *s, void *d) { struct pinctrl_maps *maps_node; const struct pinctrl_map *map; |
8a9dcc3ff pinctrl: shut up ... |
408 409 |
const struct pinctrl_map *found = NULL; struct pinctrl_dev *pctldev; |
f07512e61 pinctrl/pinconfig... |
410 |
struct dbg_cfg *dbg = &pinconf_dbg_conf; |
d99c8053f pinctrl: pinconf:... |
411 |
int i; |
f07512e61 pinctrl/pinconfig... |
412 |
|
a386267a2 pinctrl: pinconf:... |
413 |
mutex_lock(&pinctrl_maps_mutex); |
f07512e61 pinctrl/pinconfig... |
414 415 416 417 418 419 420 421 422 |
/* Parse the pinctrl map and look for the elected pin/state */ for_each_maps(maps_node, i, map) { if (map->type != dbg->map_type) continue; if (strcmp(map->dev_name, dbg->dev_name)) continue; if (strcmp(map->name, dbg->state_name)) continue; |
d99c8053f pinctrl: pinconf:... |
423 424 425 426 |
if (!strcmp(map->data.configs.group_or_pin, dbg->pin_name)) { /* We found the right pin */ found = map; break; |
f07512e61 pinctrl/pinconfig... |
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
} } if (!found) { seq_printf(s, "No config found for dev/state/pin, expected: "); seq_printf(s, "Searched dev:%s ", dbg->dev_name); seq_printf(s, "Searched state:%s ", dbg->state_name); seq_printf(s, "Searched pin:%s ", dbg->pin_name); seq_printf(s, "Use: modify config_pin <devname> "\ "<state> <pinname> <value> "); goto exit; } |
8a9dcc3ff pinctrl: shut up ... |
444 |
pctldev = get_pinctrl_dev_from_devname(found->ctrl_dev_name); |
d96310aed pinctrl: pinconf:... |
445 446 447 448 449 |
seq_printf(s, "Dev %s has config of %s in state %s: ", dbg->dev_name, dbg->pin_name, dbg->state_name); pinconf_show_config(s, pctldev, found->data.configs.configs, found->data.configs.num_configs); |
f07512e61 pinctrl/pinconfig... |
450 451 |
exit: |
a386267a2 pinctrl: pinconf:... |
452 |
mutex_unlock(&pinctrl_maps_mutex); |
f07512e61 pinctrl/pinconfig... |
453 454 455 456 457 458 459 460 |
return 0; } /** * pinconf_dbg_config_write() - modify the pinctrl config in the pinctrl * map, of a dev/pin/state entry based on user entries to pinconf-config * @user_buf: contains the modification request with expected format: |
756299810 pinctrl: pinconf:... |
461 |
* modify <config> <devicename> <state> <name> <newvalue> |
f07512e61 pinctrl/pinconfig... |
462 |
* modify is literal string, alternatives like add/delete not supported yet |
756299810 pinctrl: pinconf:... |
463 464 465 466 |
* <config> is the configuration to be changed. Supported configs are * "config_pin" or "config_group", alternatives like config_mux are not * supported yet. * <devicename> <state> <name> are values that should match the pinctrl-maps |
3ec440e33 pinctrl: Fix spel... |
467 |
* <newvalue> reflects the new config and is driver dependent |
f07512e61 pinctrl/pinconfig... |
468 |
*/ |
3b59e432e pinctrl: fix pinc... |
469 |
static ssize_t pinconf_dbg_config_write(struct file *file, |
f07512e61 pinctrl/pinconfig... |
470 471 472 473 |
const char __user *user_buf, size_t count, loff_t *ppos) { struct pinctrl_maps *maps_node; const struct pinctrl_map *map; |
8a9dcc3ff pinctrl: shut up ... |
474 475 |
const struct pinctrl_map *found = NULL; struct pinctrl_dev *pctldev; |
f07512e61 pinctrl/pinconfig... |
476 477 478 |
const struct pinconf_ops *confops = NULL; struct dbg_cfg *dbg = &pinconf_dbg_conf; const struct pinctrl_map_configs *configs; |
e8c5d759d pinctrl: Add spac... |
479 |
char config[MAX_NAME_LEN + 1]; |
f07512e61 pinctrl/pinconfig... |
480 481 482 483 484 485 486 |
char buf[128]; char *b = &buf[0]; int buf_size; char *token; int i; /* Get userspace string and assure termination */ |
81d36c4ff pinctrl: remove a... |
487 |
buf_size = min(count, sizeof(buf) - 1); |
f07512e61 pinctrl/pinconfig... |
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 |
if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; buf[buf_size] = 0; /* * need to parse entry and extract parameters: * modify configs_pin devicename state pinname newvalue */ /* Get arg: 'modify' */ token = strsep(&b, " "); if (!token) return -EINVAL; if (strcmp(token, "modify")) return -EINVAL; |
756299810 pinctrl: pinconf:... |
503 504 505 506 |
/* * Get arg type: "config_pin" and "config_group" * types are supported so far */ |
f07512e61 pinctrl/pinconfig... |
507 508 509 |
token = strsep(&b, " "); if (!token) return -EINVAL; |
756299810 pinctrl: pinconf:... |
510 511 512 513 514 |
if (!strcmp(token, "config_pin")) dbg->map_type = PIN_MAP_TYPE_CONFIGS_PIN; else if (!strcmp(token, "config_group")) dbg->map_type = PIN_MAP_TYPE_CONFIGS_GROUP; else |
f07512e61 pinctrl/pinconfig... |
515 |
return -EINVAL; |
f07512e61 pinctrl/pinconfig... |
516 517 518 |
/* get arg 'device_name' */ token = strsep(&b, " "); |
76ce37f05 pinctrl: Adjust f... |
519 |
if (!token) |
f07512e61 pinctrl/pinconfig... |
520 521 522 523 524 525 526 |
return -EINVAL; if (strlen(token) >= MAX_NAME_LEN) return -EINVAL; strncpy(dbg->dev_name, token, MAX_NAME_LEN); /* get arg 'state_name' */ token = strsep(&b, " "); |
76ce37f05 pinctrl: Adjust f... |
527 |
if (!token) |
f07512e61 pinctrl/pinconfig... |
528 529 530 531 532 533 534 |
return -EINVAL; if (strlen(token) >= MAX_NAME_LEN) return -EINVAL; strncpy(dbg->state_name, token, MAX_NAME_LEN); /* get arg 'pin_name' */ token = strsep(&b, " "); |
76ce37f05 pinctrl: Adjust f... |
535 |
if (!token) |
f07512e61 pinctrl/pinconfig... |
536 537 538 539 540 541 542 |
return -EINVAL; if (strlen(token) >= MAX_NAME_LEN) return -EINVAL; strncpy(dbg->pin_name, token, MAX_NAME_LEN); /* get new_value of config' */ token = strsep(&b, " "); |
76ce37f05 pinctrl: Adjust f... |
543 |
if (!token) |
f07512e61 pinctrl/pinconfig... |
544 545 546 547 |
return -EINVAL; if (strlen(token) >= MAX_NAME_LEN) return -EINVAL; strncpy(config, token, MAX_NAME_LEN); |
42fed7ba4 pinctrl: move sub... |
548 |
mutex_lock(&pinctrl_maps_mutex); |
f07512e61 pinctrl/pinconfig... |
549 550 551 552 553 554 555 556 557 558 559 560 |
/* Parse the pinctrl map and look for the selected dev/state/pin */ for_each_maps(maps_node, i, map) { if (strcmp(map->dev_name, dbg->dev_name)) continue; if (map->type != dbg->map_type) continue; if (strcmp(map->name, dbg->state_name)) continue; /* we found the right pin / state, so overwrite config */ if (!strcmp(map->data.configs.group_or_pin, dbg->pin_name)) { |
8a9dcc3ff pinctrl: shut up ... |
561 |
found = map; |
f07512e61 pinctrl/pinconfig... |
562 563 564 565 566 |
break; } } if (!found) { |
f07512e61 pinctrl/pinconfig... |
567 |
count = -EINVAL; |
cb6d315dc pinctrl/pinconfig... |
568 |
goto exit; |
f07512e61 pinctrl/pinconfig... |
569 |
} |
8a9dcc3ff pinctrl: shut up ... |
570 |
pctldev = get_pinctrl_dev_from_devname(found->ctrl_dev_name); |
f07512e61 pinctrl/pinconfig... |
571 572 573 574 |
if (pctldev) confops = pctldev->desc->confops; if (confops && confops->pin_config_dbg_parse_modify) { |
8a9dcc3ff pinctrl: shut up ... |
575 |
configs = &found->data.configs; |
f07512e61 pinctrl/pinconfig... |
576 577 578 579 580 581 582 583 |
for (i = 0; i < configs->num_configs; i++) { confops->pin_config_dbg_parse_modify(pctldev, config, &configs->configs[i]); } } exit: |
42fed7ba4 pinctrl: move sub... |
584 |
mutex_unlock(&pinctrl_maps_mutex); |
f07512e61 pinctrl/pinconfig... |
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 |
return count; } static int pinconf_dbg_config_open(struct inode *inode, struct file *file) { return single_open(file, pinconf_dbg_config_print, inode->i_private); } static const struct file_operations pinconf_dbg_pinconfig_fops = { .open = pinconf_dbg_config_open, .write = pinconf_dbg_config_write, .read = seq_read, .llseek = seq_lseek, .release = single_release, .owner = THIS_MODULE, }; |
ae6b4d858 pinctrl: add a pi... |
602 603 604 605 606 607 608 |
void pinconf_init_device_debugfs(struct dentry *devroot, struct pinctrl_dev *pctldev) { debugfs_create_file("pinconf-pins", S_IFREG | S_IRUGO, devroot, pctldev, &pinconf_pins_ops); debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO, devroot, pctldev, &pinconf_groups_ops); |
f07512e61 pinctrl/pinconfig... |
609 610 |
debugfs_create_file("pinconf-config", (S_IRUGO | S_IWUSR | S_IWGRP), devroot, pctldev, &pinconf_dbg_pinconfig_fops); |
ae6b4d858 pinctrl: add a pi... |
611 612 613 |
} #endif |