Commit | Line | Data |
---|---|---|
2744e8af LW |
1 | /* |
2 | * Core driver for the pin muxing portions of the pin control subsystem | |
3 | * | |
e93bcee0 | 4 | * Copyright (C) 2011-2012 ST-Ericsson SA |
2744e8af LW |
5 | * Written on behalf of Linaro for ST-Ericsson |
6 | * Based on bits of regulator core, gpio core and clk core | |
7 | * | |
8 | * Author: Linus Walleij <linus.walleij@linaro.org> | |
9 | * | |
7ecdb16f SW |
10 | * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. |
11 | * | |
2744e8af LW |
12 | * License terms: GNU General Public License (GPL) version 2 |
13 | */ | |
14 | #define pr_fmt(fmt) "pinmux core: " fmt | |
15 | ||
16 | #include <linux/kernel.h> | |
17 | #include <linux/module.h> | |
18 | #include <linux/init.h> | |
19 | #include <linux/device.h> | |
20 | #include <linux/slab.h> | |
21 | #include <linux/radix-tree.h> | |
22 | #include <linux/err.h> | |
23 | #include <linux/list.h> | |
97607d15 | 24 | #include <linux/string.h> |
2744e8af LW |
25 | #include <linux/sysfs.h> |
26 | #include <linux/debugfs.h> | |
27 | #include <linux/seq_file.h> | |
28 | #include <linux/pinctrl/machine.h> | |
29 | #include <linux/pinctrl/pinmux.h> | |
30 | #include "core.h" | |
befe5bdf | 31 | #include "pinmux.h" |
2744e8af | 32 | |
03665e0f SW |
33 | int pinmux_check_ops(struct pinctrl_dev *pctldev) |
34 | { | |
35 | const struct pinmux_ops *ops = pctldev->desc->pmxops; | |
36 | unsigned selector = 0; | |
37 | ||
38 | /* Check that we implement required operations */ | |
39 | if (!ops->list_functions || | |
40 | !ops->get_function_name || | |
41 | !ops->get_function_groups || | |
42 | !ops->enable || | |
43 | !ops->disable) | |
44 | return -EINVAL; | |
45 | ||
46 | /* Check that all functions registered have names */ | |
47 | while (ops->list_functions(pctldev, selector) >= 0) { | |
48 | const char *fname = ops->get_function_name(pctldev, | |
49 | selector); | |
50 | if (!fname) { | |
51 | pr_err("pinmux ops has no name for function%u\n", | |
52 | selector); | |
53 | return -EINVAL; | |
54 | } | |
55 | selector++; | |
56 | } | |
57 | ||
58 | return 0; | |
59 | } | |
60 | ||
1e2082b5 SW |
61 | int pinmux_validate_map(struct pinctrl_map const *map, int i) |
62 | { | |
63 | if (!map->data.mux.function) { | |
64 | pr_err("failed to register map %s (%d): no function given\n", | |
65 | map->name, i); | |
66 | return -EINVAL; | |
67 | } | |
68 | ||
69 | return 0; | |
70 | } | |
71 | ||
2744e8af LW |
72 | /** |
73 | * pin_request() - request a single pin to be muxed in, typically for GPIO | |
74 | * @pin: the pin number in the global pin space | |
3cc70ed3 SW |
75 | * @owner: a representation of the owner of this pin; typically the device |
76 | * name that controls its mux function, or the requested GPIO name | |
2744e8af LW |
77 | * @gpio_range: the range matching the GPIO pin if this is a request for a |
78 | * single GPIO pin | |
79 | */ | |
80 | static int pin_request(struct pinctrl_dev *pctldev, | |
3cc70ed3 | 81 | int pin, const char *owner, |
2744e8af LW |
82 | struct pinctrl_gpio_range *gpio_range) |
83 | { | |
84 | struct pin_desc *desc; | |
85 | const struct pinmux_ops *ops = pctldev->desc->pmxops; | |
86 | int status = -EINVAL; | |
87 | ||
3cc70ed3 | 88 | dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, owner); |
2744e8af | 89 | |
2744e8af LW |
90 | desc = pin_desc_get(pctldev, pin); |
91 | if (desc == NULL) { | |
51cd24ee | 92 | dev_err(pctldev->dev, |
2744e8af LW |
93 | "pin is not registered so it cannot be requested\n"); |
94 | goto out; | |
95 | } | |
96 | ||
0e3db173 | 97 | if (desc->usecount && strcmp(desc->owner, owner)) { |
51cd24ee | 98 | dev_err(pctldev->dev, |
2744e8af LW |
99 | "pin already requested\n"); |
100 | goto out; | |
101 | } | |
0e3db173 SW |
102 | |
103 | desc->usecount++; | |
104 | if (desc->usecount > 1) | |
105 | return 0; | |
106 | ||
3cc70ed3 | 107 | desc->owner = owner; |
2744e8af LW |
108 | |
109 | /* Let each pin increase references to this module */ | |
110 | if (!try_module_get(pctldev->owner)) { | |
51cd24ee | 111 | dev_err(pctldev->dev, |
2744e8af LW |
112 | "could not increase module refcount for pin %d\n", |
113 | pin); | |
114 | status = -EINVAL; | |
115 | goto out_free_pin; | |
116 | } | |
117 | ||
118 | /* | |
119 | * If there is no kind of request function for the pin we just assume | |
120 | * we got it by default and proceed. | |
121 | */ | |
3712a3c4 | 122 | if (gpio_range && ops->gpio_request_enable) |
2744e8af LW |
123 | /* This requests and enables a single GPIO pin */ |
124 | status = ops->gpio_request_enable(pctldev, gpio_range, pin); | |
125 | else if (ops->request) | |
126 | status = ops->request(pctldev, pin); | |
127 | else | |
128 | status = 0; | |
129 | ||
0e3db173 | 130 | if (status) { |
f9d41d7c | 131 | dev_err(pctldev->dev, "->request on device %s failed for pin %d\n", |
2744e8af | 132 | pctldev->desc->name, pin); |
0e3db173 SW |
133 | module_put(pctldev->owner); |
134 | } | |
135 | ||
2744e8af | 136 | out_free_pin: |
0e3db173 SW |
137 | if (status) { |
138 | desc->usecount--; | |
139 | if (!desc->usecount) | |
140 | desc->owner = NULL; | |
141 | } | |
2744e8af LW |
142 | out: |
143 | if (status) | |
51cd24ee | 144 | dev_err(pctldev->dev, "pin-%d (%s) status %d\n", |
3cc70ed3 | 145 | pin, owner, status); |
2744e8af LW |
146 | |
147 | return status; | |
148 | } | |
149 | ||
150 | /** | |
151 | * pin_free() - release a single muxed in pin so something else can be muxed | |
152 | * @pctldev: pin controller device handling this pin | |
153 | * @pin: the pin to free | |
3712a3c4 SW |
154 | * @gpio_range: the range matching the GPIO pin if this is a request for a |
155 | * single GPIO pin | |
336cdba0 | 156 | * |
3cc70ed3 SW |
157 | * This function returns a pointer to the previous owner. This is used |
158 | * for callers that dynamically allocate an owner name so it can be freed | |
336cdba0 | 159 | * once the pin is free. This is done for GPIO request functions. |
2744e8af | 160 | */ |
3712a3c4 SW |
161 | static const char *pin_free(struct pinctrl_dev *pctldev, int pin, |
162 | struct pinctrl_gpio_range *gpio_range) | |
2744e8af LW |
163 | { |
164 | const struct pinmux_ops *ops = pctldev->desc->pmxops; | |
165 | struct pin_desc *desc; | |
3cc70ed3 | 166 | const char *owner; |
2744e8af LW |
167 | |
168 | desc = pin_desc_get(pctldev, pin); | |
169 | if (desc == NULL) { | |
51cd24ee | 170 | dev_err(pctldev->dev, |
2744e8af | 171 | "pin is not registered so it cannot be freed\n"); |
3712a3c4 | 172 | return NULL; |
2744e8af LW |
173 | } |
174 | ||
0e3db173 SW |
175 | desc->usecount--; |
176 | if (desc->usecount) | |
177 | return NULL; | |
178 | ||
3712a3c4 SW |
179 | /* |
180 | * If there is no kind of request function for the pin we just assume | |
181 | * we got it by default and proceed. | |
182 | */ | |
183 | if (gpio_range && ops->gpio_disable_free) | |
184 | ops->gpio_disable_free(pctldev, gpio_range, pin); | |
185 | else if (ops->free) | |
2744e8af LW |
186 | ops->free(pctldev, pin); |
187 | ||
3cc70ed3 SW |
188 | owner = desc->owner; |
189 | desc->owner = NULL; | |
2744e8af | 190 | module_put(pctldev->owner); |
3712a3c4 | 191 | |
3cc70ed3 | 192 | return owner; |
2744e8af LW |
193 | } |
194 | ||
195 | /** | |
befe5bdf LW |
196 | * pinmux_request_gpio() - request pinmuxing for a GPIO pin |
197 | * @pctldev: pin controller device affected | |
198 | * @pin: the pin to mux in for GPIO | |
199 | * @range: the applicable GPIO range | |
2744e8af | 200 | */ |
befe5bdf LW |
201 | int pinmux_request_gpio(struct pinctrl_dev *pctldev, |
202 | struct pinctrl_gpio_range *range, | |
203 | unsigned pin, unsigned gpio) | |
2744e8af LW |
204 | { |
205 | char gpiostr[16]; | |
3cc70ed3 | 206 | const char *owner; |
2744e8af | 207 | int ret; |
2744e8af LW |
208 | |
209 | /* Conjure some name stating what chip and pin this is taken by */ | |
210 | snprintf(gpiostr, 15, "%s:%d", range->name, gpio); | |
211 | ||
3cc70ed3 SW |
212 | owner = kstrdup(gpiostr, GFP_KERNEL); |
213 | if (!owner) | |
5d2eaf80 SW |
214 | return -EINVAL; |
215 | ||
3cc70ed3 | 216 | ret = pin_request(pctldev, pin, owner, range); |
5d2eaf80 | 217 | if (ret < 0) |
3cc70ed3 | 218 | kfree(owner); |
5d2eaf80 SW |
219 | |
220 | return ret; | |
2744e8af | 221 | } |
2744e8af LW |
222 | |
223 | /** | |
befe5bdf LW |
224 | * pinmux_free_gpio() - release a pin from GPIO muxing |
225 | * @pctldev: the pin controller device for the pin | |
226 | * @pin: the affected currently GPIO-muxed in pin | |
227 | * @range: applicable GPIO range | |
2744e8af | 228 | */ |
befe5bdf LW |
229 | void pinmux_free_gpio(struct pinctrl_dev *pctldev, unsigned pin, |
230 | struct pinctrl_gpio_range *range) | |
2744e8af | 231 | { |
3cc70ed3 | 232 | const char *owner; |
2744e8af | 233 | |
3cc70ed3 SW |
234 | owner = pin_free(pctldev, pin, range); |
235 | kfree(owner); | |
2744e8af | 236 | } |
2744e8af | 237 | |
befe5bdf LW |
238 | /** |
239 | * pinmux_gpio_direction() - set the direction of a single muxed-in GPIO pin | |
240 | * @pctldev: the pin controller handling this pin | |
241 | * @range: applicable GPIO range | |
242 | * @pin: the affected GPIO pin in this controller | |
243 | * @input: true if we set the pin as input, false for output | |
244 | */ | |
245 | int pinmux_gpio_direction(struct pinctrl_dev *pctldev, | |
246 | struct pinctrl_gpio_range *range, | |
247 | unsigned pin, bool input) | |
542e704f | 248 | { |
542e704f LW |
249 | const struct pinmux_ops *ops; |
250 | int ret; | |
542e704f LW |
251 | |
252 | ops = pctldev->desc->pmxops; | |
253 | ||
542e704f LW |
254 | if (ops->gpio_set_direction) |
255 | ret = ops->gpio_set_direction(pctldev, range, pin, input); | |
256 | else | |
257 | ret = 0; | |
258 | ||
259 | return ret; | |
260 | } | |
261 | ||
7ecdb16f SW |
262 | static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev, |
263 | const char *function) | |
2744e8af LW |
264 | { |
265 | const struct pinmux_ops *ops = pctldev->desc->pmxops; | |
266 | unsigned selector = 0; | |
267 | ||
268 | /* See if this pctldev has this function */ | |
269 | while (ops->list_functions(pctldev, selector) >= 0) { | |
270 | const char *fname = ops->get_function_name(pctldev, | |
271 | selector); | |
2744e8af | 272 | |
7ecdb16f SW |
273 | if (!strcmp(function, fname)) |
274 | return selector; | |
2744e8af | 275 | |
2744e8af LW |
276 | selector++; |
277 | } | |
278 | ||
279 | pr_err("%s does not support function %s\n", | |
7ecdb16f | 280 | pinctrl_dev_get_name(pctldev), function); |
2744e8af LW |
281 | return -EINVAL; |
282 | } | |
283 | ||
7ecdb16f SW |
284 | int pinmux_map_to_setting(struct pinctrl_map const *map, |
285 | struct pinctrl_setting *setting) | |
2744e8af | 286 | { |
7ecdb16f SW |
287 | struct pinctrl_dev *pctldev = setting->pctldev; |
288 | const struct pinmux_ops *pmxops = pctldev->desc->pmxops; | |
289 | const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; | |
290 | char const * const *groups; | |
291 | unsigned num_groups; | |
2744e8af | 292 | int ret; |
7ecdb16f SW |
293 | const char *group; |
294 | int i; | |
295 | const unsigned *pins; | |
296 | unsigned num_pins; | |
2744e8af | 297 | |
1e2082b5 SW |
298 | setting->data.mux.func = |
299 | pinmux_func_name_to_selector(pctldev, map->data.mux.function); | |
300 | if (setting->data.mux.func < 0) | |
301 | return setting->data.mux.func; | |
2744e8af | 302 | |
1e2082b5 | 303 | ret = pmxops->get_function_groups(pctldev, setting->data.mux.func, |
7ecdb16f SW |
304 | &groups, &num_groups); |
305 | if (ret < 0) | |
306 | return ret; | |
307 | if (!num_groups) | |
2744e8af | 308 | return -EINVAL; |
7ecdb16f | 309 | |
1e2082b5 | 310 | if (map->data.mux.group) { |
7ecdb16f | 311 | bool found = false; |
1e2082b5 | 312 | group = map->data.mux.group; |
7ecdb16f SW |
313 | for (i = 0; i < num_groups; i++) { |
314 | if (!strcmp(group, groups[i])) { | |
315 | found = true; | |
316 | break; | |
317 | } | |
318 | } | |
319 | if (!found) | |
320 | return -EINVAL; | |
321 | } else { | |
322 | group = groups[0]; | |
2744e8af | 323 | } |
2744e8af | 324 | |
1e2082b5 SW |
325 | setting->data.mux.group = pinctrl_get_group_selector(pctldev, group); |
326 | if (setting->data.mux.group < 0) | |
327 | return setting->data.mux.group; | |
2744e8af | 328 | |
1e2082b5 SW |
329 | ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins, |
330 | &num_pins); | |
2744e8af | 331 | if (ret) { |
7ecdb16f SW |
332 | dev_err(pctldev->dev, |
333 | "could not get pins for device %s group selector %d\n", | |
1e2082b5 | 334 | pinctrl_dev_get_name(pctldev), setting->data.mux.group); |
7ecdb16f SW |
335 | return -ENODEV; |
336 | } | |
337 | ||
338 | /* Try to allocate all pins in this group, one by one */ | |
339 | for (i = 0; i < num_pins; i++) { | |
340 | ret = pin_request(pctldev, pins[i], map->dev_name, NULL); | |
341 | if (ret) { | |
342 | dev_err(pctldev->dev, | |
343 | "could not get request pin %d on device %s\n", | |
344 | pins[i], pinctrl_dev_get_name(pctldev)); | |
345 | /* On error release all taken pins */ | |
346 | i--; /* this pin just failed */ | |
347 | for (; i >= 0; i--) | |
348 | pin_free(pctldev, pins[i], NULL); | |
349 | return -ENODEV; | |
350 | } | |
2744e8af | 351 | } |
2744e8af LW |
352 | |
353 | return 0; | |
354 | } | |
355 | ||
7ecdb16f | 356 | void pinmux_free_setting(struct pinctrl_setting const *setting) |
2744e8af | 357 | { |
7ecdb16f SW |
358 | struct pinctrl_dev *pctldev = setting->pctldev; |
359 | const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; | |
360 | const unsigned *pins; | |
361 | unsigned num_pins; | |
befe5bdf | 362 | int ret; |
7ecdb16f | 363 | int i; |
2744e8af | 364 | |
1e2082b5 | 365 | ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, |
7ecdb16f | 366 | &pins, &num_pins); |
befe5bdf | 367 | if (ret) { |
7ecdb16f SW |
368 | dev_err(pctldev->dev, |
369 | "could not get pins for device %s group selector %d\n", | |
1e2082b5 | 370 | pinctrl_dev_get_name(pctldev), setting->data.mux.group); |
7ecdb16f | 371 | return; |
2744e8af LW |
372 | } |
373 | ||
7ecdb16f SW |
374 | for (i = 0; i < num_pins; i++) |
375 | pin_free(pctldev, pins[i], NULL); | |
2744e8af | 376 | } |
2744e8af | 377 | |
7ecdb16f | 378 | int pinmux_enable_setting(struct pinctrl_setting const *setting) |
2744e8af | 379 | { |
7ecdb16f | 380 | struct pinctrl_dev *pctldev = setting->pctldev; |
befe5bdf | 381 | const struct pinmux_ops *ops = pctldev->desc->pmxops; |
2744e8af | 382 | |
1e2082b5 SW |
383 | return ops->enable(pctldev, setting->data.mux.func, |
384 | setting->data.mux.group); | |
2744e8af | 385 | } |
2744e8af | 386 | |
7ecdb16f | 387 | void pinmux_disable_setting(struct pinctrl_setting const *setting) |
2744e8af | 388 | { |
7ecdb16f | 389 | struct pinctrl_dev *pctldev = setting->pctldev; |
befe5bdf | 390 | const struct pinmux_ops *ops = pctldev->desc->pmxops; |
2744e8af | 391 | |
1e2082b5 | 392 | ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group); |
2744e8af | 393 | } |
2744e8af | 394 | |
2744e8af LW |
395 | #ifdef CONFIG_DEBUG_FS |
396 | ||
397 | /* Called from pincontrol core */ | |
398 | static int pinmux_functions_show(struct seq_file *s, void *what) | |
399 | { | |
400 | struct pinctrl_dev *pctldev = s->private; | |
401 | const struct pinmux_ops *pmxops = pctldev->desc->pmxops; | |
402 | unsigned func_selector = 0; | |
403 | ||
57b676f9 SW |
404 | mutex_lock(&pinctrl_mutex); |
405 | ||
2744e8af LW |
406 | while (pmxops->list_functions(pctldev, func_selector) >= 0) { |
407 | const char *func = pmxops->get_function_name(pctldev, | |
408 | func_selector); | |
409 | const char * const *groups; | |
410 | unsigned num_groups; | |
411 | int ret; | |
412 | int i; | |
413 | ||
414 | ret = pmxops->get_function_groups(pctldev, func_selector, | |
415 | &groups, &num_groups); | |
416 | if (ret) | |
417 | seq_printf(s, "function %s: COULD NOT GET GROUPS\n", | |
418 | func); | |
419 | ||
420 | seq_printf(s, "function: %s, groups = [ ", func); | |
421 | for (i = 0; i < num_groups; i++) | |
422 | seq_printf(s, "%s ", groups[i]); | |
423 | seq_puts(s, "]\n"); | |
424 | ||
425 | func_selector++; | |
2744e8af LW |
426 | } |
427 | ||
57b676f9 SW |
428 | mutex_unlock(&pinctrl_mutex); |
429 | ||
2744e8af LW |
430 | return 0; |
431 | } | |
432 | ||
433 | static int pinmux_pins_show(struct seq_file *s, void *what) | |
434 | { | |
435 | struct pinctrl_dev *pctldev = s->private; | |
706e8520 | 436 | unsigned i, pin; |
2744e8af LW |
437 | |
438 | seq_puts(s, "Pinmux settings per pin\n"); | |
3cc70ed3 | 439 | seq_puts(s, "Format: pin (name): owner\n"); |
2744e8af | 440 | |
57b676f9 SW |
441 | mutex_lock(&pinctrl_mutex); |
442 | ||
706e8520 CP |
443 | /* The pin number can be retrived from the pin controller descriptor */ |
444 | for (i = 0; i < pctldev->desc->npins; i++) { | |
2744e8af | 445 | struct pin_desc *desc; |
1cf94c45 | 446 | bool is_hog = false; |
2744e8af | 447 | |
706e8520 | 448 | pin = pctldev->desc->pins[i].number; |
2744e8af | 449 | desc = pin_desc_get(pctldev, pin); |
706e8520 | 450 | /* Skip if we cannot search the pin */ |
2744e8af LW |
451 | if (desc == NULL) |
452 | continue; | |
453 | ||
1cf94c45 LW |
454 | if (desc->owner && |
455 | !strcmp(desc->owner, pinctrl_dev_get_name(pctldev))) | |
456 | is_hog = true; | |
457 | ||
458 | seq_printf(s, "pin %d (%s): %s%s\n", pin, | |
2744e8af | 459 | desc->name ? desc->name : "unnamed", |
1cf94c45 LW |
460 | desc->owner ? desc->owner : "UNCLAIMED", |
461 | is_hog ? " (HOG)" : ""); | |
2744e8af LW |
462 | } |
463 | ||
57b676f9 SW |
464 | mutex_unlock(&pinctrl_mutex); |
465 | ||
2744e8af LW |
466 | return 0; |
467 | } | |
468 | ||
1e2082b5 SW |
469 | void pinmux_show_map(struct seq_file *s, struct pinctrl_map const *map) |
470 | { | |
471 | seq_printf(s, "group %s\nfunction %s\n", | |
472 | map->data.mux.group ? map->data.mux.group : "(default)", | |
473 | map->data.mux.function); | |
474 | } | |
475 | ||
476 | void pinmux_show_setting(struct seq_file *s, | |
477 | struct pinctrl_setting const *setting) | |
2744e8af | 478 | { |
7ecdb16f SW |
479 | struct pinctrl_dev *pctldev = setting->pctldev; |
480 | const struct pinmux_ops *pmxops = pctldev->desc->pmxops; | |
481 | const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; | |
482 | ||
1e2082b5 SW |
483 | seq_printf(s, "group: %s (%u) function: %s (%u)\n", |
484 | pctlops->get_group_name(pctldev, setting->data.mux.group), | |
485 | setting->data.mux.group, | |
486 | pmxops->get_function_name(pctldev, setting->data.mux.func), | |
487 | setting->data.mux.func); | |
2744e8af LW |
488 | } |
489 | ||
490 | static int pinmux_functions_open(struct inode *inode, struct file *file) | |
491 | { | |
492 | return single_open(file, pinmux_functions_show, inode->i_private); | |
493 | } | |
494 | ||
495 | static int pinmux_pins_open(struct inode *inode, struct file *file) | |
496 | { | |
497 | return single_open(file, pinmux_pins_show, inode->i_private); | |
498 | } | |
499 | ||
2744e8af LW |
500 | static const struct file_operations pinmux_functions_ops = { |
501 | .open = pinmux_functions_open, | |
502 | .read = seq_read, | |
503 | .llseek = seq_lseek, | |
504 | .release = single_release, | |
505 | }; | |
506 | ||
507 | static const struct file_operations pinmux_pins_ops = { | |
508 | .open = pinmux_pins_open, | |
509 | .read = seq_read, | |
510 | .llseek = seq_lseek, | |
511 | .release = single_release, | |
512 | }; | |
513 | ||
2744e8af LW |
514 | void pinmux_init_device_debugfs(struct dentry *devroot, |
515 | struct pinctrl_dev *pctldev) | |
516 | { | |
517 | debugfs_create_file("pinmux-functions", S_IFREG | S_IRUGO, | |
518 | devroot, pctldev, &pinmux_functions_ops); | |
519 | debugfs_create_file("pinmux-pins", S_IFREG | S_IRUGO, | |
520 | devroot, pctldev, &pinmux_pins_ops); | |
2744e8af LW |
521 | } |
522 | ||
523 | #endif /* CONFIG_DEBUG_FS */ |