pinconf.c 8.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * Core driver for the pin config portions of the pin control subsystem
 *
 * Copyright (C) 2011 ST-Ericsson SA
 * Written on behalf of Linaro for ST-Ericsson
 *
 * Author: Linus Walleij <linus.walleij@linaro.org>
 *
 * License terms: GNU General Public License (GPL) version 2
 */
#define pr_fmt(fmt) "pinconfig core: " fmt

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf.h>
#include "core.h"
#include "pinconf.h"

int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
			   unsigned long *config)
{
	const struct pinconf_ops *ops = pctldev->desc->confops;

	if (!ops || !ops->pin_config_get) {
32
		dev_err(pctldev->dev, "cannot get pin configuration, missing "
33 34 35 36 37 38 39 40 41
			"pin_config_get() function in driver\n");
		return -EINVAL;
	}

	return ops->pin_config_get(pctldev, pin, config);
}

/**
 * pin_config_get() - get the configuration of a single pin parameter
42
 * @dev_name: name of the pin controller device for this pin
43 44 45 46 47
 * @name: name of the pin to get the config for
 * @config: the config pointed to by this argument will be filled in with the
 *	current pin state, it can be used directly by drivers as a numeral, or
 *	it can be dereferenced to any struct.
 */
48
int pin_config_get(const char *dev_name, const char *name,
49 50
			  unsigned long *config)
{
51
	struct pinctrl_dev *pctldev;
52 53
	int pin;

54 55 56 57
	pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
	if (!pctldev)
		return -EINVAL;

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
	pin = pin_get_from_name(pctldev, name);
	if (pin < 0)
		return pin;

	return pin_config_get_for_pin(pctldev, pin, config);
}
EXPORT_SYMBOL(pin_config_get);

int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
			   unsigned long config)
{
	const struct pinconf_ops *ops = pctldev->desc->confops;
	int ret;

	if (!ops || !ops->pin_config_set) {
73
		dev_err(pctldev->dev, "cannot configure pin, missing "
74 75 76 77 78 79
			"config function in driver\n");
		return -EINVAL;
	}

	ret = ops->pin_config_set(pctldev, pin, config);
	if (ret) {
80
		dev_err(pctldev->dev,
81 82 83 84 85 86 87 88 89
			"unable to set pin configuration on pin %d\n", pin);
		return ret;
	}

	return 0;
}

/**
 * pin_config_set() - set the configuration of a single pin parameter
90
 * @dev_name: name of pin controller device for this pin
91 92 93 94 95
 * @name: name of the pin to set the config for
 * @config: the config in this argument will contain the desired pin state, it
 *	can be used directly by drivers as a numeral, or it can be dereferenced
 *	to any struct.
 */
96
int pin_config_set(const char *dev_name, const char *name,
97 98
		   unsigned long config)
{
99
	struct pinctrl_dev *pctldev;
100 101
	int pin;

102 103 104 105
	pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
	if (!pctldev)
		return -EINVAL;

106 107 108 109 110 111 112 113
	pin = pin_get_from_name(pctldev, name);
	if (pin < 0)
		return pin;

	return pin_config_set_for_pin(pctldev, pin, config);
}
EXPORT_SYMBOL(pin_config_set);

114
int pin_config_group_get(const char *dev_name, const char *pin_group,
115 116
			 unsigned long *config)
{
117 118
	struct pinctrl_dev *pctldev;
	const struct pinconf_ops *ops;
119 120
	int selector;

121 122 123 124 125
	pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
	if (!pctldev)
		return -EINVAL;
	ops = pctldev->desc->confops;

126
	if (!ops || !ops->pin_config_group_get) {
127
		dev_err(pctldev->dev, "cannot get configuration for pin "
128 129 130 131 132 133 134 135 136 137 138 139 140 141
			"group, missing group config get function in "
			"driver\n");
		return -EINVAL;
	}

	selector = pinctrl_get_group_selector(pctldev, pin_group);
	if (selector < 0)
		return selector;

	return ops->pin_config_group_get(pctldev, selector, config);
}
EXPORT_SYMBOL(pin_config_group_get);


142
int pin_config_group_set(const char *dev_name, const char *pin_group,
143 144
			 unsigned long config)
{
145 146 147
	struct pinctrl_dev *pctldev;
	const struct pinconf_ops *ops;
	const struct pinctrl_ops *pctlops;
148 149 150 151 152 153
	int selector;
	const unsigned *pins;
	unsigned num_pins;
	int ret;
	int i;

154 155 156 157 158 159
	pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
	if (!pctldev)
		return -EINVAL;
	ops = pctldev->desc->confops;
	pctlops = pctldev->desc->pctlops;

160
	if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) {
161
		dev_err(pctldev->dev, "cannot configure pin group, missing "
162 163 164 165 166 167 168 169 170 171
			"config function in driver\n");
		return -EINVAL;
	}

	selector = pinctrl_get_group_selector(pctldev, pin_group);
	if (selector < 0)
		return selector;

	ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins);
	if (ret) {
172
		dev_err(pctldev->dev, "cannot configure pin group, error "
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
			"getting pins\n");
		return ret;
	}

	/*
	 * If the pin controller supports handling entire groups we use that
	 * capability.
	 */
	if (ops->pin_config_group_set) {
		ret = ops->pin_config_group_set(pctldev, selector, config);
		/*
		 * If the pin controller prefer that a certain group be handled
		 * pin-by-pin as well, it returns -EAGAIN.
		 */
		if (ret != -EAGAIN)
			return ret;
	}

	/*
	 * If the controller cannot handle entire groups, we configure each pin
	 * individually.
	 */
	if (!ops->pin_config_set)
		return 0;

	for (i = 0; i < num_pins; i++) {
		ret = ops->pin_config_set(pctldev, pins[i], config);
		if (ret < 0)
			return ret;
	}

	return 0;
}
EXPORT_SYMBOL(pin_config_group_set);

208
int pinconf_check_ops(struct pinctrl_dev *pctldev)
209
{
210 211
	const struct pinconf_ops *ops = pctldev->desc->confops;

212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
	/* We must be able to read out pin status */
	if (!ops->pin_config_get && !ops->pin_config_group_get)
		return -EINVAL;
	/* We have to be able to config the pins in SOME way */
	if (!ops->pin_config_set && !ops->pin_config_group_set)
		return -EINVAL;
	return 0;
}

#ifdef CONFIG_DEBUG_FS

static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
			     struct seq_file *s, int pin)
{
	const struct pinconf_ops *ops = pctldev->desc->confops;

	if (ops && ops->pin_config_dbg_show)
		ops->pin_config_dbg_show(pctldev, s, pin);
}

static int pinconf_pins_show(struct seq_file *s, void *what)
{
	struct pinctrl_dev *pctldev = s->private;
235
	unsigned i, pin;
236 237 238 239

	seq_puts(s, "Pin config settings per pin\n");
	seq_puts(s, "Format: pin (name): pinmux setting array\n");

240
	/* The pin number can be retrived from the pin controller descriptor */
241
	for (i = 0; i < pctldev->desc->npins; i++) {
242 243
		struct pin_desc *desc;

244
		pin = pctldev->desc->pins[i].number;
245
		desc = pin_desc_get(pctldev, pin);
246
		/* Skip if we cannot search the pin */
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
		if (desc == NULL)
			continue;

		seq_printf(s, "pin %d (%s):", pin,
			   desc->name ? desc->name : "unnamed");

		pinconf_dump_pin(pctldev, s, pin);

		seq_printf(s, "\n");
	}

	return 0;
}

static void pinconf_dump_group(struct pinctrl_dev *pctldev,
			       struct seq_file *s, unsigned selector,
			       const char *gname)
{
	const struct pinconf_ops *ops = pctldev->desc->confops;

	if (ops && ops->pin_config_group_dbg_show)
		ops->pin_config_group_dbg_show(pctldev, s, selector);
}

static int pinconf_groups_show(struct seq_file *s, void *what)
{
	struct pinctrl_dev *pctldev = s->private;
	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
	const struct pinconf_ops *ops = pctldev->desc->confops;
	unsigned selector = 0;

	if (!ops || !ops->pin_config_group_get)
		return 0;

	seq_puts(s, "Pin config settings per pin group\n");
	seq_puts(s, "Format: group (name): pinmux setting array\n");

	while (pctlops->list_groups(pctldev, selector) >= 0) {
		const char *gname = pctlops->get_group_name(pctldev, selector);

		seq_printf(s, "%u (%s):", selector, gname);
		pinconf_dump_group(pctldev, s, selector, gname);
		selector++;
	}

	return 0;
}

static int pinconf_pins_open(struct inode *inode, struct file *file)
{
	return single_open(file, pinconf_pins_show, inode->i_private);
}

static int pinconf_groups_open(struct inode *inode, struct file *file)
{
	return single_open(file, pinconf_groups_show, inode->i_private);
}

static const struct file_operations pinconf_pins_ops = {
	.open		= pinconf_pins_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
};

static const struct file_operations pinconf_groups_ops = {
	.open		= pinconf_groups_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
};

void pinconf_init_device_debugfs(struct dentry *devroot,
			 struct pinctrl_dev *pctldev)
{
	debugfs_create_file("pinconf-pins", S_IFREG | S_IRUGO,
			    devroot, pctldev, &pinconf_pins_ops);
	debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO,
			    devroot, pctldev, &pinconf_groups_ops);
}

#endif