mux.c 19.7 KB
Newer Older
1 2 3
/*
 * linux/arch/arm/mach-omap2/mux.c
 *
4
 * OMAP2, OMAP3 and OMAP4 pin multiplexing configurations
5
 *
6
 * Copyright (C) 2004 - 2010 Texas Instruments Inc.
T
Tony Lindgren 已提交
7
 * Copyright (C) 2003 - 2008 Nokia Corporation
8
 *
T
Tony Lindgren 已提交
9
 * Written by Tony Lindgren
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */
26
#include <linux/kernel.h>
27
#include <linux/init.h>
28
#include <linux/io.h>
29
#include <linux/list.h>
30
#include <linux/slab.h>
31 32 33 34
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
35

36 37
#include <asm/system.h>

38
#include "control.h"
39
#include "mux.h"
40

41 42 43
#define OMAP_MUX_BASE_OFFSET		0x30	/* Offset from CTRL_BASE */
#define OMAP_MUX_BASE_SZ		0x5ca

44 45 46 47 48
struct omap_mux_entry {
	struct omap_mux		mux;
	struct list_head	node;
};

49 50 51 52 53 54 55 56 57 58 59
static LIST_HEAD(mux_partitions);
static DEFINE_MUTEX(muxmode_mutex);

struct omap_mux_partition *omap_mux_get(const char *name)
{
	struct omap_mux_partition *partition;

	list_for_each_entry(partition, &mux_partitions, node) {
		if (!strcmp(name, partition->name))
			return partition;
	}
60

61 62 63 64
	return NULL;
}

u16 omap_mux_read(struct omap_mux_partition *partition, u16 reg)
65
{
66 67
	if (partition->flags & OMAP_MUX_REG_8BIT)
		return __raw_readb(partition->base + reg);
68
	else
69
		return __raw_readw(partition->base + reg);
70 71
}

72 73
void omap_mux_write(struct omap_mux_partition *partition, u16 val,
			   u16 reg)
74
{
75 76
	if (partition->flags & OMAP_MUX_REG_8BIT)
		__raw_writeb(val, partition->base + reg);
77
	else
78
		__raw_writew(val, partition->base + reg);
79
}
80

81 82
void omap_mux_write_array(struct omap_mux_partition *partition,
				 struct omap_board_mux *board_mux)
83
{
84 85 86
	while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) {
		omap_mux_write(partition, board_mux->value,
			       board_mux->reg_offset);
87 88 89 90
		board_mux++;
	}
}

91 92 93 94
#ifdef CONFIG_OMAP_MUX

static char *omap_mux_options;

95 96
static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
				      int gpio, int val)
97 98
{
	struct omap_mux_entry *e;
99
	struct omap_mux *gpio_mux = NULL;
100 101
	u16 old_mode;
	u16 mux_mode;
102
	int found = 0;
103
	struct list_head *muxmodes = &partition->muxmodes;
104 105 106 107

	if (!gpio)
		return -EINVAL;

108
	list_for_each_entry(e, muxmodes, node) {
109 110
		struct omap_mux *m = &e->mux;
		if (gpio == m->gpio) {
111
			gpio_mux = m;
112 113 114 115
			found++;
		}
	}

116
	if (found == 0) {
117
		pr_err("%s: Could not set gpio%i\n", __func__, gpio);
118 119
		return -ENODEV;
	}
120 121

	if (found > 1) {
122
		pr_info("%s: Multiple gpio paths (%d) for gpio%i\n", __func__,
123
			found, gpio);
124 125 126
		return -EINVAL;
	}

127
	old_mode = omap_mux_read(partition, gpio_mux->reg_offset);
128
	mux_mode = val & ~(OMAP_MUX_NR_MODES - 1);
129
	if (partition->flags & OMAP_MUX_GPIO_IN_MODE3)
130 131 132
		mux_mode |= OMAP_MUX_MODE3;
	else
		mux_mode |= OMAP_MUX_MODE4;
133
	pr_debug("%s: Setting signal %s.gpio%i 0x%04x -> 0x%04x\n", __func__,
134
		 gpio_mux->muxnames[0], gpio, old_mode, mux_mode);
135
	omap_mux_write(partition, mux_mode, gpio_mux->reg_offset);
136

137
	return 0;
138 139
}

140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
int __init omap_mux_init_gpio(int gpio, int val)
{
	struct omap_mux_partition *partition;
	int ret;

	list_for_each_entry(partition, &mux_partitions, node) {
		ret = _omap_mux_init_gpio(partition, gpio, val);
		if (!ret)
			return ret;
	}

	return -ENODEV;
}

static int __init _omap_mux_init_signal(struct omap_mux_partition *partition,
					const char *muxname, int val)
156 157
{
	struct omap_mux_entry *e;
158 159
	const char *mode_name;
	int found = 0, mode0_len = 0;
160
	struct list_head *muxmodes = &partition->muxmodes;
161 162 163

	mode_name = strchr(muxname, '.');
	if (mode_name) {
164
		mode0_len = strlen(muxname) - strlen(mode_name);
165 166 167 168 169
		mode_name++;
	} else {
		mode_name = muxname;
	}

170
	list_for_each_entry(e, muxmodes, node) {
171 172 173 174
		struct omap_mux *m = &e->mux;
		char *m0_entry = m->muxnames[0];
		int i;

175 176
		/* First check for full name in mode0.muxmode format */
		if (mode0_len && strncmp(muxname, m0_entry, mode0_len))
177 178
			continue;

179
		/* Then check for muxmode only */
180 181 182 183 184 185 186 187 188 189
		for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
			char *mode_cur = m->muxnames[i];

			if (!mode_cur)
				continue;

			if (!strcmp(mode_name, mode_cur)) {
				u16 old_mode;
				u16 mux_mode;

190 191
				old_mode = omap_mux_read(partition,
							 m->reg_offset);
192
				mux_mode = val | i;
193 194
				pr_debug("%s: Setting signal "
					 "%s.%s 0x%04x -> 0x%04x\n", __func__,
195
					 m0_entry, muxname, old_mode, mux_mode);
196 197
				omap_mux_write(partition, mux_mode,
					       m->reg_offset);
198 199 200 201 202 203 204 205 206
				found++;
			}
		}
	}

	if (found == 1)
		return 0;

	if (found > 1) {
207
		pr_err("%s: Multiple signal paths (%i) for %s\n", __func__,
208
		       found, muxname);
209 210 211
		return -EINVAL;
	}

212
	pr_err("%s: Could not set signal %s\n", __func__, muxname);
213 214 215 216

	return -ENODEV;
}

217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
int __init omap_mux_init_signal(const char *muxname, int val)
{
	struct omap_mux_partition *partition;
	int ret;

	list_for_each_entry(partition, &mux_partitions, node) {
		ret = _omap_mux_init_signal(partition, muxname, val);
		if (!ret)
			return ret;
	}

	return -ENODEV;

}

232 233 234 235 236 237 238 239 240 241 242 243 244
#ifdef CONFIG_DEBUG_FS

#define OMAP_MUX_MAX_NR_FLAGS	10
#define OMAP_MUX_TEST_FLAG(val, mask)				\
	if (((val) & (mask)) == (mask)) {			\
		i++;						\
		flags[i] =  #mask;				\
	}

/* REVISIT: Add checking for non-optimal mux settings */
static inline void omap_mux_decode(struct seq_file *s, u16 val)
{
	char *flags[OMAP_MUX_MAX_NR_FLAGS];
245
	char mode[sizeof("OMAP_MUX_MODE") + 1];
246 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
	int i = -1;

	sprintf(mode, "OMAP_MUX_MODE%d", val & 0x7);
	i++;
	flags[i] = mode;

	OMAP_MUX_TEST_FLAG(val, OMAP_PIN_OFF_WAKEUPENABLE);
	if (val & OMAP_OFF_EN) {
		if (!(val & OMAP_OFFOUT_EN)) {
			if (!(val & OMAP_OFF_PULL_UP)) {
				OMAP_MUX_TEST_FLAG(val,
					OMAP_PIN_OFF_INPUT_PULLDOWN);
			} else {
				OMAP_MUX_TEST_FLAG(val,
					OMAP_PIN_OFF_INPUT_PULLUP);
			}
		} else {
			if (!(val & OMAP_OFFOUT_VAL)) {
				OMAP_MUX_TEST_FLAG(val,
					OMAP_PIN_OFF_OUTPUT_LOW);
			} else {
				OMAP_MUX_TEST_FLAG(val,
					OMAP_PIN_OFF_OUTPUT_HIGH);
			}
		}
	}

	if (val & OMAP_INPUT_EN) {
		if (val & OMAP_PULL_ENA) {
			if (!(val & OMAP_PULL_UP)) {
				OMAP_MUX_TEST_FLAG(val,
					OMAP_PIN_INPUT_PULLDOWN);
			} else {
				OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT_PULLUP);
			}
		} else {
			OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT);
		}
	} else {
		i++;
		flags[i] = "OMAP_PIN_OUTPUT";
	}

	do {
		seq_printf(s, "%s", flags[i]);
		if (i > 0)
			seq_printf(s, " | ");
	} while (i-- > 0);
}

296
#define OMAP_MUX_DEFNAME_LEN	32
297 298 299

static int omap_mux_dbg_board_show(struct seq_file *s, void *unused)
{
300
	struct omap_mux_partition *partition = s->private;
301
	struct omap_mux_entry *e;
302
	u8 omap_gen = omap_rev() >> 28;
303

304
	list_for_each_entry(e, &partition->muxmodes, node) {
305 306 307 308 309 310 311 312 313
		struct omap_mux *m = &e->mux;
		char m0_def[OMAP_MUX_DEFNAME_LEN];
		char *m0_name = m->muxnames[0];
		u16 val;
		int i, mode;

		if (!m0_name)
			continue;

314
		/* REVISIT: Needs to be updated if mode0 names get longer */
315 316 317 318 319 320 321
		for (i = 0; i < OMAP_MUX_DEFNAME_LEN; i++) {
			if (m0_name[i] == '\0') {
				m0_def[i] = m0_name[i];
				break;
			}
			m0_def[i] = toupper(m0_name[i]);
		}
322
		val = omap_mux_read(partition, m->reg_offset);
323
		mode = val & OMAP_MUX_MODE7;
324 325 326 327 328 329 330 331
		if (mode != 0)
			seq_printf(s, "/* %s */\n", m->muxnames[mode]);

		/*
		 * XXX: Might be revisited to support differences accross
		 * same OMAP generation.
		 */
		seq_printf(s, "OMAP%d_MUX(%s, ", omap_gen, m0_def);
332 333 334 335 336 337 338 339 340
		omap_mux_decode(s, val);
		seq_printf(s, "),\n");
	}

	return 0;
}

static int omap_mux_dbg_board_open(struct inode *inode, struct file *file)
{
341
	return single_open(file, omap_mux_dbg_board_show, inode->i_private);
342 343 344 345 346 347 348 349 350
}

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

351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
static struct omap_mux_partition *omap_mux_get_partition(struct omap_mux *mux)
{
	struct omap_mux_partition *partition;

	list_for_each_entry(partition, &mux_partitions, node) {
		struct list_head *muxmodes = &partition->muxmodes;
		struct omap_mux_entry *e;

		list_for_each_entry(e, muxmodes, node) {
			struct omap_mux *m = &e->mux;

			if (m == mux)
				return partition;
		}
	}

	return NULL;
}

370 371 372
static int omap_mux_dbg_signal_show(struct seq_file *s, void *unused)
{
	struct omap_mux *m = s->private;
373
	struct omap_mux_partition *partition;
374 375 376 377
	const char *none = "NA";
	u16 val;
	int mode;

378 379 380 381 382
	partition = omap_mux_get_partition(m);
	if (!partition)
		return 0;

	val = omap_mux_read(partition, m->reg_offset);
383 384
	mode = val & OMAP_MUX_MODE7;

385
	seq_printf(s, "name: %s.%s (0x%08x/0x%03x = 0x%04x), b %s, t %s\n",
386
			m->muxnames[0], m->muxnames[mode],
387
			partition->phys + m->reg_offset, m->reg_offset, val,
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
			m->balls[0] ? m->balls[0] : none,
			m->balls[1] ? m->balls[1] : none);
	seq_printf(s, "mode: ");
	omap_mux_decode(s, val);
	seq_printf(s, "\n");
	seq_printf(s, "signals: %s | %s | %s | %s | %s | %s | %s | %s\n",
			m->muxnames[0] ? m->muxnames[0] : none,
			m->muxnames[1] ? m->muxnames[1] : none,
			m->muxnames[2] ? m->muxnames[2] : none,
			m->muxnames[3] ? m->muxnames[3] : none,
			m->muxnames[4] ? m->muxnames[4] : none,
			m->muxnames[5] ? m->muxnames[5] : none,
			m->muxnames[6] ? m->muxnames[6] : none,
			m->muxnames[7] ? m->muxnames[7] : none);

	return 0;
}

#define OMAP_MUX_MAX_ARG_CHAR  7

static ssize_t omap_mux_dbg_signal_write(struct file *file,
409 410
					 const char __user *user_buf,
					 size_t count, loff_t *ppos)
411 412 413 414 415 416
{
	char buf[OMAP_MUX_MAX_ARG_CHAR];
	struct seq_file *seqf;
	struct omap_mux *m;
	unsigned long val;
	int buf_size, ret;
417
	struct omap_mux_partition *partition;
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437

	if (count > OMAP_MUX_MAX_ARG_CHAR)
		return -EINVAL;

	memset(buf, 0, sizeof(buf));
	buf_size = min(count, sizeof(buf) - 1);

	if (copy_from_user(buf, user_buf, buf_size))
		return -EFAULT;

	ret = strict_strtoul(buf, 0x10, &val);
	if (ret < 0)
		return ret;

	if (val > 0xffff)
		return -EINVAL;

	seqf = file->private_data;
	m = seqf->private;

438 439 440 441 442
	partition = omap_mux_get_partition(m);
	if (!partition)
		return -ENODEV;

	omap_mux_write(partition, (u16)val, m->reg_offset);
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
	*ppos += count;

	return count;
}

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

static const struct file_operations omap_mux_dbg_signal_fops = {
	.open		= omap_mux_dbg_signal_open,
	.read		= seq_read,
	.write		= omap_mux_dbg_signal_write,
	.llseek		= seq_lseek,
	.release	= single_release,
};

static struct dentry *mux_dbg_dir;

463 464 465
static void __init omap_mux_dbg_create_entry(
				struct omap_mux_partition *partition,
				struct dentry *mux_dbg_dir)
466 467 468
{
	struct omap_mux_entry *e;

469 470 471 472 473 474 475 476 477 478 479 480 481
	list_for_each_entry(e, &partition->muxmodes, node) {
		struct omap_mux *m = &e->mux;

		(void)debugfs_create_file(m->muxnames[0], S_IWUGO, mux_dbg_dir,
					  m, &omap_mux_dbg_signal_fops);
	}
}

static void __init omap_mux_dbg_init(void)
{
	struct omap_mux_partition *partition;
	static struct dentry *mux_dbg_board_dir;

482 483 484 485
	mux_dbg_dir = debugfs_create_dir("omap_mux", NULL);
	if (!mux_dbg_dir)
		return;

486 487 488
	mux_dbg_board_dir = debugfs_create_dir("board", mux_dbg_dir);
	if (!mux_dbg_board_dir)
		return;
489

490 491 492 493 494
	list_for_each_entry(partition, &mux_partitions, node) {
		omap_mux_dbg_create_entry(partition, mux_dbg_dir);
		(void)debugfs_create_file(partition->name, S_IRUGO,
					  mux_dbg_board_dir, partition,
					  &omap_mux_dbg_board_fops);
495 496 497 498 499 500 501 502 503
	}
}

#else
static inline void omap_mux_dbg_init(void)
{
}
#endif	/* CONFIG_DEBUG_FS */

504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
static void __init omap_mux_free_names(struct omap_mux *m)
{
	int i;

	for (i = 0; i < OMAP_MUX_NR_MODES; i++)
		kfree(m->muxnames[i]);

#ifdef CONFIG_DEBUG_FS
	for (i = 0; i < OMAP_MUX_NR_SIDES; i++)
		kfree(m->balls[i]);
#endif

}

/* Free all data except for GPIO pins unless CONFIG_DEBUG_FS is set */
static int __init omap_mux_late_init(void)
{
521
	struct omap_mux_partition *partition;
522

523 524 525 526 527
	list_for_each_entry(partition, &mux_partitions, node) {
		struct omap_mux_entry *e, *tmp;
		list_for_each_entry_safe(e, tmp, &partition->muxmodes, node) {
			struct omap_mux *m = &e->mux;
			u16 mode = omap_mux_read(partition, m->reg_offset);
528

529 530
			if (OMAP_MODE_GPIO(mode))
				continue;
531 532

#ifndef CONFIG_DEBUG_FS
533 534 535 536 537
			mutex_lock(&muxmode_mutex);
			list_del(&e->node);
			mutex_unlock(&muxmode_mutex);
			omap_mux_free_names(m);
			kfree(m);
538
#endif
539
		}
540 541
	}

542 543
	omap_mux_dbg_init();

544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
	return 0;
}
late_initcall(omap_mux_late_init);

static void __init omap_mux_package_fixup(struct omap_mux *p,
					struct omap_mux *superset)
{
	while (p->reg_offset !=  OMAP_MUX_TERMINATOR) {
		struct omap_mux *s = superset;
		int found = 0;

		while (s->reg_offset != OMAP_MUX_TERMINATOR) {
			if (s->reg_offset == p->reg_offset) {
				*s = *p;
				found++;
				break;
			}
			s++;
		}
		if (!found)
564
			pr_err("%s: Unknown entry offset 0x%x\n", __func__,
565
			       p->reg_offset);
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
		p++;
	}
}

#ifdef CONFIG_DEBUG_FS

static void __init omap_mux_package_init_balls(struct omap_ball *b,
				struct omap_mux *superset)
{
	while (b->reg_offset != OMAP_MUX_TERMINATOR) {
		struct omap_mux *s = superset;
		int found = 0;

		while (s->reg_offset != OMAP_MUX_TERMINATOR) {
			if (s->reg_offset == b->reg_offset) {
				s->balls[0] = b->balls[0];
				s->balls[1] = b->balls[1];
				found++;
				break;
			}
			s++;
		}
		if (!found)
589
			pr_err("%s: Unknown ball offset 0x%x\n", __func__,
590
			       b->reg_offset);
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
		b++;
	}
}

#else	/* CONFIG_DEBUG_FS */

static inline void omap_mux_package_init_balls(struct omap_ball *b,
					struct omap_mux *superset)
{
}

#endif	/* CONFIG_DEBUG_FS */

static int __init omap_mux_setup(char *options)
{
	if (!options)
		return 0;

	omap_mux_options = options;

	return 1;
}
__setup("omap_mux=", omap_mux_setup);

/*
 * Note that the omap_mux=some.signal1=0x1234,some.signal2=0x1234
 * cmdline options only override the bootloader values.
 * During development, please enable CONFIG_DEBUG_FS, and use the
 * signal specific entries under debugfs.
 */
static void __init omap_mux_set_cmdline_signals(void)
{
	char *options, *next_opt, *token;

	if (!omap_mux_options)
		return;

	options = kmalloc(strlen(omap_mux_options) + 1, GFP_KERNEL);
	if (!options)
		return;

	strcpy(options, omap_mux_options);
	next_opt = options;

	while ((token = strsep(&next_opt, ",")) != NULL) {
		char *keyval, *name;
		unsigned long val;

		keyval = token;
		name = strsep(&keyval, "=");
		if (name) {
			int res;

			res = strict_strtoul(keyval, 0x10, &val);
			if (res < 0)
				continue;

			omap_mux_init_signal(name, (u16)val);
		}
	}

	kfree(options);
}

static int __init omap_mux_copy_names(struct omap_mux *src,
656
				      struct omap_mux *dst)
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
{
	int i;

	for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
		if (src->muxnames[i]) {
			dst->muxnames[i] =
				kmalloc(strlen(src->muxnames[i]) + 1,
					GFP_KERNEL);
			if (!dst->muxnames[i])
				goto free;
			strcpy(dst->muxnames[i], src->muxnames[i]);
		}
	}

#ifdef CONFIG_DEBUG_FS
	for (i = 0; i < OMAP_MUX_NR_SIDES; i++) {
		if (src->balls[i]) {
			dst->balls[i] =
				kmalloc(strlen(src->balls[i]) + 1,
					GFP_KERNEL);
			if (!dst->balls[i])
				goto free;
			strcpy(dst->balls[i], src->balls[i]);
		}
	}
#endif

	return 0;

free:
	omap_mux_free_names(dst);
	return -ENOMEM;

}

#endif	/* CONFIG_OMAP_MUX */

694 695 696
static struct omap_mux *omap_mux_get_by_gpio(
				struct omap_mux_partition *partition,
				int gpio)
697 698
{
	struct omap_mux_entry *e;
699
	struct omap_mux *ret = NULL;
700

701
	list_for_each_entry(e, &partition->muxmodes, node) {
702 703
		struct omap_mux *m = &e->mux;
		if (m->gpio == gpio) {
704
			ret = m;
705 706 707 708
			break;
		}
	}

709
	return ret;
710 711 712 713 714
}

/* Needed for dynamic muxing of GPIO pins for off-idle */
u16 omap_mux_get_gpio(int gpio)
{
715 716
	struct omap_mux_partition *partition;
	struct omap_mux *m;
717

718 719 720 721
	list_for_each_entry(partition, &mux_partitions, node) {
		m = omap_mux_get_by_gpio(partition, gpio);
		if (m)
			return omap_mux_read(partition, m->reg_offset);
722 723
	}

724
	if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
725
		pr_err("%s: Could not get gpio%i\n", __func__, gpio);
726 727

	return OMAP_MUX_TERMINATOR;
728 729 730 731 732
}

/* Needed for dynamic muxing of GPIO pins for off-idle */
void omap_mux_set_gpio(u16 val, int gpio)
{
733 734
	struct omap_mux_partition *partition;
	struct omap_mux *m = NULL;
735

736 737 738 739 740 741
	list_for_each_entry(partition, &mux_partitions, node) {
		m = omap_mux_get_by_gpio(partition, gpio);
		if (m) {
			omap_mux_write(partition, val, m->reg_offset);
			return;
		}
742 743
	}

744
	if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
745
		pr_err("%s: Could not set gpio%i\n", __func__, gpio);
746 747
}

748 749 750
static struct omap_mux * __init omap_mux_list_add(
					struct omap_mux_partition *partition,
					struct omap_mux *src)
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
{
	struct omap_mux_entry *entry;
	struct omap_mux *m;

	entry = kzalloc(sizeof(struct omap_mux_entry), GFP_KERNEL);
	if (!entry)
		return NULL;

	m = &entry->mux;
	memcpy(m, src, sizeof(struct omap_mux_entry));

#ifdef CONFIG_OMAP_MUX
	if (omap_mux_copy_names(src, m)) {
		kfree(entry);
		return NULL;
	}
#endif

	mutex_lock(&muxmode_mutex);
770
	list_add_tail(&entry->node, &partition->muxmodes);
771 772 773 774 775 776 777 778 779 780
	mutex_unlock(&muxmode_mutex);

	return m;
}

/*
 * Note if CONFIG_OMAP_MUX is not selected, we will only initialize
 * the GPIO to mux offset mapping that is needed for dynamic muxing
 * of GPIO pins for off-idle.
 */
781 782
static void __init omap_mux_init_list(struct omap_mux_partition *partition,
				      struct omap_mux *superset)
783 784 785 786
{
	while (superset->reg_offset !=  OMAP_MUX_TERMINATOR) {
		struct omap_mux *entry;

787 788
#ifdef CONFIG_OMAP_MUX
		if (!superset->muxnames || !superset->muxnames[0]) {
789 790 791
			superset++;
			continue;
		}
792 793
#else
		/* Skip pins that are not muxed as GPIO by bootloader */
794 795
		if (!OMAP_MODE_GPIO(omap_mux_read(partition,
				    superset->reg_offset))) {
T
Tony Lindgren 已提交
796 797 798 799 800
			superset++;
			continue;
		}
#endif

801
		entry = omap_mux_list_add(partition, superset);
802
		if (!entry) {
803
			pr_err("%s: Could not add entry\n", __func__);
804 805 806 807 808 809
			return;
		}
		superset++;
	}
}

810 811 812 813 814 815 816 817 818 819 820 821
#ifdef CONFIG_OMAP_MUX

static void omap_mux_init_package(struct omap_mux *superset,
				  struct omap_mux *package_subset,
				  struct omap_ball *package_balls)
{
	if (package_subset)
		omap_mux_package_fixup(package_subset, superset);
	if (package_balls)
		omap_mux_package_init_balls(package_balls, superset);
}

822 823
static void omap_mux_init_signals(struct omap_mux_partition *partition,
				  struct omap_board_mux *board_mux)
824 825
{
	omap_mux_set_cmdline_signals();
826
	omap_mux_write_array(partition, board_mux);
827 828 829 830 831 832 833 834 835 836
}

#else

static void omap_mux_init_package(struct omap_mux *superset,
				  struct omap_mux *package_subset,
				  struct omap_ball *package_balls)
{
}

837 838
static void omap_mux_init_signals(struct omap_mux_partition *partition,
				  struct omap_board_mux *board_mux)
839 840 841 842 843
{
}

#endif

844
static u32 mux_partitions_cnt;
845

846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
int __init omap_mux_init(const char *name, u32 flags,
			 u32 mux_pbase, u32 mux_size,
			 struct omap_mux *superset,
			 struct omap_mux *package_subset,
			 struct omap_board_mux *board_mux,
			 struct omap_ball *package_balls)
{
	struct omap_mux_partition *partition;

	partition = kzalloc(sizeof(struct omap_mux_partition), GFP_KERNEL);
	if (!partition)
		return -ENOMEM;

	partition->name = name;
	partition->flags = flags;
	partition->size = mux_size;
	partition->phys = mux_pbase;
	partition->base = ioremap(mux_pbase, mux_size);
	if (!partition->base) {
865 866
		pr_err("%s: Could not ioremap mux partition at 0x%08x\n",
			__func__, partition->phys);
867 868 869
		return -ENODEV;
	}

870 871 872 873
	INIT_LIST_HEAD(&partition->muxmodes);

	list_add_tail(&partition->node, &mux_partitions);
	mux_partitions_cnt++;
874
	pr_info("%s: Add partition: #%d: %s, flags: %x\n", __func__,
875
		mux_partitions_cnt, partition->name, partition->flags);
876

877
	omap_mux_init_package(superset, package_subset, package_balls);
878 879
	omap_mux_init_list(partition, superset);
	omap_mux_init_signals(partition, board_mux);
T
Tony Lindgren 已提交
880

881 882 883
	return 0;
}