Commit 97607d15 authored by Linus Walleij's avatar Linus Walleij

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: default avatarArnd Bergmann <arnd.bergmann@linaro.org>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 542e704f
...@@ -697,7 +697,7 @@ spi on the second function mapping: ...@@ -697,7 +697,7 @@ spi on the second function mapping:
#include <linux/pinctrl/machine.h> #include <linux/pinctrl/machine.h>
static const struct pinmux_map pmx_mapping[] = { static const struct pinmux_map __initdata pmx_mapping[] = {
{ {
.ctrl_dev_name = "pinctrl.0", .ctrl_dev_name = "pinctrl.0",
.function = "spi0", .function = "spi0",
...@@ -734,7 +734,7 @@ Since the above construct is pretty common there is a helper macro to make ...@@ -734,7 +734,7 @@ Since the above construct is pretty common there is a helper macro to make
it even more compact which assumes you want to use pinctrl.0 and position it even more compact which assumes you want to use pinctrl.0 and position
0 for mapping, for example: 0 for mapping, for example:
static struct pinmux_map pmx_mapping[] = { static struct pinmux_map __initdata pmx_mapping[] = {
PINMUX_MAP_PRIMARY("I2CMAP", "i2c0", "foo-i2c.0"), PINMUX_MAP_PRIMARY("I2CMAP", "i2c0", "foo-i2c.0"),
}; };
......
...@@ -1605,7 +1605,7 @@ static struct platform_device pinmux_device = { ...@@ -1605,7 +1605,7 @@ static struct platform_device pinmux_device = {
}; };
/* Pinmux settings */ /* Pinmux settings */
static struct pinmux_map u300_pinmux_map[] = { static struct pinmux_map __initdata u300_pinmux_map[] = {
/* anonymous maps for chip power and EMIFs */ /* anonymous maps for chip power and EMIFs */
PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"), PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"),
PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"), PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"),
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
...@@ -33,7 +34,7 @@ static DEFINE_MUTEX(pinmux_list_mutex); ...@@ -33,7 +34,7 @@ static DEFINE_MUTEX(pinmux_list_mutex);
static LIST_HEAD(pinmux_list); static LIST_HEAD(pinmux_list);
/* Global pinmux maps, we allow one set only */ /* Global pinmux maps, we allow one set only */
static struct pinmux_map const *pinmux_maps; static struct pinmux_map *pinmux_maps;
static unsigned pinmux_maps_num; static unsigned pinmux_maps_num;
/** /**
...@@ -333,7 +334,9 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output); ...@@ -333,7 +334,9 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output);
/** /**
* pinmux_register_mappings() - register a set of pinmux mappings * pinmux_register_mappings() - register a set of pinmux mappings
* @maps: the pinmux mappings table to register * @maps: the pinmux mappings table to register, this should be marked with
* __initdata so it can be discarded after boot, this function will
* perform a shallow copy for the mapping entries.
* @num_maps: the number of maps in the mapping table * @num_maps: the number of maps in the mapping table
* *
* Only call this once during initialization of your machine, the function is * Only call this once during initialization of your machine, the function is
...@@ -344,32 +347,48 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output); ...@@ -344,32 +347,48 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output);
int __init pinmux_register_mappings(struct pinmux_map const *maps, int __init pinmux_register_mappings(struct pinmux_map const *maps,
unsigned num_maps) unsigned num_maps)
{ {
int ret = 0;
int i; int i;
if (pinmux_maps != NULL) { if (pinmux_maps_num != 0) {
pr_err("pinmux mappings already registered, you can only " pr_err("pinmux mappings already registered, you can only "
"register one set of maps\n"); "register one set of maps\n");
return -EINVAL; return -EINVAL;
} }
pr_debug("add %d pinmux maps\n", num_maps); pr_debug("add %d pinmux maps\n", num_maps);
/*
* Make a copy of the map array - string pointers will end up in the
* kernel const section anyway so these do not need to be deep copied.
*/
pinmux_maps = kmemdup(maps, sizeof(struct pinmux_map) * num_maps,
GFP_KERNEL);
if (!pinmux_maps)
return -ENOMEM;
for (i = 0; i < num_maps; i++) { for (i = 0; i < num_maps; i++) {
/* Sanity check the mapping */ /* Sanity check the mapping while copying it */
if (!maps[i].name) { if (!maps[i].name) {
pr_err("failed to register map %d: " pr_err("failed to register map %d: "
"no map name given\n", i); "no map name given\n", i);
return -EINVAL; ret = -EINVAL;
goto err_out_free;
} }
if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) {
pr_err("failed to register map %s (%d): " pr_err("failed to register map %s (%d): "
"no pin control device given\n", "no pin control device given\n",
maps[i].name, i); maps[i].name, i);
return -EINVAL; ret = -EINVAL;
goto err_out_free;
} }
if (!maps[i].function) { if (!maps[i].function) {
pr_err("failed to register map %s (%d): " pr_err("failed to register map %s (%d): "
"no function ID given\n", maps[i].name, i); "no function ID given\n", maps[i].name, i);
return -EINVAL; ret = -EINVAL;
goto err_out_free;
} }
if (!maps[i].dev && !maps[i].dev_name) if (!maps[i].dev && !maps[i].dev_name)
...@@ -380,12 +399,17 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, ...@@ -380,12 +399,17 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps,
pr_debug("register map %s, function %s\n", pr_debug("register map %s, function %s\n",
maps[i].name, maps[i].name,
maps[i].function); maps[i].function);
}
pinmux_maps = maps; pinmux_maps_num++;
pinmux_maps_num = num_maps; }
return 0; return 0;
err_out_free:
kfree(pinmux_maps);
pinmux_maps = NULL;
pinmux_maps_num = 0;
return ret;
} }
/** /**
......
...@@ -48,7 +48,7 @@ struct pinmux_map { ...@@ -48,7 +48,7 @@ struct pinmux_map {
const char *group; const char *group;
struct device *dev; struct device *dev;
const char *dev_name; const char *dev_name;
const bool hog_on_boot; bool hog_on_boot;
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment