Merge tag 'pinctrl-for-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl

Pull pinctrl updates for v3.4 from Linus Walleij (*):
 - Switches the PXA 168, 910 and MMP over to use pinctrl
 - Locking revamped
 - Massive refactorings...
 - Reform the driver API to use multiple states
 - Support pin config in the mapping tables
 - Pinctrl drivers for the nVidia Tegra series
 - Generic pin config support lib for simple pin controllers
 - Implement pin config for the U300

* tag 'pinctrl-for-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (48 commits)
  ARM: u300: configure some pins as an example
  pinctrl: support pinconfig on the U300
  pinctrl/coh901: use generic pinconf enums and parameters
  pinctrl: introduce generic pin config
  pinctrl: fix error path in pinconf_map_to_setting()
  pinctrl: allow concurrent gpio and mux function ownership of pins
  pinctrl: forward-declare struct device
  pinctrl: split pincontrol states into its own header
  pinctrl: include machine header to core.h
  ARM: tegra: Select PINCTRL Kconfig variables
  pinctrl: add a driver for NVIDIA Tegra
  pinctrl: Show selected function and group in pinmux-pins debugfs
  pinctrl: enhance mapping table to support pin config operations
  pinctrl: API changes to support multiple states per device
  pinctrl: add usecount to pins for muxing
  pinctrl: refactor struct pinctrl handling in core.c vs pinmux.c
  pinctrl: fix and simplify locking
  pinctrl: fix the pin descriptor kerneldoc
  pinctrl: assume map table entries can't have a NULL name field
  pinctrl: introduce PINCTRL_STATE_DEFAULT, define hogs as that state
  ...

(*) What is it with all these Linuses these days? There's a Linus at
    google too.  Some day I will get myself my own broadsword, and run
    around screaming "There can be only one".

    I used to be _special_ dammit. Snif.
This commit is contained in:
Linus Torvalds
2012-03-22 20:25:50 -07:00
35 changed files with 12981 additions and 1623 deletions

View File

@@ -0,0 +1,159 @@
/*
* Consumer interface the pin control subsystem
*
* Copyright (C) 2012 ST-Ericsson SA
* Written on behalf of Linaro for ST-Ericsson
* Based on bits of regulator core, gpio core and clk core
*
* Author: Linus Walleij <linus.walleij@linaro.org>
*
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef __LINUX_PINCTRL_CONSUMER_H
#define __LINUX_PINCTRL_CONSUMER_H
#include <linux/err.h>
#include <linux/list.h>
#include <linux/seq_file.h>
#include "pinctrl-state.h"
/* This struct is private to the core and should be regarded as a cookie */
struct pinctrl;
struct pinctrl_state;
#ifdef CONFIG_PINCTRL
/* External interface to pin control */
extern int pinctrl_request_gpio(unsigned gpio);
extern void pinctrl_free_gpio(unsigned gpio);
extern int pinctrl_gpio_direction_input(unsigned gpio);
extern int pinctrl_gpio_direction_output(unsigned gpio);
extern struct pinctrl * __must_check pinctrl_get(struct device *dev);
extern void pinctrl_put(struct pinctrl *p);
extern struct pinctrl_state * __must_check pinctrl_lookup_state(
struct pinctrl *p,
const char *name);
extern int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s);
#else /* !CONFIG_PINCTRL */
static inline int pinctrl_request_gpio(unsigned gpio)
{
return 0;
}
static inline void pinctrl_free_gpio(unsigned gpio)
{
}
static inline int pinctrl_gpio_direction_input(unsigned gpio)
{
return 0;
}
static inline int pinctrl_gpio_direction_output(unsigned gpio)
{
return 0;
}
static inline struct pinctrl * __must_check pinctrl_get(struct device *dev)
{
return NULL;
}
static inline void pinctrl_put(struct pinctrl *p)
{
}
static inline struct pinctrl_state * __must_check pinctrl_lookup_state(
struct pinctrl *p,
const char *name)
{
return NULL;
}
static inline int pinctrl_select_state(struct pinctrl *p,
struct pinctrl_state *s)
{
return 0;
}
#endif /* CONFIG_PINCTRL */
static inline struct pinctrl * __must_check pinctrl_get_select(
struct device *dev, const char *name)
{
struct pinctrl *p;
struct pinctrl_state *s;
int ret;
p = pinctrl_get(dev);
if (IS_ERR(p))
return p;
s = pinctrl_lookup_state(p, name);
if (IS_ERR(s)) {
pinctrl_put(p);
return ERR_PTR(PTR_ERR(s));
}
ret = pinctrl_select_state(p, s);
if (ret < 0) {
pinctrl_put(p);
return ERR_PTR(ret);
}
return p;
}
static inline struct pinctrl * __must_check pinctrl_get_select_default(
struct device *dev)
{
return pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT);
}
#ifdef CONFIG_PINCONF
extern int pin_config_get(const char *dev_name, const char *name,
unsigned long *config);
extern int pin_config_set(const char *dev_name, const char *name,
unsigned long config);
extern int pin_config_group_get(const char *dev_name,
const char *pin_group,
unsigned long *config);
extern int pin_config_group_set(const char *dev_name,
const char *pin_group,
unsigned long config);
#else
static inline int pin_config_get(const char *dev_name, const char *name,
unsigned long *config)
{
return 0;
}
static inline int pin_config_set(const char *dev_name, const char *name,
unsigned long config)
{
return 0;
}
static inline int pin_config_group_get(const char *dev_name,
const char *pin_group,
unsigned long *config)
{
return 0;
}
static inline int pin_config_group_set(const char *dev_name,
const char *pin_group,
unsigned long config)
{
return 0;
}
#endif
#endif /* __LINUX_PINCTRL_CONSUMER_H */

View File

@@ -9,87 +9,153 @@
*
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef __LINUX_PINMUX_MACHINE_H
#define __LINUX_PINMUX_MACHINE_H
#ifndef __LINUX_PINCTRL_MACHINE_H
#define __LINUX_PINCTRL_MACHINE_H
/**
* struct pinmux_map - boards/machines shall provide this map for devices
* @name: the name of this specific map entry for the particular machine.
* This is the second parameter passed to pinmux_get() when you want
* to have several mappings to the same device
* @ctrl_dev: the pin control device to be used by this mapping, may be NULL
* if you provide .ctrl_dev_name instead (this is more common)
* @ctrl_dev_name: the name of the device controlling this specific mapping,
* the name must be the same as in your struct device*, may be NULL if
* you provide .ctrl_dev instead
* @function: a function in the driver to use for this mapping, the driver
* will lookup the function referenced by this ID on the specified
* pin control device
* @group: sometimes a function can map to different pin groups, so this
* selects a certain specific pin group to activate for the function, if
* left as NULL, the first applicable group will be used
* @dev: the device using this specific mapping, may be NULL if you provide
* .dev_name instead (this is more common)
* @dev_name: the name of the device using this specific mapping, the name
* must be the same as in your struct device*, may be NULL if you
* provide .dev instead
* @hog_on_boot: if this is set to true, the pin control subsystem will itself
* hog the mappings as the pinmux device drivers are attached, so this is
* typically used with system maps (mux mappings without an assigned
* device) that you want to get hogged and enabled by default as soon as
* a pinmux device supporting it is registered. These maps will not be
* disabled and put until the system shuts down.
*/
struct pinmux_map {
const char *name;
struct device *ctrl_dev;
const char *ctrl_dev_name;
const char *function;
const char *group;
struct device *dev;
const char *dev_name;
bool hog_on_boot;
#include "pinctrl-state.h"
enum pinctrl_map_type {
PIN_MAP_TYPE_INVALID,
PIN_MAP_TYPE_DUMMY_STATE,
PIN_MAP_TYPE_MUX_GROUP,
PIN_MAP_TYPE_CONFIGS_PIN,
PIN_MAP_TYPE_CONFIGS_GROUP,
};
/*
* Convenience macro to set a simple map from a certain pin controller and a
* certain function to a named device
/**
* struct pinctrl_map_mux - mapping table content for MAP_TYPE_MUX_GROUP
* @group: the name of the group whose mux function is to be configured. This
* field may be left NULL, and the first applicable group for the function
* will be used.
* @function: the mux function to select for the group
*/
#define PINMUX_MAP(a, b, c, d) \
{ .name = a, .ctrl_dev_name = b, .function = c, .dev_name = d }
struct pinctrl_map_mux {
const char *group;
const char *function;
};
/*
* Convenience macro to map a system function onto a certain pinctrl device.
* System functions are not assigned to a particular device.
/**
* struct pinctrl_map_configs - mapping table content for MAP_TYPE_CONFIGS_*
* @group_or_pin: the name of the pin or group whose configuration parameters
* are to be configured.
* @configs: a pointer to an array of config parameters/values to program into
* hardware. Each individual pin controller defines the format and meaning
* of config parameters.
* @num_configs: the number of entries in array @configs
*/
#define PINMUX_MAP_SYS(a, b, c) \
{ .name = a, .ctrl_dev_name = b, .function = c }
struct pinctrl_map_configs {
const char *group_or_pin;
unsigned long *configs;
unsigned num_configs;
};
/*
* Convenience macro to map a system function onto a certain pinctrl device,
* to be hogged by the pinmux core until the system shuts down.
/**
* struct pinctrl_map - boards/machines shall provide this map for devices
* @dev_name: the name of the device using this specific mapping, the name
* must be the same as in your struct device*. If this name is set to the
* same name as the pin controllers own dev_name(), the map entry will be
* hogged by the driver itself upon registration
* @name: the name of this specific map entry for the particular machine.
* This is the parameter passed to pinmux_lookup_state()
* @type: the type of mapping table entry
* @ctrl_dev_name: the name of the device controlling this specific mapping,
* the name must be the same as in your struct device*. This field is not
* used for PIN_MAP_TYPE_DUMMY_STATE
* @data: Data specific to the mapping type
*/
#define PINMUX_MAP_SYS_HOG(a, b, c) \
{ .name = a, .ctrl_dev_name = b, .function = c, \
.hog_on_boot = true }
struct pinctrl_map {
const char *dev_name;
const char *name;
enum pinctrl_map_type type;
const char *ctrl_dev_name;
union {
struct pinctrl_map_mux mux;
struct pinctrl_map_configs configs;
} data;
};
/*
* Convenience macro to map a system function onto a certain pinctrl device
* using a specified group, to be hogged by the pinmux core until the system
* shuts down.
*/
#define PINMUX_MAP_SYS_HOG_GROUP(a, b, c, d) \
{ .name = a, .ctrl_dev_name = b, .function = c, .group = d, \
.hog_on_boot = true }
/* Convenience macros to create mapping table entries */
#define PIN_MAP_DUMMY_STATE(dev, state) \
{ \
.dev_name = dev, \
.name = state, \
.type = PIN_MAP_TYPE_DUMMY_STATE, \
}
#define PIN_MAP_MUX_GROUP(dev, state, pinctrl, grp, func) \
{ \
.dev_name = dev, \
.name = state, \
.type = PIN_MAP_TYPE_MUX_GROUP, \
.ctrl_dev_name = pinctrl, \
.data.mux = { \
.group = grp, \
.function = func, \
}, \
}
#define PIN_MAP_MUX_GROUP_DEFAULT(dev, pinctrl, grp, func) \
PIN_MAP_MUX_GROUP(dev, PINCTRL_STATE_DEFAULT, pinctrl, grp, func)
#define PIN_MAP_MUX_GROUP_HOG(dev, state, grp, func) \
PIN_MAP_MUX_GROUP(dev, state, dev, grp, func)
#define PIN_MAP_MUX_GROUP_HOG_DEFAULT(dev, grp, func) \
PIN_MAP_MUX_GROUP(dev, PINCTRL_STATE_DEFAULT, dev, grp, func)
#define PIN_MAP_CONFIGS_PIN(dev, state, pinctrl, pin, cfgs) \
{ \
.dev_name = dev, \
.name = state, \
.type = PIN_MAP_TYPE_CONFIGS_PIN, \
.ctrl_dev_name = pinctrl, \
.data.configs = { \
.group_or_pin = pin, \
.configs = cfgs, \
.num_configs = ARRAY_SIZE(cfgs), \
}, \
}
#define PIN_MAP_CONFIGS_PIN_DEFAULT(dev, pinctrl, pin, cfgs) \
PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_DEFAULT, pinctrl, pin, cfgs)
#define PIN_MAP_CONFIGS_PIN_HOG(dev, state, pin, cfgs) \
PIN_MAP_CONFIGS_PIN(dev, state, dev, pin, cfgs)
#define PIN_MAP_CONFIGS_PIN_HOG_DEFAULT(dev, pin, cfgs) \
PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_DEFAULT, dev, pin, cfgs)
#define PIN_MAP_CONFIGS_GROUP(dev, state, pinctrl, grp, cfgs) \
{ \
.dev_name = dev, \
.name = state, \
.type = PIN_MAP_TYPE_CONFIGS_GROUP, \
.ctrl_dev_name = pinctrl, \
.data.configs = { \
.group_or_pin = grp, \
.configs = cfgs, \
.num_configs = ARRAY_SIZE(cfgs), \
}, \
}
#define PIN_MAP_CONFIGS_GROUP_DEFAULT(dev, pinctrl, grp, cfgs) \
PIN_MAP_CONFIGS_GROUP(dev, PINCTRL_STATE_DEFAULT, pinctrl, grp, cfgs)
#define PIN_MAP_CONFIGS_GROUP_HOG(dev, state, grp, cfgs) \
PIN_MAP_CONFIGS_GROUP(dev, state, dev, grp, cfgs)
#define PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(dev, grp, cfgs) \
PIN_MAP_CONFIGS_GROUP(dev, PINCTRL_STATE_DEFAULT, dev, grp, cfgs)
#ifdef CONFIG_PINMUX
extern int pinmux_register_mappings(struct pinmux_map const *map,
extern int pinctrl_register_mappings(struct pinctrl_map const *map,
unsigned num_maps);
#else
static inline int pinmux_register_mappings(struct pinmux_map const *map,
static inline int pinctrl_register_mappings(struct pinctrl_map const *map,
unsigned num_maps)
{
return 0;

View File

@@ -0,0 +1,114 @@
/*
* Interface the generic pinconfig portions of the pinctrl subsystem
*
* Copyright (C) 2011 ST-Ericsson SA
* Written on behalf of Linaro for ST-Ericsson
* This interface is used in the core to keep track of pins.
*
* Author: Linus Walleij <linus.walleij@linaro.org>
*
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef __LINUX_PINCTRL_PINCONF_GENERIC_H
#define __LINUX_PINCTRL_PINCONF_GENERIC_H
/*
* You shouldn't even be able to compile with these enums etc unless you're
* using generic pin config. That is why this is defined out.
*/
#ifdef CONFIG_GENERIC_PINCONF
/**
* enum pin_config_param - possible pin configuration parameters
* @PIN_CONFIG_BIAS_DISABLE: disable any pin bias on the pin, a
* transition from say pull-up to pull-down implies that you disable
* pull-up in the process, this setting disables all biasing.
* @PIN_CONFIG_BIAS_HIGH_IMPEDANCE: the pin will be set to a high impedance
* mode, also know as "third-state" (tristate) or "high-Z" or "floating".
* On output pins this effectively disconnects the pin, which is useful
* if for example some other pin is going to drive the signal connected
* to it for a while. Pins used for input are usually always high
* impedance.
* @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high
* impedance to VDD). If the argument is != 0 pull-up is enabled,
* if it is 0, pull-up is disabled.
* @PIN_CONFIG_BIAS_PULL_DOWN: the pin will be pulled down (usually with high
* impedance to GROUND). If the argument is != 0 pull-down is enabled,
* if it is 0, pull-down is disabled.
* @PIN_CONFIG_DRIVE_PUSH_PULL: the pin will be driven actively high and
* low, this is the most typical case and is typically achieved with two
* active transistors on the output. Sending this config will enabale
* push-pull mode, the argument is ignored.
* @PIN_CONFIG_DRIVE_OPEN_DRAIN: the pin will be driven with open drain (open
* collector) which means it is usually wired with other output ports
* which are then pulled up with an external resistor. Sending this
* config will enabale open drain mode, the argument is ignored.
* @PIN_CONFIG_DRIVE_OPEN_SOURCE: the pin will be driven with open source
* (open emitter). Sending this config will enabale open drain mode, the
* argument is ignored.
* @PIN_CONFIG_INPUT_SCHMITT: this will configure an input pin to run in
* schmitt-trigger mode. If the schmitt-trigger has adjustable hysteresis,
* the threshold value is given on a custom format as argument when
* setting pins to this mode. The argument zero turns the schmitt trigger
* off.
* @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode,
* which means it will wait for signals to settle when reading inputs. The
* argument gives the debounce time on a custom format. Setting the
* argument to zero turns debouncing off.
* @PIN_CONFIG_POWER_SOURCE: if the pin can select between different power
* supplies, the argument to this parameter (on a custom format) tells
* the driver which alternative power source to use.
* @PIN_CONFIG_LOW_POWER_MODE: this will configure the pin for low power
* operation, if several modes of operation are supported these can be
* passed in the argument on a custom form, else just use argument 1
* to indicate low power mode, argument 0 turns low power mode off.
* @PIN_CONFIG_END: this is the last enumerator for pin configurations, if
* you need to pass in custom configurations to the pin controller, use
* PIN_CONFIG_END+1 as the base offset.
*/
enum pin_config_param {
PIN_CONFIG_BIAS_DISABLE,
PIN_CONFIG_BIAS_HIGH_IMPEDANCE,
PIN_CONFIG_BIAS_PULL_UP,
PIN_CONFIG_BIAS_PULL_DOWN,
PIN_CONFIG_DRIVE_PUSH_PULL,
PIN_CONFIG_DRIVE_OPEN_DRAIN,
PIN_CONFIG_DRIVE_OPEN_SOURCE,
PIN_CONFIG_INPUT_SCHMITT,
PIN_CONFIG_INPUT_DEBOUNCE,
PIN_CONFIG_POWER_SOURCE,
PIN_CONFIG_LOW_POWER_MODE,
PIN_CONFIG_END = 0x7FFF,
};
/*
* Helpful configuration macro to be used in tables etc.
*/
#define PIN_CONF_PACKED(p, a) ((a << 16) | ((unsigned long) p & 0xffffUL))
/*
* The following inlines stuffs a configuration parameter and data value
* into and out of an unsigned long argument, as used by the generic pin config
* system. We put the parameter in the lower 16 bits and the argument in the
* upper 16 bits.
*/
static inline enum pin_config_param pinconf_to_config_param(unsigned long config)
{
return (enum pin_config_param) (config & 0xffffUL);
}
static inline u16 pinconf_to_config_argument(unsigned long config)
{
return (enum pin_config_param) ((config >> 16) & 0xffffUL);
}
static inline unsigned long pinconf_to_config_packed(enum pin_config_param param,
u16 argument)
{
return PIN_CONF_PACKED(param, argument);
}
#endif /* CONFIG_GENERIC_PINCONF */
#endif /* __LINUX_PINCTRL_PINCONF_GENERIC_H */

View File

@@ -20,6 +20,8 @@ struct seq_file;
/**
* struct pinconf_ops - pin config operations, to be implemented by
* pin configuration capable drivers.
* @is_generic: for pin controllers that want to use the generic interface,
* this flag tells the framework that it's generic.
* @pin_config_get: get the config of a certain pin, if the requested config
* is not available on this controller this should return -ENOTSUPP
* and if it is available but disabled it should return -EINVAL
@@ -33,6 +35,9 @@ struct seq_file;
* per-device info for a certain group in debugfs
*/
struct pinconf_ops {
#ifdef CONFIG_GENERIC_PINCONF
bool is_generic;
#endif
int (*pin_config_get) (struct pinctrl_dev *pctldev,
unsigned pin,
unsigned long *config);
@@ -53,45 +58,6 @@ struct pinconf_ops {
unsigned selector);
};
extern int pin_config_get(const char *dev_name, const char *name,
unsigned long *config);
extern int pin_config_set(const char *dev_name, const char *name,
unsigned long config);
extern int pin_config_group_get(const char *dev_name,
const char *pin_group,
unsigned long *config);
extern int pin_config_group_set(const char *dev_name,
const char *pin_group,
unsigned long config);
#else
static inline int pin_config_get(const char *dev_name, const char *name,
unsigned long *config)
{
return 0;
}
static inline int pin_config_set(const char *dev_name, const char *name,
unsigned long config)
{
return 0;
}
static inline int pin_config_group_get(const char *dev_name,
const char *pin_group,
unsigned long *config)
{
return 0;
}
static inline int pin_config_group_set(const char *dev_name,
const char *pin_group,
unsigned long config)
{
return 0;
}
#endif
#endif /* __LINUX_PINCTRL_PINCONF_H */

View File

@@ -0,0 +1,6 @@
/*
* Standard pin control state definitions
*/
#define PINCTRL_STATE_DEFAULT "default"
#define PINCTRL_STATE_IDLE "idle"

View File

@@ -15,10 +15,11 @@
#ifdef CONFIG_PINCTRL
#include <linux/radix-tree.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/seq_file.h>
#include "pinctrl-state.h"
struct device;
struct pinctrl_dev;
struct pinmux_ops;
struct pinconf_ops;

View File

@@ -16,9 +16,6 @@
#include <linux/seq_file.h>
#include "pinctrl.h"
/* This struct is private to the core and should be regarded as a cookie */
struct pinmux;
#ifdef CONFIG_PINMUX
struct pinctrl_dev;
@@ -88,55 +85,6 @@ struct pinmux_ops {
bool input);
};
/* External interface to pinmux */
extern int pinmux_request_gpio(unsigned gpio);
extern void pinmux_free_gpio(unsigned gpio);
extern int pinmux_gpio_direction_input(unsigned gpio);
extern int pinmux_gpio_direction_output(unsigned gpio);
extern struct pinmux * __must_check pinmux_get(struct device *dev, const char *name);
extern void pinmux_put(struct pinmux *pmx);
extern int pinmux_enable(struct pinmux *pmx);
extern void pinmux_disable(struct pinmux *pmx);
#else /* !CONFIG_PINMUX */
static inline int pinmux_request_gpio(unsigned gpio)
{
return 0;
}
static inline void pinmux_free_gpio(unsigned gpio)
{
}
static inline int pinmux_gpio_direction_input(unsigned gpio)
{
return 0;
}
static inline int pinmux_gpio_direction_output(unsigned gpio)
{
return 0;
}
static inline struct pinmux * __must_check pinmux_get(struct device *dev, const char *name)
{
return NULL;
}
static inline void pinmux_put(struct pinmux *pmx)
{
}
static inline int pinmux_enable(struct pinmux *pmx)
{
return 0;
}
static inline void pinmux_disable(struct pinmux *pmx)
{
}
#endif /* CONFIG_PINMUX */
#endif /* __LINUX_PINCTRL_PINMUX_H */