forked from Minki/linux
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>
This commit is contained in:
parent
542e704f3f
commit
97607d157c
@ -697,7 +697,7 @@ spi on the second function mapping:
|
||||
|
||||
#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",
|
||||
.function = "spi0",
|
||||
@ -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
|
||||
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"),
|
||||
};
|
||||
|
||||
|
@ -1605,7 +1605,7 @@ static struct platform_device pinmux_device = {
|
||||
};
|
||||
|
||||
/* Pinmux settings */
|
||||
static struct pinmux_map u300_pinmux_map[] = {
|
||||
static struct pinmux_map __initdata u300_pinmux_map[] = {
|
||||
/* anonymous maps for chip power and EMIFs */
|
||||
PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"),
|
||||
PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"),
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
@ -33,7 +34,7 @@ static DEFINE_MUTEX(pinmux_list_mutex);
|
||||
static LIST_HEAD(pinmux_list);
|
||||
|
||||
/* 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;
|
||||
|
||||
/**
|
||||
@ -333,7 +334,9 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Only call this once during initialization of your machine, the function is
|
||||
@ -344,32 +347,48 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output);
|
||||
int __init pinmux_register_mappings(struct pinmux_map const *maps,
|
||||
unsigned num_maps)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
if (pinmux_maps != NULL) {
|
||||
if (pinmux_maps_num != 0) {
|
||||
pr_err("pinmux mappings already registered, you can only "
|
||||
"register one set of maps\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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++) {
|
||||
/* Sanity check the mapping */
|
||||
/* Sanity check the mapping while copying it */
|
||||
if (!maps[i].name) {
|
||||
pr_err("failed to register map %d: "
|
||||
"no map name given\n", i);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_out_free;
|
||||
}
|
||||
|
||||
if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) {
|
||||
pr_err("failed to register map %s (%d): "
|
||||
"no pin control device given\n",
|
||||
maps[i].name, i);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_out_free;
|
||||
}
|
||||
|
||||
if (!maps[i].function) {
|
||||
pr_err("failed to register map %s (%d): "
|
||||
"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)
|
||||
@ -380,12 +399,17 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps,
|
||||
pr_debug("register map %s, function %s\n",
|
||||
maps[i].name,
|
||||
maps[i].function);
|
||||
|
||||
pinmux_maps_num++;
|
||||
}
|
||||
|
||||
pinmux_maps = maps;
|
||||
pinmux_maps_num = num_maps;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_free:
|
||||
kfree(pinmux_maps);
|
||||
pinmux_maps = NULL;
|
||||
pinmux_maps_num = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,7 +48,7 @@ struct pinmux_map {
|
||||
const char *group;
|
||||
struct device *dev;
|
||||
const char *dev_name;
|
||||
const bool hog_on_boot;
|
||||
bool hog_on_boot;
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user