mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 05:34:13 +08:00
Merge branch 'for-torvalds' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Here are some fixes to the pin control system that has accumulated since -rc1. Mainly Tony Lindgren fixed the module load/unload logic and the rest are minor fixes and documentation. * 'for-torvalds' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: pinctrl: add checks for empty function names pinctrl: fix pinmux_hog_maps when ctrl_dev_name is not set pinctrl: fix some pinmux typos pinctrl: free debugfs entries when unloading a pinmux driver pinctrl: unbreak error messages Documentation/pinctrl: fix a few syntax errors in code examples pinctrl: fix pinconf_pins_show iteration
This commit is contained in:
commit
8e2a2880a5
@ -857,42 +857,41 @@ case), we define a mapping like this:
|
||||
|
||||
...
|
||||
{
|
||||
.name "2bit"
|
||||
.name = "2bit"
|
||||
.ctrl_dev_name = "pinctrl-foo",
|
||||
.function = "mmc0",
|
||||
.group = "mmc0_1_grp",
|
||||
.dev_name = "foo-mmc.0",
|
||||
},
|
||||
{
|
||||
.name "4bit"
|
||||
.name = "4bit"
|
||||
.ctrl_dev_name = "pinctrl-foo",
|
||||
.function = "mmc0",
|
||||
.group = "mmc0_1_grp",
|
||||
.dev_name = "foo-mmc.0",
|
||||
},
|
||||
{
|
||||
.name "4bit"
|
||||
.name = "4bit"
|
||||
.ctrl_dev_name = "pinctrl-foo",
|
||||
.function = "mmc0",
|
||||
.group = "mmc0_2_grp",
|
||||
.dev_name = "foo-mmc.0",
|
||||
},
|
||||
{
|
||||
.name "8bit"
|
||||
.name = "8bit"
|
||||
.ctrl_dev_name = "pinctrl-foo",
|
||||
.function = "mmc0",
|
||||
.group = "mmc0_1_grp",
|
||||
.dev_name = "foo-mmc.0",
|
||||
},
|
||||
{
|
||||
.name "8bit"
|
||||
.name = "8bit"
|
||||
.ctrl_dev_name = "pinctrl-foo",
|
||||
.function = "mmc0",
|
||||
.group = "mmc0_2_grp",
|
||||
.dev_name = "foo-mmc.0",
|
||||
},
|
||||
{
|
||||
.name "8bit"
|
||||
.name = "8bit"
|
||||
.ctrl_dev_name = "pinctrl-foo",
|
||||
.function = "mmc0",
|
||||
.group = "mmc0_3_grp",
|
||||
@ -995,7 +994,7 @@ This is enabled by simply setting the .hog_on_boot field in the map to true,
|
||||
like this:
|
||||
|
||||
{
|
||||
.name "POWERMAP"
|
||||
.name = "POWERMAP"
|
||||
.ctrl_dev_name = "pinctrl-foo",
|
||||
.function = "power_func",
|
||||
.hog_on_boot = true,
|
||||
@ -1025,7 +1024,7 @@ it, disables and releases it, and muxes it in on the pins defined by group B:
|
||||
|
||||
foo_switch()
|
||||
{
|
||||
struct pinmux pmx;
|
||||
struct pinmux *pmx;
|
||||
|
||||
/* Enable on position A */
|
||||
pmx = pinmux_get(&device, "spi0-pos-A");
|
||||
|
@ -510,10 +510,12 @@ static struct dentry *debugfs_root;
|
||||
|
||||
static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
static struct dentry *device_root;
|
||||
struct dentry *device_root;
|
||||
|
||||
device_root = debugfs_create_dir(dev_name(pctldev->dev),
|
||||
debugfs_root);
|
||||
pctldev->device_root = device_root;
|
||||
|
||||
if (IS_ERR(device_root) || !device_root) {
|
||||
pr_warn("failed to create debugfs directory for %s\n",
|
||||
dev_name(pctldev->dev));
|
||||
@ -529,6 +531,11 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
|
||||
pinconf_init_device_debugfs(device_root, pctldev);
|
||||
}
|
||||
|
||||
static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
debugfs_remove_recursive(pctldev->device_root);
|
||||
}
|
||||
|
||||
static void pinctrl_init_debugfs(void)
|
||||
{
|
||||
debugfs_root = debugfs_create_dir("pinctrl", NULL);
|
||||
@ -553,6 +560,10 @@ static void pinctrl_init_debugfs(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -572,26 +583,6 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||
if (pctldesc->name == NULL)
|
||||
return NULL;
|
||||
|
||||
/* If we're implementing pinmuxing, check the ops for sanity */
|
||||
if (pctldesc->pmxops) {
|
||||
ret = pinmux_check_ops(pctldesc->pmxops);
|
||||
if (ret) {
|
||||
pr_err("%s pinmux ops lacks necessary functions\n",
|
||||
pctldesc->name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're implementing pinconfig, check the ops for sanity */
|
||||
if (pctldesc->confops) {
|
||||
ret = pinconf_check_ops(pctldesc->confops);
|
||||
if (ret) {
|
||||
pr_err("%s pin config ops lacks necessary functions\n",
|
||||
pctldesc->name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
|
||||
if (pctldev == NULL)
|
||||
return NULL;
|
||||
@ -606,6 +597,26 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||
mutex_init(&pctldev->gpio_ranges_lock);
|
||||
pctldev->dev = dev;
|
||||
|
||||
/* If we're implementing pinmuxing, check the ops for sanity */
|
||||
if (pctldesc->pmxops) {
|
||||
ret = pinmux_check_ops(pctldev);
|
||||
if (ret) {
|
||||
pr_err("%s pinmux ops lacks necessary functions\n",
|
||||
pctldesc->name);
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're implementing pinconfig, check the ops for sanity */
|
||||
if (pctldesc->confops) {
|
||||
ret = pinconf_check_ops(pctldev);
|
||||
if (ret) {
|
||||
pr_err("%s pin config ops lacks necessary functions\n",
|
||||
pctldesc->name);
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Register all the pins */
|
||||
pr_debug("try to register %d pins on %s...\n",
|
||||
pctldesc->npins, pctldesc->name);
|
||||
@ -641,6 +652,7 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
|
||||
if (pctldev == NULL)
|
||||
return;
|
||||
|
||||
pinctrl_remove_device_debugfs(pctldev);
|
||||
pinmux_unhog_maps(pctldev);
|
||||
/* TODO: check that no pinmuxes are still active? */
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
@ -41,6 +41,9 @@ struct pinctrl_dev {
|
||||
struct device *dev;
|
||||
struct module *owner;
|
||||
void *driver_data;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *device_root;
|
||||
#endif
|
||||
#ifdef CONFIG_PINMUX
|
||||
struct mutex pinmux_hogs_lock;
|
||||
struct list_head pinmux_hogs;
|
||||
|
@ -205,8 +205,10 @@ int pin_config_group_set(const char *dev_name, const char *pin_group,
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_group_set);
|
||||
|
||||
int pinconf_check_ops(const struct pinconf_ops *ops)
|
||||
int pinconf_check_ops(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
const struct pinconf_ops *ops = pctldev->desc->confops;
|
||||
|
||||
/* We must be able to read out pin status */
|
||||
if (!ops->pin_config_get && !ops->pin_config_group_get)
|
||||
return -EINVAL;
|
||||
@ -236,7 +238,7 @@ static int pinconf_pins_show(struct seq_file *s, void *what)
|
||||
seq_puts(s, "Format: pin (name): pinmux setting array\n");
|
||||
|
||||
/* The pin number can be retrived from the pin controller descriptor */
|
||||
for (i = 0; pin < pctldev->desc->npins; i++) {
|
||||
for (i = 0; i < pctldev->desc->npins; i++) {
|
||||
struct pin_desc *desc;
|
||||
|
||||
pin = pctldev->desc->pins[i].number;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#ifdef CONFIG_PINCONF
|
||||
|
||||
int pinconf_check_ops(const struct pinconf_ops *ops);
|
||||
int pinconf_check_ops(struct pinctrl_dev *pctldev);
|
||||
void pinconf_init_device_debugfs(struct dentry *devroot,
|
||||
struct pinctrl_dev *pctldev);
|
||||
int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
@ -23,7 +23,7 @@ int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
|
||||
#else
|
||||
|
||||
static inline int pinconf_check_ops(const struct pinconf_ops *ops)
|
||||
static inline int pinconf_check_ops(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -53,11 +53,6 @@ struct pinmux_group {
|
||||
* @dev: the device using this pinmux
|
||||
* @usecount: the number of active users of this mux setting, used to keep
|
||||
* track of nested use cases
|
||||
* @pins: an array of discrete physical pins used in this mapping, taken
|
||||
* from the global pin enumeration space (copied from pinmux map)
|
||||
* @num_pins: the number of pins in this mapping array, i.e. the number of
|
||||
* elements in .pins so we can iterate over that array (copied from
|
||||
* pinmux map)
|
||||
* @pctldev: pin control device handling this pinmux
|
||||
* @func_selector: the function selector for the pinmux device handling
|
||||
* this pinmux
|
||||
@ -152,8 +147,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
|
||||
status = 0;
|
||||
|
||||
if (status)
|
||||
dev_err(pctldev->dev, "->request on device %s failed "
|
||||
"for pin %d\n",
|
||||
dev_err(pctldev->dev, "->request on device %s failed for pin %d\n",
|
||||
pctldev->desc->name, pin);
|
||||
out_free_pin:
|
||||
if (status) {
|
||||
@ -355,21 +349,20 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps,
|
||||
/* First sanity check the new mapping */
|
||||
for (i = 0; i < num_maps; i++) {
|
||||
if (!maps[i].name) {
|
||||
pr_err("failed to register map %d: "
|
||||
"no map name given\n", i);
|
||||
pr_err("failed to register map %d: no map name given\n",
|
||||
i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) {
|
||||
pr_err("failed to register map %s (%d): "
|
||||
"no pin control device given\n",
|
||||
pr_err("failed to register map %s (%d): no pin control device given\n",
|
||||
maps[i].name, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!maps[i].function) {
|
||||
pr_err("failed to register map %s (%d): "
|
||||
"no function ID given\n", maps[i].name, i);
|
||||
pr_err("failed to register map %s (%d): no function ID given\n",
|
||||
maps[i].name, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -411,7 +404,7 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps,
|
||||
}
|
||||
|
||||
/**
|
||||
* acquire_pins() - acquire all the pins for a certain funcion on a pinmux
|
||||
* acquire_pins() - acquire all the pins for a certain function on a pinmux
|
||||
* @pctldev: the device to take the pins on
|
||||
* @func_selector: the function selector to acquire the pins for
|
||||
* @group_selector: the group selector containing the pins to acquire
|
||||
@ -442,8 +435,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
|
||||
ret = pin_request(pctldev, pins[i], func, NULL);
|
||||
if (ret) {
|
||||
dev_err(pctldev->dev,
|
||||
"could not get pin %d for function %s "
|
||||
"on device %s - conflicting mux mappings?\n",
|
||||
"could not get pin %d for function %s on device %s - conflicting mux mappings?\n",
|
||||
pins[i], func ? : "(undefined)",
|
||||
pinctrl_dev_get_name(pctldev));
|
||||
/* On error release all taken pins */
|
||||
@ -458,7 +450,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
|
||||
|
||||
/**
|
||||
* release_pins() - release pins taken by earlier acquirement
|
||||
* @pctldev: the device to free the pinx on
|
||||
* @pctldev: the device to free the pins on
|
||||
* @group_selector: the group selector containing the pins to free
|
||||
*/
|
||||
static void release_pins(struct pinctrl_dev *pctldev,
|
||||
@ -473,8 +465,7 @@ static void release_pins(struct pinctrl_dev *pctldev,
|
||||
ret = pctlops->get_group_pins(pctldev, group_selector,
|
||||
&pins, &num_pins);
|
||||
if (ret) {
|
||||
dev_err(pctldev->dev, "could not get pins to release for "
|
||||
"group selector %d\n",
|
||||
dev_err(pctldev->dev, "could not get pins to release for group selector %d\n",
|
||||
group_selector);
|
||||
return;
|
||||
}
|
||||
@ -526,8 +517,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
|
||||
ret = pinctrl_get_group_selector(pctldev, groups[0]);
|
||||
if (ret < 0) {
|
||||
dev_err(pctldev->dev,
|
||||
"function %s wants group %s but the pin "
|
||||
"controller does not seem to have that group\n",
|
||||
"function %s wants group %s but the pin controller does not seem to have that group\n",
|
||||
pmxops->get_function_name(pctldev, func_selector),
|
||||
groups[0]);
|
||||
return ret;
|
||||
@ -535,8 +525,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
|
||||
|
||||
if (num_groups > 1)
|
||||
dev_dbg(pctldev->dev,
|
||||
"function %s support more than one group, "
|
||||
"default-selecting first group %s (%d)\n",
|
||||
"function %s support more than one group, default-selecting first group %s (%d)\n",
|
||||
pmxops->get_function_name(pctldev, func_selector),
|
||||
groups[0],
|
||||
ret);
|
||||
@ -628,10 +617,8 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
|
||||
|
||||
if (pmx->pctldev && pmx->pctldev != pctldev) {
|
||||
dev_err(pctldev->dev,
|
||||
"different pin control devices given for device %s, "
|
||||
"function %s\n",
|
||||
devname,
|
||||
map->function);
|
||||
"different pin control devices given for device %s, function %s\n",
|
||||
devname, map->function);
|
||||
return -EINVAL;
|
||||
}
|
||||
pmx->dev = dev;
|
||||
@ -695,7 +682,6 @@ static void pinmux_free_groups(struct pinmux *pmx)
|
||||
*/
|
||||
struct pinmux *pinmux_get(struct device *dev, const char *name)
|
||||
{
|
||||
|
||||
struct pinmux_map const *map = NULL;
|
||||
struct pinctrl_dev *pctldev = NULL;
|
||||
const char *devname = NULL;
|
||||
@ -745,8 +731,7 @@ struct pinmux *pinmux_get(struct device *dev, const char *name)
|
||||
else if (map->ctrl_dev_name)
|
||||
devname = map->ctrl_dev_name;
|
||||
|
||||
pr_warning("could not find a pinctrl device for pinmux "
|
||||
"function %s, fishy, they shall all have one\n",
|
||||
pr_warning("could not find a pinctrl device for pinmux function %s, fishy, they shall all have one\n",
|
||||
map->function);
|
||||
pr_warning("given pinctrl device name: %s",
|
||||
devname ? devname : "UNDEFINED");
|
||||
@ -904,8 +889,11 @@ void pinmux_disable(struct pinmux *pmx)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinmux_disable);
|
||||
|
||||
int pinmux_check_ops(const struct pinmux_ops *ops)
|
||||
int pinmux_check_ops(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
const struct pinmux_ops *ops = pctldev->desc->pmxops;
|
||||
unsigned selector = 0;
|
||||
|
||||
/* Check that we implement required operations */
|
||||
if (!ops->list_functions ||
|
||||
!ops->get_function_name ||
|
||||
@ -914,6 +902,18 @@ int pinmux_check_ops(const struct pinmux_ops *ops)
|
||||
!ops->disable)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check that all functions registered have names */
|
||||
while (ops->list_functions(pctldev, selector) >= 0) {
|
||||
const char *fname = ops->get_function_name(pctldev,
|
||||
selector);
|
||||
if (!fname) {
|
||||
pr_err("pinmux ops has no name for function%u\n",
|
||||
selector);
|
||||
return -EINVAL;
|
||||
}
|
||||
selector++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -932,8 +932,8 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
|
||||
* without any problems, so then we can hog pinmuxes for
|
||||
* all devices that just want a static pin mux at this point.
|
||||
*/
|
||||
dev_err(pctldev->dev, "map %s wants to hog a non-system "
|
||||
"pinmux, this is not going to work\n", map->name);
|
||||
dev_err(pctldev->dev, "map %s wants to hog a non-system pinmux, this is not going to work\n",
|
||||
map->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -993,9 +993,12 @@ int pinmux_hog_maps(struct pinctrl_dev *pctldev)
|
||||
for (i = 0; i < pinmux_maps_num; i++) {
|
||||
struct pinmux_map const *map = &pinmux_maps[i];
|
||||
|
||||
if (((map->ctrl_dev == dev) ||
|
||||
!strcmp(map->ctrl_dev_name, devname)) &&
|
||||
map->hog_on_boot) {
|
||||
if (!map->hog_on_boot)
|
||||
continue;
|
||||
|
||||
if ((map->ctrl_dev == dev) ||
|
||||
(map->ctrl_dev_name &&
|
||||
!strcmp(map->ctrl_dev_name, devname))) {
|
||||
/* OK time to hog! */
|
||||
ret = pinmux_hog_map(pctldev, map);
|
||||
if (ret)
|
||||
@ -1122,13 +1125,15 @@ static int pinmux_show(struct seq_file *s, void *what)
|
||||
|
||||
seq_printf(s, "device: %s function: %s (%u),",
|
||||
pinctrl_dev_get_name(pmx->pctldev),
|
||||
pmxops->get_function_name(pctldev, pmx->func_selector),
|
||||
pmxops->get_function_name(pctldev,
|
||||
pmx->func_selector),
|
||||
pmx->func_selector);
|
||||
|
||||
seq_printf(s, " groups: [");
|
||||
list_for_each_entry(grp, &pmx->groups, node) {
|
||||
seq_printf(s, " %s (%u)",
|
||||
pctlops->get_group_name(pctldev, grp->group_selector),
|
||||
pctlops->get_group_name(pctldev,
|
||||
grp->group_selector),
|
||||
grp->group_selector);
|
||||
}
|
||||
seq_printf(s, " ]");
|
||||
|
@ -12,7 +12,7 @@
|
||||
*/
|
||||
#ifdef CONFIG_PINMUX
|
||||
|
||||
int pinmux_check_ops(const struct pinmux_ops *ops);
|
||||
int pinmux_check_ops(struct pinctrl_dev *pctldev);
|
||||
void pinmux_init_device_debugfs(struct dentry *devroot,
|
||||
struct pinctrl_dev *pctldev);
|
||||
void pinmux_init_debugfs(struct dentry *subsys_root);
|
||||
@ -21,7 +21,7 @@ void pinmux_unhog_maps(struct pinctrl_dev *pctldev);
|
||||
|
||||
#else
|
||||
|
||||
static inline int pinmux_check_ops(const struct pinmux_ops *ops)
|
||||
static inline int pinmux_check_ops(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user