mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 11:19:37 +00:00
![Linus Torvalds](/assets/img/avatar_default.png)
When pulling the recent pinctrl merge, I was surprised by how a pinctrl-only pull request ended up rebuilding basically the whole kernel. The reason for that ended up being that <linux/device.h> included <linux/pinctrl/devinfo.h>, so any change to that file ended up causing pretty much every driver out there to be rebuilt. The reason for that was because 'struct device' has this in it: #ifdef CONFIG_PINCTRL struct dev_pin_info *pins; #endif but we already avoid header includes for these kinds of things in that header file, preferring to just use a forward-declaration of the structure instead. Exactly to avoid this kind of header dependency. Since some drivers seem to expect that <linux/pinctrl/devinfo.h> header to come in automatically, move the include to <linux/pinctrl/pinctrl.h> instead. It might be better to just make the includes more targeted, but I'm not going to review every driver. It would definitely be good to have a tool for finding and minimizing header dependencies automatically - or at least help with them. Right now we almost certainly end up having way too many of these things, and it's hard to test every single configuration. FWIW, you can get a sense of the "hotness" of a header file with something like this after doing a full build: find . -name '.*.o.cmd' -print0 | xargs -0 tail --lines=+2 | grep -v 'wildcard ' | tr ' \\' '\n' | sort | uniq -c | sort -n | less -S which isn't exact (there are other things in those '*.o.cmd' than just the dependencies, and the "--lines=+2" only removes the header), but might a useful approximation. With this patch, <linux/pinctrl/devinfo.h> drops to "only" having 833 users in the current x86-64 allmodconfig. In contrast, <linux/device.h> has 14857 build files including it directly or indirectly. Of course, the headers that absolutely _everybody_ includes (things like <linux/types.h> etc) get a score of 23000+. Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
213 lines
7.5 KiB
C
213 lines
7.5 KiB
C
/*
|
|
* Interface 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_PINCTRL_H
|
|
#define __LINUX_PINCTRL_PINCTRL_H
|
|
|
|
#ifdef CONFIG_PINCTRL
|
|
|
|
#include <linux/radix-tree.h>
|
|
#include <linux/list.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/pinctrl/pinctrl-state.h>
|
|
#include <linux/pinctrl/devinfo.h>
|
|
|
|
struct device;
|
|
struct pinctrl_dev;
|
|
struct pinctrl_map;
|
|
struct pinmux_ops;
|
|
struct pinconf_ops;
|
|
struct pin_config_item;
|
|
struct gpio_chip;
|
|
struct device_node;
|
|
|
|
/**
|
|
* struct pinctrl_pin_desc - boards/machines provide information on their
|
|
* pins, pads or other muxable units in this struct
|
|
* @number: unique pin number from the global pin number space
|
|
* @name: a name for this pin
|
|
* @drv_data: driver-defined per-pin data. pinctrl core does not touch this
|
|
*/
|
|
struct pinctrl_pin_desc {
|
|
unsigned number;
|
|
const char *name;
|
|
void *drv_data;
|
|
};
|
|
|
|
/* Convenience macro to define a single named or anonymous pin descriptor */
|
|
#define PINCTRL_PIN(a, b) { .number = a, .name = b }
|
|
#define PINCTRL_PIN_ANON(a) { .number = a }
|
|
|
|
/**
|
|
* struct pinctrl_gpio_range - each pin controller can provide subranges of
|
|
* the GPIO number space to be handled by the controller
|
|
* @node: list node for internal use
|
|
* @name: a name for the chip in this range
|
|
* @id: an ID number for the chip in this range
|
|
* @base: base offset of the GPIO range
|
|
* @pin_base: base pin number of the GPIO range if pins == NULL
|
|
* @pins: enumeration of pins in GPIO range or NULL
|
|
* @npins: number of pins in the GPIO range, including the base number
|
|
* @gc: an optional pointer to a gpio_chip
|
|
*/
|
|
struct pinctrl_gpio_range {
|
|
struct list_head node;
|
|
const char *name;
|
|
unsigned int id;
|
|
unsigned int base;
|
|
unsigned int pin_base;
|
|
unsigned const *pins;
|
|
unsigned int npins;
|
|
struct gpio_chip *gc;
|
|
};
|
|
|
|
/**
|
|
* struct pinctrl_ops - global pin control operations, to be implemented by
|
|
* pin controller drivers.
|
|
* @get_groups_count: Returns the count of total number of groups registered.
|
|
* @get_group_name: return the group name of the pin group
|
|
* @get_group_pins: return an array of pins corresponding to a certain
|
|
* group selector @pins, and the size of the array in @num_pins
|
|
* @pin_dbg_show: optional debugfs display hook that will provide per-device
|
|
* info for a certain pin in debugfs
|
|
* @dt_node_to_map: parse a device tree "pin configuration node", and create
|
|
* mapping table entries for it. These are returned through the @map and
|
|
* @num_maps output parameters. This function is optional, and may be
|
|
* omitted for pinctrl drivers that do not support device tree.
|
|
* @dt_free_map: free mapping table entries created via @dt_node_to_map. The
|
|
* top-level @map pointer must be freed, along with any dynamically
|
|
* allocated members of the mapping table entries themselves. This
|
|
* function is optional, and may be omitted for pinctrl drivers that do
|
|
* not support device tree.
|
|
*/
|
|
struct pinctrl_ops {
|
|
int (*get_groups_count) (struct pinctrl_dev *pctldev);
|
|
const char *(*get_group_name) (struct pinctrl_dev *pctldev,
|
|
unsigned selector);
|
|
int (*get_group_pins) (struct pinctrl_dev *pctldev,
|
|
unsigned selector,
|
|
const unsigned **pins,
|
|
unsigned *num_pins);
|
|
void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s,
|
|
unsigned offset);
|
|
int (*dt_node_to_map) (struct pinctrl_dev *pctldev,
|
|
struct device_node *np_config,
|
|
struct pinctrl_map **map, unsigned *num_maps);
|
|
void (*dt_free_map) (struct pinctrl_dev *pctldev,
|
|
struct pinctrl_map *map, unsigned num_maps);
|
|
};
|
|
|
|
/**
|
|
* struct pinctrl_desc - pin controller descriptor, register this to pin
|
|
* control subsystem
|
|
* @name: name for the pin controller
|
|
* @pins: an array of pin descriptors describing all the pins handled by
|
|
* this pin controller
|
|
* @npins: number of descriptors in the array, usually just ARRAY_SIZE()
|
|
* of the pins field above
|
|
* @pctlops: pin control operation vtable, to support global concepts like
|
|
* grouping of pins, this is optional.
|
|
* @pmxops: pinmux operations vtable, if you support pinmuxing in your driver
|
|
* @confops: pin config operations vtable, if you support pin configuration in
|
|
* your driver
|
|
* @owner: module providing the pin controller, used for refcounting
|
|
* @num_custom_params: Number of driver-specific custom parameters to be parsed
|
|
* from the hardware description
|
|
* @custom_params: List of driver_specific custom parameters to be parsed from
|
|
* the hardware description
|
|
* @custom_conf_items: Information how to print @params in debugfs, must be
|
|
* the same size as the @custom_params, i.e. @num_custom_params
|
|
*/
|
|
struct pinctrl_desc {
|
|
const char *name;
|
|
const struct pinctrl_pin_desc *pins;
|
|
unsigned int npins;
|
|
const struct pinctrl_ops *pctlops;
|
|
const struct pinmux_ops *pmxops;
|
|
const struct pinconf_ops *confops;
|
|
struct module *owner;
|
|
#ifdef CONFIG_GENERIC_PINCONF
|
|
unsigned int num_custom_params;
|
|
const struct pinconf_generic_params *custom_params;
|
|
const struct pin_config_item *custom_conf_items;
|
|
#endif
|
|
};
|
|
|
|
/* External interface to pin controller */
|
|
|
|
extern int pinctrl_register_and_init(struct pinctrl_desc *pctldesc,
|
|
struct device *dev, void *driver_data,
|
|
struct pinctrl_dev **pctldev);
|
|
extern int pinctrl_enable(struct pinctrl_dev *pctldev);
|
|
|
|
/* Please use pinctrl_register_and_init() and pinctrl_enable() instead */
|
|
extern struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
|
struct device *dev, void *driver_data);
|
|
|
|
extern void pinctrl_unregister(struct pinctrl_dev *pctldev);
|
|
|
|
extern int devm_pinctrl_register_and_init(struct device *dev,
|
|
struct pinctrl_desc *pctldesc,
|
|
void *driver_data,
|
|
struct pinctrl_dev **pctldev);
|
|
|
|
/* Please use devm_pinctrl_register_and_init() instead */
|
|
extern struct pinctrl_dev *devm_pinctrl_register(struct device *dev,
|
|
struct pinctrl_desc *pctldesc,
|
|
void *driver_data);
|
|
|
|
extern void devm_pinctrl_unregister(struct device *dev,
|
|
struct pinctrl_dev *pctldev);
|
|
|
|
extern bool pin_is_valid(struct pinctrl_dev *pctldev, int pin);
|
|
extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
|
|
struct pinctrl_gpio_range *range);
|
|
extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
|
|
struct pinctrl_gpio_range *ranges,
|
|
unsigned nranges);
|
|
extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
|
|
struct pinctrl_gpio_range *range);
|
|
|
|
extern struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
|
|
struct pinctrl_gpio_range *range);
|
|
extern struct pinctrl_gpio_range *
|
|
pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
|
|
unsigned int pin);
|
|
extern int pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
|
|
const char *pin_group, const unsigned **pins,
|
|
unsigned *num_pins);
|
|
|
|
#ifdef CONFIG_OF
|
|
extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np);
|
|
#else
|
|
static inline
|
|
struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
|
|
{
|
|
return NULL;
|
|
}
|
|
#endif /* CONFIG_OF */
|
|
|
|
extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
|
|
extern const char *pinctrl_dev_get_devname(struct pinctrl_dev *pctldev);
|
|
extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
|
|
#else
|
|
|
|
struct pinctrl_dev;
|
|
|
|
/* Sufficiently stupid default functions when pinctrl is not in use */
|
|
static inline bool pin_is_valid(struct pinctrl_dev *pctldev, int pin)
|
|
{
|
|
return pin >= 0;
|
|
}
|
|
|
|
#endif /* !CONFIG_PINCTRL */
|
|
|
|
#endif /* __LINUX_PINCTRL_PINCTRL_H */
|