599 lines · 15.4 KB · C
RawDownload
/* * Core driver for the pin control subsystem * * Copyright (C) 2011 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 */#define pr_fmt(fmt) "pinctrl core: " fmt #include <linux/kernel.h>#include <linux/export.h>#include <linux/init.h>#include <linux/device.h>#include <linux/slab.h>#include <linux/radix-tree.h>#include <linux/err.h>#include <linux/list.h>#include <linux/mutex.h>#include <linux/spinlock.h>#include <linux/sysfs.h>#include <linux/debugfs.h>#include <linux/seq_file.h>#include <linux/pinctrl/pinctrl.h>#include <linux/pinctrl/machine.h>#include "core.h"#include "pinmux.h" /* Global list of pin control devices */static DEFINE_MUTEX(pinctrldev_list_mutex);static LIST_HEAD(pinctrldev_list); static void pinctrl_dev_release(struct device *dev){	struct pinctrl_dev *pctldev = dev_get_drvdata(dev);	kfree(pctldev);} const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev){	/* We're not allowed to register devices without name */	return pctldev->desc->name;}EXPORT_SYMBOL_GPL(pinctrl_dev_get_name); void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev){	return pctldev->driver_data;}EXPORT_SYMBOL_GPL(pinctrl_dev_get_drvdata); /** * get_pinctrl_dev_from_dev() - look up pin controller device * @dev: a device pointer, this may be NULL but then devname needs to be *	defined instead * @devname: the name of a device instance, as returned by dev_name(), this *	may be NULL but then dev needs to be defined instead * * Looks up a pin control device matching a certain device name or pure device * pointer, the pure device pointer will take precedence. */struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev,					     const char *devname){	struct pinctrl_dev *pctldev = NULL;	bool found = false; 	mutex_lock(&pinctrldev_list_mutex);	list_for_each_entry(pctldev, &pinctrldev_list, node) {		if (dev &&  &pctldev->dev == dev) {			/* Matched on device pointer */			found = true;			break;		} 		if (devname &&		    !strcmp(dev_name(&pctldev->dev), devname)) {			/* Matched on device name */			found = true;			break;		}	}	mutex_unlock(&pinctrldev_list_mutex); 	return found ? pctldev : NULL;} struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin){	struct pin_desc *pindesc;	unsigned long flags; 	spin_lock_irqsave(&pctldev->pin_desc_tree_lock, flags);	pindesc = radix_tree_lookup(&pctldev->pin_desc_tree, pin);	spin_unlock_irqrestore(&pctldev->pin_desc_tree_lock, flags); 	return pindesc;} /** * pin_is_valid() - check if pin exists on controller * @pctldev: the pin control device to check the pin on * @pin: pin to check, use the local pin controller index number * * This tells us whether a certain pin exist on a certain pin controller or * not. Pin lists may be sparse, so some pins may not exist. */bool pin_is_valid(struct pinctrl_dev *pctldev, int pin){	struct pin_desc *pindesc; 	if (pin < 0)		return false; 	pindesc = pin_desc_get(pctldev, pin);	if (pindesc == NULL)		return false; 	return true;}EXPORT_SYMBOL_GPL(pin_is_valid); /* Deletes a range of pin descriptors */static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev,				  const struct pinctrl_pin_desc *pins,				  unsigned num_pins){	int i; 	spin_lock(&pctldev->pin_desc_tree_lock);	for (i = 0; i < num_pins; i++) {		struct pin_desc *pindesc; 		pindesc = radix_tree_lookup(&pctldev->pin_desc_tree,					    pins[i].number);		if (pindesc != NULL) {			radix_tree_delete(&pctldev->pin_desc_tree,					  pins[i].number);		}		kfree(pindesc);	}	spin_unlock(&pctldev->pin_desc_tree_lock);} static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,				    unsigned number, const char *name){	struct pin_desc *pindesc; 	pindesc = pin_desc_get(pctldev, number);	if (pindesc != NULL) {		pr_err("pin %d already registered on %s\n", number,		       pctldev->desc->name);		return -EINVAL;	} 	pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL);	if (pindesc == NULL)		return -ENOMEM;	spin_lock_init(&pindesc->lock); 	/* Set owner */	pindesc->pctldev = pctldev; 	/* Copy basic pin info */	pindesc->name = name; 	spin_lock(&pctldev->pin_desc_tree_lock);	radix_tree_insert(&pctldev->pin_desc_tree, number, pindesc);	spin_unlock(&pctldev->pin_desc_tree_lock);	pr_debug("registered pin %d (%s) on %s\n",		 number, name ? name : "(unnamed)", pctldev->desc->name);	return 0;} static int pinctrl_register_pins(struct pinctrl_dev *pctldev,				 struct pinctrl_pin_desc const *pins,				 unsigned num_descs){	unsigned i;	int ret = 0; 	for (i = 0; i < num_descs; i++) {		ret = pinctrl_register_one_pin(pctldev,					       pins[i].number, pins[i].name);		if (ret)			return ret;	} 	return 0;} /** * pinctrl_match_gpio_range() - check if a certain GPIO pin is in range * @pctldev: pin controller device to check * @gpio: gpio pin to check taken from the global GPIO pin space * * Tries to match a GPIO pin number to the ranges handled by a certain pin * controller, return the range or NULL */static struct pinctrl_gpio_range *pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio){	struct pinctrl_gpio_range *range = NULL; 	/* Loop over the ranges */	mutex_lock(&pctldev->gpio_ranges_lock);	list_for_each_entry(range, &pctldev->gpio_ranges, node) {		/* Check if we're in the valid range */		if (gpio >= range->base &&		    gpio < range->base + range->npins) {			mutex_unlock(&pctldev->gpio_ranges_lock);			return range;		}	}	mutex_unlock(&pctldev->gpio_ranges_lock); 	return NULL;} /** * pinctrl_get_device_gpio_range() - find device for GPIO range * @gpio: the pin to locate the pin controller for * @outdev: the pin control device if found * @outrange: the GPIO range if found * * Find the pin controller handling a certain GPIO pin from the pinspace of * the GPIO subsystem, return the device and the matching GPIO range. Returns * negative if the GPIO range could not be found in any device. */int pinctrl_get_device_gpio_range(unsigned gpio,				struct pinctrl_dev **outdev,				struct pinctrl_gpio_range **outrange){	struct pinctrl_dev *pctldev = NULL; 	/* Loop over the pin controllers */	mutex_lock(&pinctrldev_list_mutex);	list_for_each_entry(pctldev, &pinctrldev_list, node) {		struct pinctrl_gpio_range *range; 		range = pinctrl_match_gpio_range(pctldev, gpio);		if (range != NULL) {			*outdev = pctldev;			*outrange = range;			mutex_unlock(&pinctrldev_list_mutex);			return 0;		}	}	mutex_unlock(&pinctrldev_list_mutex); 	return -EINVAL;} /** * pinctrl_add_gpio_range() - register a GPIO range for a controller * @pctldev: pin controller device to add the range to * @range: the GPIO range to add * * This adds a range of GPIOs to be handled by a certain pin controller. Call * this to register handled ranges after registering your pin controller. */void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,			    struct pinctrl_gpio_range *range){	mutex_lock(&pctldev->gpio_ranges_lock);	list_add(&range->node, &pctldev->gpio_ranges);	mutex_unlock(&pctldev->gpio_ranges_lock);} /** * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller * @pctldev: pin controller device to remove the range from * @range: the GPIO range to remove */void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,			       struct pinctrl_gpio_range *range){	mutex_lock(&pctldev->gpio_ranges_lock);	list_del(&range->node);	mutex_unlock(&pctldev->gpio_ranges_lock);} #ifdef CONFIG_DEBUG_FS static int pinctrl_pins_show(struct seq_file *s, void *what){	struct pinctrl_dev *pctldev = s->private;	const struct pinctrl_ops *ops = pctldev->desc->pctlops;	unsigned pin; 	seq_printf(s, "registered pins: %d\n", pctldev->desc->npins);	seq_printf(s, "max pin number: %d\n", pctldev->desc->maxpin); 	/* The highest pin number need to be included in the loop, thus <= */	for (pin = 0; pin <= pctldev->desc->maxpin; pin++) {		struct pin_desc *desc; 		desc = pin_desc_get(pctldev, pin);		/* Pin space may be sparse */		if (desc == NULL)			continue; 		seq_printf(s, "pin %d (%s) ", pin,			   desc->name ? desc->name : "unnamed"); 		/* Driver-specific info per pin */		if (ops->pin_dbg_show)			ops->pin_dbg_show(pctldev, s, pin); 		seq_puts(s, "\n");	} 	return 0;} static int pinctrl_groups_show(struct seq_file *s, void *what){	struct pinctrl_dev *pctldev = s->private;	const struct pinctrl_ops *ops = pctldev->desc->pctlops;	unsigned selector = 0; 	/* No grouping */	if (!ops)		return 0; 	seq_puts(s, "registered pin groups:\n");	while (ops->list_groups(pctldev, selector) >= 0) {		const unsigned *pins;		unsigned num_pins;		const char *gname = ops->get_group_name(pctldev, selector);		int ret;		int i; 		ret = ops->get_group_pins(pctldev, selector,					  &pins, &num_pins);		if (ret)			seq_printf(s, "%s [ERROR GETTING PINS]\n",				   gname);		else {			seq_printf(s, "group: %s, pins = [ ", gname);			for (i = 0; i < num_pins; i++)				seq_printf(s, "%d ", pins[i]);			seq_puts(s, "]\n");		}		selector++;	}  	return 0;} static int pinctrl_gpioranges_show(struct seq_file *s, void *what){	struct pinctrl_dev *pctldev = s->private;	struct pinctrl_gpio_range *range = NULL; 	seq_puts(s, "GPIO ranges handled:\n"); 	/* Loop over the ranges */	mutex_lock(&pctldev->gpio_ranges_lock);	list_for_each_entry(range, &pctldev->gpio_ranges, node) {		seq_printf(s, "%u: %s [%u - %u]\n", range->id, range->name,			   range->base, (range->base + range->npins - 1));	}	mutex_unlock(&pctldev->gpio_ranges_lock); 	return 0;} static int pinctrl_devices_show(struct seq_file *s, void *what){	struct pinctrl_dev *pctldev; 	seq_puts(s, "name [pinmux]\n");	mutex_lock(&pinctrldev_list_mutex);	list_for_each_entry(pctldev, &pinctrldev_list, node) {		seq_printf(s, "%s ", pctldev->desc->name);		if (pctldev->desc->pmxops)			seq_puts(s, "yes");		else			seq_puts(s, "no");		seq_puts(s, "\n");	}	mutex_unlock(&pinctrldev_list_mutex); 	return 0;} static int pinctrl_pins_open(struct inode *inode, struct file *file){	return single_open(file, pinctrl_pins_show, inode->i_private);} static int pinctrl_groups_open(struct inode *inode, struct file *file){	return single_open(file, pinctrl_groups_show, inode->i_private);} static int pinctrl_gpioranges_open(struct inode *inode, struct file *file){	return single_open(file, pinctrl_gpioranges_show, inode->i_private);} static int pinctrl_devices_open(struct inode *inode, struct file *file){	return single_open(file, pinctrl_devices_show, NULL);} static const struct file_operations pinctrl_pins_ops = {	.open		= pinctrl_pins_open,	.read		= seq_read,	.llseek		= seq_lseek,	.release	= single_release,}; static const struct file_operations pinctrl_groups_ops = {	.open		= pinctrl_groups_open,	.read		= seq_read,	.llseek		= seq_lseek,	.release	= single_release,}; static const struct file_operations pinctrl_gpioranges_ops = {	.open		= pinctrl_gpioranges_open,	.read		= seq_read,	.llseek		= seq_lseek,	.release	= single_release,}; static const struct file_operations pinctrl_devices_ops = {	.open		= pinctrl_devices_open,	.read		= seq_read,	.llseek		= seq_lseek,	.release	= single_release,}; static struct dentry *debugfs_root; static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev){	static struct dentry *device_root; 	device_root = debugfs_create_dir(dev_name(&pctldev->dev),					 debugfs_root);	if (IS_ERR(device_root) || !device_root) {		pr_warn("failed to create debugfs directory for %s\n",			dev_name(&pctldev->dev));		return;	}	debugfs_create_file("pins", S_IFREG | S_IRUGO,			    device_root, pctldev, &pinctrl_pins_ops);	debugfs_create_file("pingroups", S_IFREG | S_IRUGO,			    device_root, pctldev, &pinctrl_groups_ops);	debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO,			    device_root, pctldev, &pinctrl_gpioranges_ops);	pinmux_init_device_debugfs(device_root, pctldev);} static void pinctrl_init_debugfs(void){	debugfs_root = debugfs_create_dir("pinctrl", NULL);	if (IS_ERR(debugfs_root) || !debugfs_root) {		pr_warn("failed to create debugfs directory\n");		debugfs_root = NULL;		return;	} 	debugfs_create_file("pinctrl-devices", S_IFREG | S_IRUGO,			    debugfs_root, NULL, &pinctrl_devices_ops);	pinmux_init_debugfs(debugfs_root);} #else /* CONFIG_DEBUG_FS */ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev){} static void pinctrl_init_debugfs(void){} #endif /** * pinctrl_register() - register a pin controller device * @pctldesc: descriptor for this pin controller * @dev: parent device for this pin controller * @driver_data: private pin controller data for this pin controller */struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,				    struct device *dev, void *driver_data){	static atomic_t pinmux_no = ATOMIC_INIT(0);	struct pinctrl_dev *pctldev;	int ret;

Lines 1–500 of 599.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t