aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinmux.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2011-11-29 06:52:39 -0500
committerLinus Walleij <linus.walleij@linaro.org>2012-01-03 03:10:02 -0500
commit97607d157c133ab18dfcd77fa836e37fa950a44a (patch)
treef9ac62a9534295f24ab40a2890bfd285bc157a03 /drivers/pinctrl/pinmux.c
parent542e704f3ffee1dc4539c9e8191e4dc215220f5e (diff)
pinctrl: make a copy of pinmux map
This makes a deep copy of the pinmux function map instead of keeping the copy supplied from the platform around. This makes it possible to tag the platforms map with __initdata as is also done as part of this patch. Rationale: a certain target platform (PXA) has numerous pinmux maps, many of which will be lying around unused after boot in a multi-platform binary. Instead, deep-copy the one we're going to use and tag them all __initdata so they go away after boot. ChangeLog v1->v2: - Fixup the deep copy, missed a few items on the struct, plus mark bool member non-const since we're making runtime copies if this stuff now. ChangeLog v2->v3: - Make a shallow copy (just copy the array of map structs) as Arnd noticed, string constants never get discarded by the kernel anyway, so these pointers may be safely copied over. Reviewed-by: Arnd Bergmann <arnd.bergmann@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinmux.c')
-rw-r--r--drivers/pinctrl/pinmux.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index f3e4f031fe1c..f6e7d583998c 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -21,6 +21,7 @@
21#include <linux/list.h> 21#include <linux/list.h>
22#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <linux/spinlock.h> 23#include <linux/spinlock.h>
24#include <linux/string.h>
24#include <linux/sysfs.h> 25#include <linux/sysfs.h>
25#include <linux/debugfs.h> 26#include <linux/debugfs.h>
26#include <linux/seq_file.h> 27#include <linux/seq_file.h>
@@ -33,7 +34,7 @@ static DEFINE_MUTEX(pinmux_list_mutex);
33static LIST_HEAD(pinmux_list); 34static LIST_HEAD(pinmux_list);
34 35
35/* Global pinmux maps, we allow one set only */ 36/* Global pinmux maps, we allow one set only */
36static struct pinmux_map const *pinmux_maps; 37static struct pinmux_map *pinmux_maps;
37static unsigned pinmux_maps_num; 38static unsigned pinmux_maps_num;
38 39
39/** 40/**
@@ -333,7 +334,9 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output);
333 334
334/** 335/**
335 * pinmux_register_mappings() - register a set of pinmux mappings 336 * pinmux_register_mappings() - register a set of pinmux mappings
336 * @maps: the pinmux mappings table to register 337 * @maps: the pinmux mappings table to register, this should be marked with
338 * __initdata so it can be discarded after boot, this function will
339 * perform a shallow copy for the mapping entries.
337 * @num_maps: the number of maps in the mapping table 340 * @num_maps: the number of maps in the mapping table
338 * 341 *
339 * Only call this once during initialization of your machine, the function is 342 * Only call this once during initialization of your machine, the function is
@@ -344,32 +347,48 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output);
344int __init pinmux_register_mappings(struct pinmux_map const *maps, 347int __init pinmux_register_mappings(struct pinmux_map const *maps,
345 unsigned num_maps) 348 unsigned num_maps)
346{ 349{
350 int ret = 0;
347 int i; 351 int i;
348 352
349 if (pinmux_maps != NULL) { 353 if (pinmux_maps_num != 0) {
350 pr_err("pinmux mappings already registered, you can only " 354 pr_err("pinmux mappings already registered, you can only "
351 "register one set of maps\n"); 355 "register one set of maps\n");
352 return -EINVAL; 356 return -EINVAL;
353 } 357 }
354 358
355 pr_debug("add %d pinmux maps\n", num_maps); 359 pr_debug("add %d pinmux maps\n", num_maps);
360
361 /*
362 * Make a copy of the map array - string pointers will end up in the
363 * kernel const section anyway so these do not need to be deep copied.
364 */
365 pinmux_maps = kmemdup(maps, sizeof(struct pinmux_map) * num_maps,
366 GFP_KERNEL);
367 if (!pinmux_maps)
368 return -ENOMEM;
369
356 for (i = 0; i < num_maps; i++) { 370 for (i = 0; i < num_maps; i++) {
357 /* Sanity check the mapping */ 371 /* Sanity check the mapping while copying it */
358 if (!maps[i].name) { 372 if (!maps[i].name) {
359 pr_err("failed to register map %d: " 373 pr_err("failed to register map %d: "
360 "no map name given\n", i); 374 "no map name given\n", i);
361 return -EINVAL; 375 ret = -EINVAL;
376 goto err_out_free;
362 } 377 }
378
363 if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { 379 if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) {
364 pr_err("failed to register map %s (%d): " 380 pr_err("failed to register map %s (%d): "
365 "no pin control device given\n", 381 "no pin control device given\n",
366 maps[i].name, i); 382 maps[i].name, i);
367 return -EINVAL; 383 ret = -EINVAL;
384 goto err_out_free;
368 } 385 }
386
369 if (!maps[i].function) { 387 if (!maps[i].function) {
370 pr_err("failed to register map %s (%d): " 388 pr_err("failed to register map %s (%d): "
371 "no function ID given\n", maps[i].name, i); 389 "no function ID given\n", maps[i].name, i);
372 return -EINVAL; 390 ret = -EINVAL;
391 goto err_out_free;
373 } 392 }
374 393
375 if (!maps[i].dev && !maps[i].dev_name) 394 if (!maps[i].dev && !maps[i].dev_name)
@@ -380,12 +399,17 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps,
380 pr_debug("register map %s, function %s\n", 399 pr_debug("register map %s, function %s\n",
381 maps[i].name, 400 maps[i].name,
382 maps[i].function); 401 maps[i].function);
383 }
384 402
385 pinmux_maps = maps; 403 pinmux_maps_num++;
386 pinmux_maps_num = num_maps; 404 }
387 405
388 return 0; 406 return 0;
407
408err_out_free:
409 kfree(pinmux_maps);
410 pinmux_maps = NULL;
411 pinmux_maps_num = 0;
412 return ret;
389} 413}
390 414
391/** 415/**