mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
pinctrl: introduce PINCTRL_STATE_DEFAULT, define hogs as that state
This provides a single centralized name for the default state. Update PIN_MAP_* macros to use this state name, instead of requiring the user to pass a state name in. With this change, hog entries in the mapping table are defined as those with state name PINCTRL_STATE_DEFAULT, i.e. all entries have the same name. This interacts badly with the nested iteration over mapping table entries in pinctrl_hog_maps() and pinctrl_hog_map() which would now attempt to claim each hog mapping table entry multiple times. Replacing the custom hog code with a simple pinctrl_get()/pinctrl_enable(). Update documentation and mapping tables to use this. Signed-off-by: Stephen Warren <swarren@nvidia.com> Acked-by: Dong Aisheng <dong.aisheng@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
d4e3198736
commit
46919ae63d
@ -814,7 +814,7 @@ it even more compact which assumes you want to use pinctrl-foo and position
|
|||||||
0 for mapping, for example:
|
0 for mapping, for example:
|
||||||
|
|
||||||
static struct pinctrl_map __initdata mapping[] = {
|
static struct pinctrl_map __initdata mapping[] = {
|
||||||
PIN_MAP("I2CMAP", "pinctrl-foo", "i2c0", "foo-i2c.0"),
|
PIN_MAP(PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", "foo-i2c.0"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -930,7 +930,7 @@ foo_probe()
|
|||||||
/* Allocate a state holder named "state" etc */
|
/* Allocate a state holder named "state" etc */
|
||||||
struct pinctrl p;
|
struct pinctrl p;
|
||||||
|
|
||||||
p = pinctrl_get(&device, NULL);
|
p = pinctrl_get(&device, PINCTRL_STATE_DEFAULT);
|
||||||
if IS_ERR(p)
|
if IS_ERR(p)
|
||||||
return PTR_ERR(p);
|
return PTR_ERR(p);
|
||||||
pinctrl_enable(p);
|
pinctrl_enable(p);
|
||||||
@ -989,7 +989,7 @@ of the pin controller itself, like this:
|
|||||||
|
|
||||||
{
|
{
|
||||||
.dev_name = "pinctrl-foo",
|
.dev_name = "pinctrl-foo",
|
||||||
.name = "POWERMAP"
|
.name = PINCTRL_STATE_DEFAULT,
|
||||||
.ctrl_dev_name = "pinctrl-foo",
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
.function = "power_func",
|
.function = "power_func",
|
||||||
},
|
},
|
||||||
@ -998,7 +998,7 @@ Since it may be common to request the core to hog a few always-applicable
|
|||||||
mux settings on the primary pin controller, there is a convenience macro for
|
mux settings on the primary pin controller, there is a convenience macro for
|
||||||
this:
|
this:
|
||||||
|
|
||||||
PIN_MAP_PRIMARY_SYS_HOG("POWERMAP", "pinctrl-foo", "power_func")
|
PIN_MAP_SYS_HOG("pinctrl-foo", "power_func")
|
||||||
|
|
||||||
This gives the exact same result as the above construction.
|
This gives the exact same result as the above construction.
|
||||||
|
|
||||||
|
@ -1608,9 +1608,9 @@ static struct platform_device dma_device = {
|
|||||||
/* Pinmux settings */
|
/* Pinmux settings */
|
||||||
static struct pinctrl_map __initdata u300_pinmux_map[] = {
|
static struct pinctrl_map __initdata u300_pinmux_map[] = {
|
||||||
/* anonymous maps for chip power and EMIFs */
|
/* anonymous maps for chip power and EMIFs */
|
||||||
PIN_MAP_SYS_HOG("POWER", "pinctrl-u300", "power"),
|
PIN_MAP_SYS_HOG("pinctrl-u300", "power"),
|
||||||
PIN_MAP_SYS_HOG("EMIF0", "pinctrl-u300", "emif0"),
|
PIN_MAP_SYS_HOG("pinctrl-u300", "emif0"),
|
||||||
PIN_MAP_SYS_HOG("EMIF1", "pinctrl-u300", "emif1"),
|
PIN_MAP_SYS_HOG("pinctrl-u300", "emif1"),
|
||||||
/* per-device maps for MMC/SD, SPI and UART */
|
/* per-device maps for MMC/SD, SPI and UART */
|
||||||
PIN_MAP("MMCSD", "pinctrl-u300", "mmc0", "mmci"),
|
PIN_MAP("MMCSD", "pinctrl-u300", "mmc0", "mmci"),
|
||||||
PIN_MAP("SPI", "pinctrl-u300", "spi0", "pl022"),
|
PIN_MAP("SPI", "pinctrl-u300", "spi0", "pl022"),
|
||||||
|
@ -44,18 +44,6 @@ struct pinctrl_maps {
|
|||||||
unsigned num_maps;
|
unsigned num_maps;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* struct pinctrl_hog - a list item to stash control hogs
|
|
||||||
* @node: pin control hog list node
|
|
||||||
* @map: map entry responsible for this hogging
|
|
||||||
* @pmx: the pin control hogged by this item
|
|
||||||
*/
|
|
||||||
struct pinctrl_hog {
|
|
||||||
struct list_head node;
|
|
||||||
struct pinctrl_map const *map;
|
|
||||||
struct pinctrl *p;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Global list of pin control devices */
|
/* Global list of pin control devices */
|
||||||
static DEFINE_MUTEX(pinctrldev_list_mutex);
|
static DEFINE_MUTEX(pinctrldev_list_mutex);
|
||||||
static LIST_HEAD(pinctrldev_list);
|
static LIST_HEAD(pinctrldev_list);
|
||||||
@ -702,103 +690,6 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hog a single map entry and add to the hoglist */
|
|
||||||
static int pinctrl_hog_map(struct pinctrl_dev *pctldev,
|
|
||||||
struct pinctrl_map const *map)
|
|
||||||
{
|
|
||||||
struct pinctrl_hog *hog;
|
|
||||||
struct pinctrl *p;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
hog = kzalloc(sizeof(*hog), GFP_KERNEL);
|
|
||||||
if (!hog) {
|
|
||||||
dev_err(pctldev->dev, "failed to alloc struct pinctrl_hog\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = pinctrl_get_locked(pctldev->dev, map->name);
|
|
||||||
if (IS_ERR(p)) {
|
|
||||||
kfree(hog);
|
|
||||||
dev_err(pctldev->dev,
|
|
||||||
"could not get the %s pin control mapping for hogging\n",
|
|
||||||
map->name);
|
|
||||||
return PTR_ERR(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = pinctrl_enable(p);
|
|
||||||
if (ret) {
|
|
||||||
pinctrl_put(p);
|
|
||||||
kfree(hog);
|
|
||||||
dev_err(pctldev->dev,
|
|
||||||
"could not enable the %s pin control mapping for hogging\n",
|
|
||||||
map->name);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
hog->map = map;
|
|
||||||
hog->p = p;
|
|
||||||
|
|
||||||
dev_info(pctldev->dev, "hogged map %s, function %s\n", map->name,
|
|
||||||
map->function);
|
|
||||||
list_add_tail(&hog->node, &pctldev->pinctrl_hogs);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pinctrl_hog_maps() - hog specific map entries on controller device
|
|
||||||
* @pctldev: the pin control device to hog entries on
|
|
||||||
*
|
|
||||||
* When the pin controllers are registered, there may be some specific pinmux
|
|
||||||
* map entries that need to be hogged, i.e. get+enabled until the system shuts
|
|
||||||
* down.
|
|
||||||
*/
|
|
||||||
static int pinctrl_hog_maps(struct pinctrl_dev *pctldev)
|
|
||||||
{
|
|
||||||
struct device *dev = pctldev->dev;
|
|
||||||
const char *devname = dev_name(dev);
|
|
||||||
int ret;
|
|
||||||
struct pinctrl_maps *maps_node;
|
|
||||||
int i;
|
|
||||||
struct pinctrl_map const *map;
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&pctldev->pinctrl_hogs);
|
|
||||||
|
|
||||||
mutex_lock(&pinctrl_maps_mutex);
|
|
||||||
for_each_maps(maps_node, i, map) {
|
|
||||||
if (!strcmp(map->ctrl_dev_name, devname) &&
|
|
||||||
!strcmp(map->dev_name, devname)) {
|
|
||||||
/* OK time to hog! */
|
|
||||||
ret = pinctrl_hog_map(pctldev, map);
|
|
||||||
if (ret) {
|
|
||||||
mutex_unlock(&pinctrl_maps_mutex);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mutex_unlock(&pinctrl_maps_mutex);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pinctrl_unhog_maps() - unhog specific map entries on controller device
|
|
||||||
* @pctldev: the pin control device to unhog entries on
|
|
||||||
*/
|
|
||||||
static void pinctrl_unhog_maps(struct pinctrl_dev *pctldev)
|
|
||||||
{
|
|
||||||
struct list_head *node, *tmp;
|
|
||||||
|
|
||||||
list_for_each_safe(node, tmp, &pctldev->pinctrl_hogs) {
|
|
||||||
struct pinctrl_hog *hog =
|
|
||||||
list_entry(node, struct pinctrl_hog, node);
|
|
||||||
pinctrl_disable(hog->p);
|
|
||||||
pinctrl_put(hog->p);
|
|
||||||
list_del(node);
|
|
||||||
kfree(hog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|
||||||
static int pinctrl_pins_show(struct seq_file *s, void *what)
|
static int pinctrl_pins_show(struct seq_file *s, void *what)
|
||||||
@ -889,19 +780,6 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pinmux_hogs_show(struct seq_file *s, void *what)
|
|
||||||
{
|
|
||||||
struct pinctrl_dev *pctldev = s->private;
|
|
||||||
struct pinctrl_hog *hog;
|
|
||||||
|
|
||||||
seq_puts(s, "Pin control map hogs held by device\n");
|
|
||||||
|
|
||||||
list_for_each_entry(hog, &pctldev->pinctrl_hogs, node)
|
|
||||||
seq_printf(s, "%s\n", hog->map->name);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pinctrl_devices_show(struct seq_file *s, void *what)
|
static int pinctrl_devices_show(struct seq_file *s, void *what)
|
||||||
{
|
{
|
||||||
struct pinctrl_dev *pctldev;
|
struct pinctrl_dev *pctldev;
|
||||||
@ -988,11 +866,6 @@ static int pinctrl_gpioranges_open(struct inode *inode, struct file *file)
|
|||||||
return single_open(file, pinctrl_gpioranges_show, inode->i_private);
|
return single_open(file, pinctrl_gpioranges_show, inode->i_private);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pinmux_hogs_open(struct inode *inode, struct file *file)
|
|
||||||
{
|
|
||||||
return single_open(file, pinmux_hogs_show, inode->i_private);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pinctrl_devices_open(struct inode *inode, struct file *file)
|
static int pinctrl_devices_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
return single_open(file, pinctrl_devices_show, NULL);
|
return single_open(file, pinctrl_devices_show, NULL);
|
||||||
@ -1029,13 +902,6 @@ static const struct file_operations pinctrl_gpioranges_ops = {
|
|||||||
.release = single_release,
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct file_operations pinmux_hogs_ops = {
|
|
||||||
.open = pinmux_hogs_open,
|
|
||||||
.read = seq_read,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct file_operations pinctrl_devices_ops = {
|
static const struct file_operations pinctrl_devices_ops = {
|
||||||
.open = pinctrl_devices_open,
|
.open = pinctrl_devices_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
@ -1078,8 +944,6 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
|
|||||||
device_root, pctldev, &pinctrl_groups_ops);
|
device_root, pctldev, &pinctrl_groups_ops);
|
||||||
debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO,
|
debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO,
|
||||||
device_root, pctldev, &pinctrl_gpioranges_ops);
|
device_root, pctldev, &pinctrl_gpioranges_ops);
|
||||||
debugfs_create_file("pinmux-hogs", S_IFREG | S_IRUGO,
|
|
||||||
device_root, pctldev, &pinmux_hogs_ops);
|
|
||||||
pinmux_init_device_debugfs(device_root, pctldev);
|
pinmux_init_device_debugfs(device_root, pctldev);
|
||||||
pinconf_init_device_debugfs(device_root, pctldev);
|
pinconf_init_device_debugfs(device_root, pctldev);
|
||||||
}
|
}
|
||||||
@ -1188,7 +1052,9 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
|||||||
mutex_lock(&pinctrldev_list_mutex);
|
mutex_lock(&pinctrldev_list_mutex);
|
||||||
list_add_tail(&pctldev->node, &pinctrldev_list);
|
list_add_tail(&pctldev->node, &pinctrldev_list);
|
||||||
mutex_unlock(&pinctrldev_list_mutex);
|
mutex_unlock(&pinctrldev_list_mutex);
|
||||||
pinctrl_hog_maps(pctldev);
|
pctldev->p = pinctrl_get(pctldev->dev, PINCTRL_STATE_DEFAULT);
|
||||||
|
if (!IS_ERR(pctldev->p))
|
||||||
|
pinctrl_enable(pctldev->p);
|
||||||
pinctrl_init_device_debugfs(pctldev);
|
pinctrl_init_device_debugfs(pctldev);
|
||||||
|
|
||||||
return pctldev;
|
return pctldev;
|
||||||
@ -1211,7 +1077,10 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
pinctrl_remove_device_debugfs(pctldev);
|
pinctrl_remove_device_debugfs(pctldev);
|
||||||
pinctrl_unhog_maps(pctldev);
|
if (!IS_ERR(pctldev->p)) {
|
||||||
|
pinctrl_disable(pctldev->p);
|
||||||
|
pinctrl_put(pctldev->p);
|
||||||
|
}
|
||||||
/* TODO: check that no pinmuxes are still active? */
|
/* TODO: check that no pinmuxes are still active? */
|
||||||
mutex_lock(&pinctrldev_list_mutex);
|
mutex_lock(&pinctrldev_list_mutex);
|
||||||
list_del(&pctldev->node);
|
list_del(&pctldev->node);
|
||||||
|
@ -27,7 +27,7 @@ struct pinctrl_gpio_range;
|
|||||||
* @owner: module providing the pin controller, used for refcounting
|
* @owner: module providing the pin controller, used for refcounting
|
||||||
* @driver_data: driver data for drivers registering to the pin controller
|
* @driver_data: driver data for drivers registering to the pin controller
|
||||||
* subsystem
|
* subsystem
|
||||||
* @pinctrl_hogs: list of pin control maps hogged by this device
|
* @p: result of pinctrl_get() for this device
|
||||||
* @device_root: debugfs root for this device
|
* @device_root: debugfs root for this device
|
||||||
*/
|
*/
|
||||||
struct pinctrl_dev {
|
struct pinctrl_dev {
|
||||||
@ -39,7 +39,7 @@ struct pinctrl_dev {
|
|||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
void *driver_data;
|
void *driver_data;
|
||||||
struct list_head pinctrl_hogs;
|
struct pinctrl *p;
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
struct dentry *device_root;
|
struct dentry *device_root;
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#ifndef __LINUX_PINCTRL_MACHINE_H
|
#ifndef __LINUX_PINCTRL_MACHINE_H
|
||||||
#define __LINUX_PINCTRL_MACHINE_H
|
#define __LINUX_PINCTRL_MACHINE_H
|
||||||
|
|
||||||
|
#include "pinctrl.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct pinctrl_map - boards/machines shall provide this map for devices
|
* struct pinctrl_map - boards/machines shall provide this map for devices
|
||||||
* @dev_name: the name of the device using this specific mapping, the name
|
* @dev_name: the name of the device using this specific mapping, the name
|
||||||
@ -49,17 +51,18 @@ struct pinctrl_map {
|
|||||||
* Convenience macro to map a system function onto a certain pinctrl device,
|
* Convenience macro to map a system function onto a certain pinctrl device,
|
||||||
* to be hogged by the pin control core until the system shuts down.
|
* to be hogged by the pin control core until the system shuts down.
|
||||||
*/
|
*/
|
||||||
#define PIN_MAP_SYS_HOG(a, b, c) \
|
#define PIN_MAP_SYS_HOG(a, b) \
|
||||||
{ .name = a, .ctrl_dev_name = b, .dev_name = b, .function = c, }
|
{ .name = PINCTRL_STATE_DEFAULT, .ctrl_dev_name = a, .dev_name = a, \
|
||||||
|
.function = b, }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convenience macro to map a system function onto a certain pinctrl device
|
* Convenience macro to map a system function onto a certain pinctrl device
|
||||||
* using a specified group, to be hogged by the pin control core until the
|
* using a specified group, to be hogged by the pin control core until the
|
||||||
* system shuts down.
|
* system shuts down.
|
||||||
*/
|
*/
|
||||||
#define PIN_MAP_SYS_HOG_GROUP(a, b, c, d) \
|
#define PIN_MAP_SYS_HOG_GROUP(a, b, c) \
|
||||||
{ .name = a, .ctrl_dev_name = b, .dev_name = b, .function = c, \
|
{ .name = PINCTRL_STATE_DEFAULT, .ctrl_dev_name = a, .dev_name = a, \
|
||||||
.group = d, }
|
.function = b, .group = c, }
|
||||||
|
|
||||||
#ifdef CONFIG_PINMUX
|
#ifdef CONFIG_PINMUX
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
|
|
||||||
|
#define PINCTRL_STATE_DEFAULT "default"
|
||||||
|
|
||||||
struct pinctrl_dev;
|
struct pinctrl_dev;
|
||||||
struct pinmux_ops;
|
struct pinmux_ops;
|
||||||
struct pinconf_ops;
|
struct pinconf_ops;
|
||||||
|
Loading…
Reference in New Issue
Block a user