pinconf.c 8.9 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
/*
 * 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"

26 27 28 29 30 31 32 33 34 35 36 37 38 39
int pinconf_check_ops(struct pinctrl_dev *pctldev)
{
	const struct pinconf_ops *ops = pctldev->desc->confops;

	/* 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;
}

static int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
40 41 42 43 44
			   unsigned long *config)
{
	const struct pinconf_ops *ops = pctldev->desc->confops;

	if (!ops || !ops->pin_config_get) {
45
		dev_err(pctldev->dev, "cannot get pin configuration, missing "
46 47 48 49 50 51 52 53 54
			"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
55
 * @dev_name: name of the pin controller device for this pin
56 57 58 59 60
 * @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.
 */
61
int pin_config_get(const char *dev_name, const char *name,
62 63
			  unsigned long *config)
{
64
	struct pinctrl_dev *pctldev;
65 66
	int pin;

67 68
	mutex_lock(&pinctrl_mutex);

69
	pctldev = get_pinctrl_dev_from_devname(dev_name);
70 71 72 73
	if (!pctldev) {
		pin = -EINVAL;
		goto unlock;
	}
74

75 76
	pin = pin_get_from_name(pctldev, name);
	if (pin < 0)
77
		goto unlock;
78

79 80 81 82 83
	pin = pin_config_get_for_pin(pctldev, pin, config);

unlock:
	mutex_unlock(&pinctrl_mutex);
	return pin;
84 85 86
}
EXPORT_SYMBOL(pin_config_get);

87
static int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
88 89 90 91 92 93
			   unsigned long config)
{
	const struct pinconf_ops *ops = pctldev->desc->confops;
	int ret;

	if (!ops || !ops->pin_config_set) {
94
		dev_err(pctldev->dev, "cannot configure pin, missing "
95 96 97 98 99 100
			"config function in driver\n");
		return -EINVAL;
	}

	ret = ops->pin_config_set(pctldev, pin, config);
	if (ret) {
101
		dev_err(pctldev->dev,
102 103 104 105 106 107 108 109 110
			"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
111
 * @dev_name: name of pin controller device for this pin
112 113 114 115 116
 * @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.
 */
117
int pin_config_set(const char *dev_name, const char *name,
118 119
		   unsigned long config)
{
120
	struct pinctrl_dev *pctldev;
121 122 123
	int pin, ret;

	mutex_lock(&pinctrl_mutex);
124

125
	pctldev = get_pinctrl_dev_from_devname(dev_name);
126 127 128 129
	if (!pctldev) {
		ret = -EINVAL;
		goto unlock;
	}
130

131
	pin = pin_get_from_name(pctldev, name);
132 133 134 135 136 137
	if (pin < 0) {
		ret = pin;
		goto unlock;
	}

	ret = pin_config_set_for_pin(pctldev, pin, config);
138

139 140 141
unlock:
	mutex_unlock(&pinctrl_mutex);
	return ret;
142 143 144
}
EXPORT_SYMBOL(pin_config_set);

145
int pin_config_group_get(const char *dev_name, const char *pin_group,
146 147
			 unsigned long *config)
{
148 149
	struct pinctrl_dev *pctldev;
	const struct pinconf_ops *ops;
150 151 152
	int selector, ret;

	mutex_lock(&pinctrl_mutex);
153

154
	pctldev = get_pinctrl_dev_from_devname(dev_name);
155 156 157 158
	if (!pctldev) {
		ret = -EINVAL;
		goto unlock;
	}
159 160
	ops = pctldev->desc->confops;

161
	if (!ops || !ops->pin_config_group_get) {
162
		dev_err(pctldev->dev, "cannot get configuration for pin "
163 164
			"group, missing group config get function in "
			"driver\n");
165 166
		ret = -EINVAL;
		goto unlock;
167 168 169
	}

	selector = pinctrl_get_group_selector(pctldev, pin_group);
170 171 172 173
	if (selector < 0) {
		ret = selector;
		goto unlock;
	}
174

175 176 177 178 179
	ret = ops->pin_config_group_get(pctldev, selector, config);

unlock:
	mutex_unlock(&pinctrl_mutex);
	return ret;
180 181 182
}
EXPORT_SYMBOL(pin_config_group_get);

183
int pin_config_group_set(const char *dev_name, const char *pin_group,
184 185
			 unsigned long config)
{
186 187 188
	struct pinctrl_dev *pctldev;
	const struct pinconf_ops *ops;
	const struct pinctrl_ops *pctlops;
189 190 191 192 193 194
	int selector;
	const unsigned *pins;
	unsigned num_pins;
	int ret;
	int i;

195 196
	mutex_lock(&pinctrl_mutex);

197
	pctldev = get_pinctrl_dev_from_devname(dev_name);
198 199 200 201
	if (!pctldev) {
		ret = -EINVAL;
		goto unlock;
	}
202 203 204
	ops = pctldev->desc->confops;
	pctlops = pctldev->desc->pctlops;

205
	if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) {
206
		dev_err(pctldev->dev, "cannot configure pin group, missing "
207
			"config function in driver\n");
208 209
		ret = -EINVAL;
		goto unlock;
210 211 212
	}

	selector = pinctrl_get_group_selector(pctldev, pin_group);
213 214 215 216
	if (selector < 0) {
		ret = selector;
		goto unlock;
	}
217 218 219

	ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins);
	if (ret) {
220
		dev_err(pctldev->dev, "cannot configure pin group, error "
221
			"getting pins\n");
222
		goto unlock;
223 224 225 226 227 228 229 230 231 232 233 234 235
	}

	/*
	 * 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)
236
			goto unlock;
237 238 239 240 241 242
	}

	/*
	 * If the controller cannot handle entire groups, we configure each pin
	 * individually.
	 */
243 244 245 246
	if (!ops->pin_config_set) {
		ret = 0;
		goto unlock;
	}
247 248 249 250

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

254 255 256 257 258 259
	ret = 0;

unlock:
	mutex_unlock(&pinctrl_mutex);

	return ret;
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
}
EXPORT_SYMBOL(pin_config_group_set);

#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;
277
	unsigned i, pin;
278 279 280 281

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

282 283
	mutex_lock(&pinctrl_mutex);

284
	/* The pin number can be retrived from the pin controller descriptor */
285
	for (i = 0; i < pctldev->desc->npins; i++) {
286 287
		struct pin_desc *desc;

288
		pin = pctldev->desc->pins[i].number;
289
		desc = pin_desc_get(pctldev, pin);
290
		/* Skip if we cannot search the pin */
291 292 293 294 295 296 297 298 299 300 301
		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");
	}

302 303
	mutex_unlock(&pinctrl_mutex);

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 329
	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");

330 331
	mutex_lock(&pinctrl_mutex);

332 333 334 335 336
	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);
337 338
		seq_printf(s, "\n");

339 340 341
		selector++;
	}

342 343
	mutex_unlock(&pinctrl_mutex);

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
	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