/*
* Core driver for the pin control subsystem
*
* Copyright (C) 2011-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>
*
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
*
* 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"
#include "pinconf.h"
/**
* struct pinctrl_maps - a list item containing part of the mapping table
* @node: mapping table list node
* @maps: array of mapping table entries
* @num_maps: the number of entries in @maps
*/
struct pinctrl_maps {
struct list_head node;
struct pinctrl_map const *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 */
static DEFINE_MUTEX(pinctrldev_list_mutex);
static LIST_HEAD(pinctrldev_list);
/* List of pin controller handles */
static DEFINE_MUTEX(pinctrl_list_mutex);
static LIST_HEAD(pinctrl_list);
/* Global pinctrl maps */
static DEFINE_MUTEX(pinctrl_maps_mutex);
static LIST_HEAD(pinctrl_maps);
#define for_each_maps(_maps_node_, _i_, _map_) \
list_for_each_entry(_maps_node_, &pinctrl_maps, node) \
for (_i_ = 0, _map_ = &_maps_node_->maps[_i_]; \
_i_ < _maps_node_->num_maps; \
i++, _map_ = &_maps_node_->maps[_i_])
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_devname() - look up pin controller device
* @devname: the name of a device instance, as returned by dev_name()
*
* 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_devname(const char *devname)
{
struct pinctrl_dev *pctldev = NULL;
bool found = false;
if (!devname)
return NULL;
mutex_lock(&pinctrldev_list_mutex);
list_for_each_entry(pctldev, &pinctrldev_list, node) {
if (!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, unsigned int pin)
{
struct pin_desc *pindesc;
unsigned long flags;
spin_lock_irqsave(&pctldev