/*
* Core driver for the pin muxing portions of 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) "pinmux core: " fmt
#include <linux/kernel.h>
#include <linux/module.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/string.h>
#include <linux/sysfs.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinmux.h>
#include "core.h"
/* List of pinmuxes */
static DEFINE_MUTEX(pinmux_list_mutex);
static LIST_HEAD(pinmux_list);
/* Global pinmux maps */
static struct pinmux_map *pinmux_maps;
static unsigned pinmux_maps_num;
/**
* struct pinmux_group - group list item for pinmux groups
* @node: pinmux group list node
* @group_selector: the group selector for this group
*/
struct pinmux_group {
struct list_head node;
unsigned group_selector;
};
/**
* struct pinmux - per-device pinmux state holder
* @node: global list node
* @dev: the device using this pinmux
* @usecount: the number of active users of this mux setting, used to keep
* track of nested use cases
* @pctldev: pin control device handling this pinmux
* @func_selector: the function selector for the pinmux device handling
* this pinmux
* @groups: the group selectors for the pinmux device and
* selector combination handling this pinmux, this is a list that
* will be traversed on all pinmux operations such as
* get/put/enable/disable
* @mutex: a lock for the pinmux state holder
*/
struct pinmux {
struct list_head node;
struct device *dev;
unsigned usecount;
struct pinctrl_dev *pctldev;
unsigned func_selector;
struct list_head groups;
struct mutex mutex;
};
/**
* struct pinmux_hog - a list item to stash mux hogs
* @node: pinmux hog list node
* @map: map entry responsible for this hogging
* @pmx: the pinmux hogged by this item
*/
struct pinmux_hog {
struct list_head node;
struct pinmux_map const *map;
struct pinmux *pmx;
};
/**
* pin_request() - request a single pin to be muxed in, typically for GPIO
* @pin: the pin number in the global pin space
* @function: a functional name to give to this pin, passed to the driver
* so it knows what function to mux in, e.g. the string "gpioNN"
* means that you want to mux in the pin for use as GPIO number NN
* @gpio_range: the range matching the GPIO pin if this is a request for a
* single GPIO pin
*/
static int pin_request(struct pinctrl_dev *pctldev,
int pin, const char *function,
struct pinctrl_gpio_range *gpio_range)
{
struct pin_desc *desc;
const struct pinmux_ops *ops = pctldev->desc->pmxops;
int status = -EINVAL;
dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, function);
desc = pin_desc_get(pctldev, pin);
if (desc == NULL) {
dev_err(pctldev->dev,
"pin is not registered so it cannot be requested\n");
goto out;
}
if (!function) {
dev_err(pctldev->dev, "no function name given\n");
return -EINVAL;
}
spin_lock(&desc->lock);
if (desc->mux_function) {
spin_unlock(&desc->lock);
dev_err(pctldev->dev,
"pin already requested\n");
goto out;
}