summaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen
AgeCommit message (Expand)Author
2012-01-13module_param: make bool parameters really bool (drivers & misc)Rusty Russell
2012-01-12Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dto...Linus Torvalds
2012-01-10Input: revert some over-zealous conversions to module_platform_driver()Dmitry Torokhov
2012-01-10Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dto...Linus Torvalds
2012-01-09Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-socLinus Torvalds
2012-01-08Merge branch 'pm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/...Linus Torvalds
2012-01-08Merge branch 'for-linus2' of git://git.kernel.org/pub/scm/linux/kernel/git/vi...Linus Torvalds
2012-01-04Input: ucb1400-ts - switch to using dev_xxx() for diagnostic messagesDmitry Torokhov
2012-01-04Input: ucb1400_ts - convert to threaded IRQDmitry Torokhov
2012-01-04Input: ucb1400_ts - drop inline annotationsDmitry Torokhov
2012-01-04Input: usb1400_ts - add __devinit/__devexit section annotationsDmitry Torokhov
2012-01-04Input: ucb1400_ts - set driver ownerDmitry Torokhov
2012-01-04Input: ucb1400_ts - convert to use dev_pm_opsDmitry Torokhov
2012-01-03switch ->is_visible() to returning umode_tAl Viro
2011-12-30Input: add driver for pixcir i2c touchscreensJianchun Bian
2011-12-28Input: zylonite-wm97xx - replace IRQ_GPIO() with gpio_to_irq()Axel Lin
2011-12-27Input: add driver for AUO In-Cell touchscreens using pixcir ICsHeiko Stübner
2011-12-25PM / input / touchscreen: Make st1232 use device PM QoS constraintsRafael J. Wysocki
2011-12-12Input: migor-ts - rework probe() to simplify error pathDmitry Torokhov
2011-12-12Input: migor-ts - use proper client data accessor functionsDmitry Torokhov
2011-12-12Input: migor-ts - convert to a threaded IRQDmitry Torokhov
2011-11-30Input: htcpen - switch to DMI-based autoloadingDmitry Torokhov
2011-11-30Input: ad7879-i2c - use swapped variant of i2c_smbus_read_word_dataJonathan Cameron
2011-11-30Input: touchscreen - use macro module_platform_driver()JJ Ding
2011-11-29Input: remove redundant spi driver bus initializationLars-Peter Clausen
2011-11-29Input: ad7879-i2c - remove redundant MODULE_ALIASAxel Lin
2011-11-29Merge commit 'v3.2-rc3' into nextDmitry Torokhov
2011-11-18USB: convert drivers/input/* to use module_usb_driver()Greg Kroah-Hartman
2011-11-15Input: ad7879 - consolidate PM methodsDmitry Torokhov
2011-11-15Input: add EETI eGalax I2C capacitive multi touch driverZhang Jiejing
2011-11-09Input: convert obsolete strict_strtox to kstrtoxJJ Ding
2011-11-06Merge branch 'modsplit-Oct31_2011' of git://git.kernel.org/pub/scm/linux/kern...Linus Torvalds
2011-11-05Input: usbtouchscreen - add ELO IntelliTouch 2700 supportMichael Gebetsroither
2011-11-03Merge branch 'for-next' of git://git.infradead.org/users/sameo/mfd-2.6Linus Torvalds
2011-10-31drivers/input: Add module.h to modular drivers implicitly using itPaul Gortmaker
2011-10-26Merge branch 'next' into for-linusDmitry Torokhov
2011-10-24input: Convert mc13783-ts to mc13xxx APIUwe Kleine-König
2011-10-11Input: tsc2007 - make sure that X plate resistance is specifiedPhilip Rakity
2011-10-06Input: ad7879-i2c - wrap suspend and resume in CONFIG_PM_SLEEPDmitry Torokhov
2011-10-06Input: atmel_mxt_ts - use snprintf for sysfs attribute show methodDaniel Kurtz
2011-09-28Input: add a driver for TSC-40 serial touchscreenSebastian Andrzej Siewior
2011-09-20Input: penmount - simplify unregister procedureDmitry Torokhov
2011-09-20Input: penmount - rework handling of different protocolsDmitry Torokhov
2011-09-20Input: penmount - add PenMount 6250 supportJohn Sung
2011-09-20Input: penmount - add PenMount 3000 supportJohn Sung
2011-09-20Input: penmount - add PenMount 6000 supportJohn Sung
2011-09-20Input: penmount - fix the protocolJohn Sung
2011-09-08Input: wacom - add POINTER and DIRECT device propertiesJason Gerecke
2011-09-07Input: remove IRQF_DISABLED from driversYong Zhang
2011-09-07Merge commit 'v3.1-rc4' into nextDmitry Torokhov
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 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 656 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 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
/*
 * Provides I2C support for Philips PNX010x/PNX4008 boards.
 *
 * Authors: Dennis Kovalev <dkovalev@ru.mvista.com>
 *	    Vitaly Wool <vwool@ru.mvista.com>
 *
 * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
 * the terms of the GNU General Public License version 2. This program
 * is licensed "as is" without any warranty of any kind, whether express
 * or implied.
 */

#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/timer.h>
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <linux/i2c-pnx.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/slab.h>

#include <mach/hardware.h>
#include <mach/i2c.h>

#define I2C_PNX_TIMEOUT		10 /* msec */
#define I2C_PNX_SPEED_KHZ	100
#define I2C_PNX_REGION_SIZE	0x100

static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
{
	while (timeout > 0 &&
			(ioread32(I2C_REG_STS(data)) & mstatus_active)) {
		mdelay(1);
		timeout--;
	}
	return (timeout <= 0);
}

static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
{
	while (timeout > 0 &&
			(ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
		mdelay(1);
		timeout--;
	}
	return (timeout <= 0);
}

static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
{
	struct timer_list *timer = &alg_data->mif.timer;
	unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT);

	if (expires <= 1)
		expires = 2;

	del_timer_sync(timer);

	dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n",
		jiffies, expires);

	timer->expires = jiffies + expires;
	timer->data = (unsigned long)alg_data;

	add_timer(timer);
}

/**
 * i2c_pnx_start - start a device
 * @slave_addr:		slave address
 * @adap:		pointer to adapter structure
 *
 * Generate a START signal in the desired mode.
 */
static int i2c_pnx_start(unsigned char slave_addr,
	struct i2c_pnx_algo_data *alg_data)
{
	dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__,
		slave_addr, alg_data->mif.mode);

	/* Check for 7 bit slave addresses only */
	if (slave_addr & ~0x7f) {
		dev_err(&alg_data->adapter.dev,
			"%s: Invalid slave address %x. Only 7-bit addresses are supported\n",
			alg_data->adapter.name, slave_addr);
		return -EINVAL;
	}

	/* First, make sure bus is idle */
	if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
		/* Somebody else is monopolizing the bus */
		dev_err(&alg_data->adapter.dev,
			"%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
			alg_data->adapter.name, slave_addr,
			ioread32(I2C_REG_CTL(alg_data)),
			ioread32(I2C_REG_STS(alg_data)));
		return -EBUSY;
	} else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
		/* Sorry, we lost the bus */
		dev_err(&alg_data->adapter.dev,
		        "%s: Arbitration failure. Slave addr = %02x\n",
			alg_data->adapter.name, slave_addr);
		return -EIO;
	}

	/*
	 * OK, I2C is enabled and we have the bus.
	 * Clear the current TDI and AFI status flags.
	 */
	iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
		  I2C_REG_STS(alg_data));

	dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__,
		(slave_addr << 1) | start_bit | alg_data->mif.mode);

	/* Write the slave address, START bit and R/W bit */
	iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
		  I2C_REG_TX(alg_data));

	dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__);

	return 0;
}

/**
 * i2c_pnx_stop - stop a device
 * @adap:		pointer to I2C adapter structure
 *
 * Generate a STOP signal to terminate the master transaction.
 */
static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data)
{
	/* Only 1 msec max timeout due to interrupt context */
	long timeout = 1000;

	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	/* Write a STOP bit to TX FIFO */
	iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));

	/* Wait until the STOP is seen. */
	while (timeout > 0 &&
	       (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) {
		/* may be called from interrupt context */
		udelay(1);
		timeout--;
	}

	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));
}

/**
 * i2c_pnx_master_xmit - transmit data to slave
 * @adap:		pointer to I2C adapter structure
 *
 * Sends one byte of data to the slave
 */
static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
{
	u32 val;

	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	if (alg_data->mif.len > 0) {
		/* We still have something to talk about... */
		val = *alg_data->mif.buf++;

		if (alg_data->mif.len == 1)
			val |= stop_bit;

		alg_data->mif.len--;
		iowrite32(val, I2C_REG_TX(alg_data));

		dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n",
			__func__, val, alg_data->mif.len + 1);

		if (alg_data->mif.len == 0) {
			if (alg_data->last) {
				/* Wait until the STOP is seen. */
				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
					dev_err(&alg_data->adapter.dev,
						"The bus is still active after timeout\n");
			}
			/* Disable master interrupts */
			iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
				~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
				  I2C_REG_CTL(alg_data));

			del_timer_sync(&alg_data->mif.timer);

			dev_dbg(&alg_data->adapter.dev,
				"%s(): Waking up xfer routine.\n",
				__func__);

			complete(&alg_data->mif.complete);
		}
	} else if (alg_data->mif.len == 0) {
		/* zero-sized transfer */
		i2c_pnx_stop(alg_data);

		/* Disable master interrupts. */
		iowrite32(ioread32(