diff mbox

input: Add Atmel maXTouch touchscreen driver

Message ID 4CDD4BBA.5070301@atmel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Iiro Valkonen Nov. 12, 2010, 2:14 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 06ea8da..a0cec0d 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -395,6 +395,19 @@  config TOUCHSCREEN_TOUCHWIN
 	  To compile this driver as a module, choose M here: the
 	  module will be called touchwin.
 
+config TOUCHSCREEN_ATMEL_MAXTOUCH
+ 	tristate "Atmel maXTouch based touchscreen: I2C Interface"
+ 	depends on I2C
+ 	help
+ 	  Say Y here if you have a touchscreen interface using an
+ 	  Amel maXTouch controller, and your board-specific initialization
+ 	  code includes that in its table of I2C devices.
+
+ 	  If unsure, say N (but it's safe to say "Y").
+
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called maXTouch.
+
 config TOUCHSCREEN_ATMEL_TSADCC
 	tristate "Atmel Touchscreen Interface"
 	depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 7cc1b4f..861941d 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -12,6 +12,7 @@  obj-$(CONFIG_TOUCHSCREEN_AD7879)	+= ad7879.o
 obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C)	+= ad7879-i2c.o
 obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI)	+= ad7879-spi.o
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
+obj-$(CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH)+= atmel_maxtouch.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_BU21013)       += bu21013_ts.o
diff --git a/drivers/input/touchscreen/atmel_maxtouch.c b/drivers/input/touchscreen/atmel_maxtouch.c
new file mode 100644
index 0000000..cf22f65
--- /dev/null
+++ b/drivers/input/touchscreen/atmel_maxtouch.c
@@ -0,0 +1,2104 @@ 
+/*
+ *  Atmel maXTouch Touchscreen Controller Driver
+ *
+ *
+ *  Copyright (C) 2010 Atmel Corporation
+ *  Copyright (C) 2010 Ulf Samuelsson (ulf@atmel.com)
+ *  Copyright (C) 2009 Raphael Derosso Pereira <raphaelpereira@gmail.com>
+ *
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *
+ * Driver for Atmel maXTouch family of touch controllers.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/debugfs.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <linux/uaccess.h>
+
+#include <linux/atmel_maxtouch.h>
+
+
+#define DRIVER_VERSION "0.91a"
+
+static int debug = DEBUG_TRACE;
+/* Defaul comms mode = 0 */
+static int comms;
+module_param(debug, int, 0644);
+module_param(comms, int, 0644);
+
+MODULE_PARM_DESC(debug, "Activate debugging output");
+MODULE_PARM_DESC(comms, "Select communications mode");
+
+/* Device Info descriptor */
+/* Parsed from maXTouch "Id information" inside device */
+struct mxt_device_info {
+	u8   family_id;
+	u8   variant_id;
+	u8   major;
+	u8   minor;
+	u8   build;
+	u8   num_objs;
+	u8   x_size;
+	u8   y_size;
+	char family_name[16];	 /* Family name */
+	char variant_name[16];    /* Variant name */
+	u16  num_nodes;           /* Number of sensor nodes */
+};
+
+/* object descriptor table, parsed from maXTouch "object table" */
+struct mxt_object {
+	u16 chip_addr;
+	u8  type;
+	u8  size;
+	u8  instances;
+	u8  num_report_ids;
+};
+
+
+/* Mapping from report id to object type and instance */
+struct report_id_map {
+	u8  object;
+	u8  instance;
+/*
+ * This is the first report ID belonging to object. It enables us to
+ * find out easily the touch number: each touch has different report
+ * ID (which are assigned to touches in increasing order). By
+ * subtracting the first report ID from current, we get the touch
+ * number.
+ */
+	u8  first_rid;
+};
+
+
+/* Driver datastructure */
+struct mxt_data {
+	struct i2c_client    *client;
+	struct input_dev     *input;
+	char                 phys_name[32];
+	int                  irq;
+
+	u16                  last_read_addr;
+	bool                 new_msgs;
+	u8                   *last_message;
+
+	int                  valid_irq_counter;
+	int                  invalid_irq_counter;
+	int                  irq_counter;
+	int                  message_counter;
+	int                  read_fail_counter;
+
+
+	int                  bytes_to_read;
+
+	struct delayed_work  dwork;
+	u8                   xpos_format;
+	u8                   ypos_format;
+
+	u8                   numtouch;
+
+	struct mxt_device_info	device_info;
+
+	u32		     info_block_crc;
+	u32                  configuration_crc;
+	u16                  report_id_count;
+	struct report_id_map *rid_map;
+	struct mxt_object    *object_table;
+
+	u16                  msg_proc_addr;
+	u8                   message_size;
+
+	u16                  max_x_val;
+	u16                  max_y_val;
+
+	void                 (*init_hw)(void);
+	void                 (*exit_hw)(void);
+	u8                   (*valid_interrupt)(void);
+	u8                   (*read_chg)(void);
+
+	/* debugfs variables */
+	struct dentry        *debug_dir;
+	int                  current_debug_datap;
+
+	struct mutex         debug_mutex;
+	u16                  *debug_data;
+
+	/* Character device variables */
+	struct cdev          cdev;
+	struct cdev          cdev_messages;  /* 2nd Char dev for messages */
+	dev_t                dev_num;
+	struct class         *mxt_class;
+
+
+	u16                  address_pointer;
+	bool                 valid_ap;
+
+	/* Message buffer & pointers */
+	char                 *messages;
+	int                  msg_buffer_startp, msg_buffer_endp;
+
+	/* Put only non-touch messages to buffer if this is set */
+	char                 nontouch_msg_only;
+	struct mutex         msg_mutex;
+};
+
+#define I2C_RETRY_COUNT 5
+#define I2C_PAYLOAD_SIZE 254
+
+/* Returns the start address of object in mXT memory. */
+#define	MXT_BASE_ADDR(object_type, mxt)					\
+	get_object_address(object_type, 0, mxt->object_table,           \
+			   mxt->device_info.num_objs)
+
+/* Maps a report ID to an object type (object type number). */
+#define	REPORT_ID_TO_OBJECT(rid, mxt)			\
+	(((rid) == 0xff) ? 0 : mxt->rid_map[rid].object)
+
+/* Maps a report ID to an object type (string). */
+#define	REPORT_ID_TO_OBJECT_NAME(rid, mxt)			\
+	object_type_name[REPORT_ID_TO_OBJECT(rid, mxt)]
+
+/* Returns non-zero if given object is a touch object */
+#define IS_TOUCH_OBJECT(object) \
+	((object == MXT_TOUCH_MULTITOUCHSCREEN_T9) || \
+	 (object == MXT_TOUCH_KEYARRAY_T15) ||	\
+	 (object == MXT_TOUCH_PROXIMITY_T23) || \
+	 (object == MXT_TOUCH_SINGLETOUCHSCREEN_T10) || \
+	 (object == MXT_TOUCH_XSLIDER_T11) || \
+	 (object == MXT_TOUCH_YSLIDER_T12) || \
+	 (object == MXT_TOUCH_XWHEEL_T13) || \
+	 (object == MXT_TOUCH_YWHEEL_T14) || \
+	 (object == MXT_TOUCH_KEYSET_T31) || \
+	 (object == MXT_TOUCH_XSLIDERSET_T32) ? 1 : 0)
+
+#define mxt_debug(level, ...) \
+	do { \
+		if (debug >= (level)) \
+			pr_debug(__VA_ARGS__); \
+	} while (0)
+
+
+/*
+ * Check whether we have multi-touch enabled kernel; if not, report just the
+ * first touch (on mXT224, the maximum is 10 simultaneous touches).
+ * Because just the 1st one is reported, it might seem that the screen is not
+ * responding to touch if the first touch is removed while the screen is being
+ * touched by another finger, so beware.
+ *
+ */
+
+#ifdef ABS_MT_TRACKING_ID
+static inline void report_mt(int touch_number, int size, int x, int y,
+			     struct mxt_data *mxt) {
+	input_report_abs(mxt->input, ABS_MT_TRACKING_ID, touch_number);
+	input_report_abs(mxt->input, ABS_MT_TOUCH_MAJOR, size);
+	input_report_abs(mxt->input, ABS_MT_POSITION_X, x);
+	input_report_abs(mxt->input, ABS_MT_POSITION_Y, y);
+	input_mt_sync(mxt->input);
+}
+#else
+static inline void report_mt(int touch_number, int size, int x, int y,
+			     struct mxt_data *mxt) {
+	if (touch_number == 0) {
+		input_report_abs(mxt->input, ABS_TOOL_WIDTH, size);
+		input_report_abs(mxt->input, ABS_X, x);
+		input_report_abs(mxt->input, ABS_Y, y);
+	}
+}
+#endif
+
+
+static inline void report_gesture(int data, struct mxt_data *mxt)
+{
+	input_event(mxt->input, EV_MSC, MSC_GESTURE, data);
+}
+
+
+static const u8	*object_type_name[] = {
+	[0]  = "Reserved",
+	[5]  = "GEN_MESSAGEPROCESSOR_T5",
+	[6]  = "GEN_COMMANDPROCESSOR_T6",
+	[7]  = "GEN_POWERCONFIG_T7",
+	[8]  = "GEN_ACQUIRECONFIG_T8",
+	[9]  = "TOUCH_MULTITOUCHSCREEN_T9",
+	[15] = "TOUCH_KEYARRAY_T15",
+	[17] = "SPT_COMMSCONFIG_T18",
+	[19] = "SPT_GPIOPWM_T19",
+	[20] = "PROCI_GRIPFACESUPPRESSION_T20",
+	[22] = "PROCG_NOISESUPPRESSION_T22",
+	[23] = "TOUCH_PROXIMITY_T23",
+	[24] = "PROCI_ONETOUCHGESTUREPROCESSOR_T24",
+	[25] = "SPT_SELFTEST_T25",
+	[27] = "PROCI_TWOTOUCHGESTUREPROCESSOR_T27",
+	[28] = "SPT_CTECONFIG_T28",
+	[37] = "DEBUG_DIAGNOSTICS_T37",
+	[38] = "SPT_USER_DATA_T38",
+	[40] = "PROCI_GRIPSUPPRESSION_T40",
+	[41] = "PROCI_PALMSUPPRESSION_T41",
+	[42] = "PROCI_FACESUPPRESSION_T42",
+	[43] = "SPT_DIGITIZER_T43",
+	[44] = "SPT_MESSAGECOUNT_T44",
+};
+
+
+static u16 get_object_address(uint8_t object_type,
+			      uint8_t instance,
+			      struct mxt_object *object_table,
+			      int max_objs);
+
+static int mxt_write_ap(struct mxt_data *mxt, u16 ap);
+
+static int mxt_read_block_wo_addr(struct i2c_client *client,
+				  u16 length,
+				  u8 *value);
+
+ssize_t debug_data_read(struct mxt_data *mxt, char *buf, size_t count,
+			loff_t *ppos, u8 debug_command)
+{
+	int i;
+	u16 *data;
+	u16 diagnostics_reg;
+	int offset = 0;
+	int size;
+	int read_size;
+	int error;
+	char *buf_start;
+	u16 debug_data_addr;
+	u16 page_address;
+	u8 page;
+	u8 debug_command_reg;
+
+	data = mxt->debug_data;
+	if (data == NULL)
+		return -EIO;
+
+	/* If first read after open, read all data to buffer. */
+	if (mxt->current_debug_datap == 0) {
+		diagnostics_reg =
+			MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6, mxt) +
+			MXT_ADR_T6_DIAGNOSTIC;
+		if (count > (mxt->device_info.num_nodes * 2))
+			count = mxt->device_info.num_nodes;
+		debug_data_addr =
+			MXT_BASE_ADDR(MXT_DEBUG_DIAGNOSTIC_T37, mxt) +
+			MXT_ADR_T37_DATA;
+		page_address = MXT_BASE_ADDR(MXT_DEBUG_DIAGNOSTIC_T37, mxt) +
+			       MXT_ADR_T37_PAGE;
+		error = mxt_read_block(mxt->client, page_address, 1, &page);
+		if (error < 0)
+			return error;
+		mxt_debug(DEBUG_TRACE, "debug data page = %d\n", page);
+		while (page != 0) {
+			error = mxt_write_byte(mxt->client,
+					diagnostics_reg,
+					MXT_CMD_T6_PAGE_DOWN);
+			if (error < 0)
+				return error;
+			/* Wait for command to be handled; when it has, the
+			   register will be cleared. */
+			debug_command_reg = 1;
+			while (debug_command_reg != 0) {
+				error = mxt_read_block(mxt->client,
+						diagnostics_reg, 1,
+						&debug_command_reg);
+				if (error < 0)
+					return error;
+				mxt_debug(DEBUG_TRACE,
+					"Waiting for debug diag command "
+					"to propagate...\n");
+
+			}
+			error = mxt_read_block(mxt->client, page_address, 1,
+					       &page);
+			if (error < 0)
+				return error;
+			mxt_debug(DEBUG_TRACE, "debug data page = %d\n", page);
+		}
+
+		/*
+		 * Lock mutex to prevent writing some unwanted data to debug
+		 * command register. User can still write through the char
+		 * device interface though. TODO: fix?
+		 */
+
+		mutex_lock(&mxt->debug_mutex);
+		/* Configure Debug Diagnostics object to show deltas/refs */
+		error = mxt_write_byte(mxt->client, diagnostics_reg,
+				debug_command);
+
+		/* Wait for command to be handled; when it has, the
+		 * register will be cleared. */
+		debug_command_reg = 1;
+		while (debug_command_reg != 0) {
+			error = mxt_read_block(mxt->client,
+					diagnostics_reg, 1,
+					&debug_command_reg);
+			if (error < 0)
+				return error;
+			mxt_debug(DEBUG_TRACE, "Waiting for debug diag command "
+				"to propagate...\n");
+		}
+
+		if (error < 0) {
+			printk(KERN_WARNING
+				"Error writing to maXTouch device!\n");
+			return error;
+		}
+
+		size = mxt->device_info.num_nodes * sizeof(u16);
+
+		while (size > 0) {
+			read_size = size > 128 ? 128 : size;
+			mxt_debug(DEBUG_TRACE,
+				"Debug data read loop, reading %d bytes...\n",
+				read_size);
+			error = mxt_read_block(mxt->client,
+					       debug_data_addr,
+					       read_size,
+					       (u8 *) &data[offset]);
+			if (error < 0) {
+				printk(KERN_WARNING
+					"Error reading debug data\n");
+				goto error;
+			}
+			offset += read_size/2;
+			size -= read_size;
+
+			/* Select next page */
+			error = mxt_write_byte(mxt->client, diagnostics_reg,
+					MXT_CMD_T6_PAGE_UP);
+			if (error < 0) {
+				printk(KERN_WARNING
+					"Error writing to maXTouch device!\n");
+				goto error;
+			}
+		}
+		mutex_unlock(&mxt->debug_mutex);
+	}
+
+	buf_start = buf;
+	i = mxt->current_debug_datap;
+
+	while (((buf - buf_start) < (count - 6)) &&
+		(i < mxt->device_info.num_nodes)) {
+
+		mxt->current_debug_datap++;
+		if (debug_command == MXT_CMD_T6_REFERENCES_MODE)
+			buf += sprintf(buf, "%d: %5d\n", i,
+				       (u16) le16_to_cpu(data[i]));
+		else if (debug_command == MXT_CMD_T6_DELTAS_MODE)
+			buf += sprintf(buf, "%d: %5d\n", i,
+				       (s16) le16_to_cpu(data[i]));
+		i++;
+	}
+
+	return buf - buf_start;
+error:
+	mutex_unlock(&mxt->debug_mutex);
+	return error;
+}
+
+ssize_t deltas_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+	return debug_data_read(file->private_data, buf, count, ppos,
+			       MXT_CMD_T6_DELTAS_MODE);
+}
+
+ssize_t refs_read(struct file *file, char *buf, size_t count,
+			loff_t *ppos)
+{
+	return debug_data_read(file->private_data, buf, count, ppos,
+			       MXT_CMD_T6_REFERENCES_MODE);
+}
+
+int debug_data_open(struct inode *inode, struct file *file)
+{
+	struct mxt_data *mxt;
+	int i;
+	mxt = inode->i_private;
+	if (mxt == NULL)
+		return -EIO;
+	mxt->current_debug_datap = 0;
+	mxt->debug_data = kmalloc(mxt->device_info.num_nodes * sizeof(u16),
+				  GFP_KERNEL);
+	if (mxt->debug_data == NULL)
+		return -ENOMEM;
+	for (i = 0; i < mxt->device_info.num_nodes; i++)
+		mxt->debug_data[i] = 7777;
+	file->private_data = mxt;
+	return 0;
+}
+
+int debug_data_release(struct inode *inode, struct file *file)
+{
+	struct mxt_data *mxt;
+	mxt = file->private_data;
+	kfree(mxt->debug_data);
+	return 0;
+}
+
+static const struct file_operations delta_fops = {
+	.owner = THIS_MODULE,
+	.open = debug_data_open,
+	.release = debug_data_release,
+	.read = deltas_read,
+};
+
+static const struct file_operations refs_fops = {
+	.owner = THIS_MODULE,
+	.open = debug_data_open,
+	.release = debug_data_release,
+	.read = refs_read,
+};
+
+
+int mxt_memory_open(struct inode *inode, struct file *file)
+{
+	struct mxt_data *mxt;
+	mxt = container_of(inode->i_cdev, struct mxt_data, cdev);
+	if (mxt == NULL)
+		return -EIO;
+	file->private_data = mxt;
+	return 0;
+}
+
+int mxt_message_open(struct inode *inode, struct file *file)
+{
+	struct mxt_data *mxt;
+	mxt = container_of(inode->i_cdev, struct mxt_data, cdev_messages);
+	if (mxt == NULL)
+		return -EIO;
+	file->private_data = mxt;
+	return 0;
+}
+
+ssize_t mxt_memory_read(struct file *file, char *buf, size_t count,
+			loff_t *ppos)
+{
+	int i;
+	struct mxt_data *mxt;
+
+	mxt = file->private_data;
+	if (mxt->valid_ap) {
+		mxt_debug(DEBUG_TRACE, "Reading %d bytes from current ap\n",
+			(int) count);
+		i = mxt_read_block_wo_addr(mxt->client, count, (u8 *) buf);
+	} else {
+		mxt_debug(DEBUG_TRACE, "Address pointer changed since set;"
+			"writing AP (%d) before reading %d bytes",
+			mxt->address_pointer, (int) count);
+		i = mxt_read_block(mxt->client, mxt->address_pointer, count,
+				buf);
+	}
+
+	return i;
+}
+
+ssize_t mxt_memory_write(struct file *file, const char *buf, size_t count,
+			 loff_t *ppos)
+{
+	int i;
+	int whole_blocks;
+	int last_block_size;
+	struct mxt_data *mxt;
+	u16 address;
+
+	mxt = file->private_data;
+	address = mxt->address_pointer;
+
+	mxt_debug(DEBUG_TRACE, "mxt_memory_write entered\n");
+	whole_blocks = count / I2C_PAYLOAD_SIZE;
+	last_block_size = count % I2C_PAYLOAD_SIZE;
+
+	for (i = 0; i < whole_blocks; i++) {
+		mxt_debug(DEBUG_TRACE, "About to write to %d...",
+			address);
+		mxt_write_block(mxt->client, address, I2C_PAYLOAD_SIZE,
+				(u8 *) buf);
+		address += I2C_PAYLOAD_SIZE;
+		buf += I2C_PAYLOAD_SIZE;
+	}
+
+	mxt_write_block(mxt->client, address, last_block_size, (u8 *) buf);
+
+	return count;
+}
+
+static int mxt_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	int retval;
+	struct mxt_data *mxt;
+
+	retval = 0;
+	mxt = file->private_data;
+
+	switch (cmd) {
+	case MXT_SET_ADDRESS_IOCTL:
+		retval = mxt_write_ap(mxt, (u16) arg);
+		if (retval >= 0) {
+			mxt->address_pointer = (u16) arg;
+			mxt->valid_ap = 1;
+		}
+		break;
+	case MXT_RESET_IOCTL:
+		retval = mxt_write_byte(mxt->client,
+			      MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6, mxt) +
+			      MXT_ADR_T6_RESET,
+			      1);
+		break;
+	case MXT_CALIBRATE_IOCTL:
+		retval = mxt_write_byte(mxt->client,
+			      MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6, mxt) +
+			      MXT_ADR_T6_CALIBRATE,
+			      1);
+
+		break;
+	case MXT_BACKUP_IOCTL:
+		retval = mxt_write_byte(mxt->client,
+			      MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6, mxt) +
+			      MXT_ADR_T6_BACKUPNV,
+			      MXT_CMD_T6_BACKUP);
+		break;
+	case MXT_NONTOUCH_MSG_IOCTL:
+		mxt->nontouch_msg_only = 1;
+		break;
+	case MXT_ALL_MSG_IOCTL:
+		mxt->nontouch_msg_only = 0;
+		break;
+	default:
+		return -EIO;
+	}
+
+	return retval;
+}
+
+/*
+ * Copies messages from buffer to user space.
+ *
+ * NOTE: if less than (mxt->message_size * 5 + 1) bytes requested,
+ * this will return 0!
+ *
+ */
+ssize_t mxt_message_read(struct file *file, char *buf, size_t count,
+			 loff_t *ppos)
+{
+	int i;
+	struct mxt_data *mxt;
+	char *buf_start;
+
+	mxt = file->private_data;
+	if (mxt == NULL)
+		return -EIO;
+	buf_start = buf;
+
+	mutex_lock(&mxt->msg_mutex);
+	/* Copy messages until buffer empty, or 'count' bytes written */
+	while ((mxt->msg_buffer_startp != mxt->msg_buffer_endp) &&
+		((buf - buf_start) < (count - (5 * mxt->message_size) - 1))) {
+
+		for (i = 0; i < mxt->message_size; i++) {
+			buf += sprintf(buf, "[%2X] ",
+				*(mxt->messages + mxt->msg_buffer_endp *
+					mxt->message_size + i));
+		}
+		buf += sprintf(buf, "\n");
+		if (mxt->msg_buffer_endp < MXT_MESSAGE_BUFFER_SIZE)
+			mxt->msg_buffer_endp++;
+		else
+			mxt->msg_buffer_endp = 0;
+	}
+	mutex_unlock(&mxt->msg_mutex);
+	return buf - buf_start;
+}
+
+static const struct file_operations mxt_message_fops = {
+	.owner = THIS_MODULE,
+	.open = mxt_message_open,
+	.read = mxt_message_read,
+};
+
+static const struct file_operations mxt_memory_fops = {
+	.owner = THIS_MODULE,
+	.open = mxt_memory_open,
+	.read = mxt_memory_read,
+	.write = mxt_memory_write,
+	.unlocked_ioctl = mxt_ioctl,
+};
+
+
+/* Writes the address pointer (to set up following reads). */
+
+int mxt_write_ap(struct mxt_data *mxt, u16 ap)
+{
+	struct i2c_client *client;
+	__le16	le_ap = cpu_to_le16(ap);
+	client = mxt->client;
+	if (mxt != NULL)
+		mxt->last_read_addr = -1;
+	if (i2c_master_send(client, (u8 *) &le_ap, 2) == 2) {
+		mxt_debug(DEBUG_TRACE, "Address pointer set to %d\n", ap);
+		return 0;
+	} else {
+		mxt_debug(DEBUG_INFO, "Error writing address pointer!\n");
+		return -EIO;
+	}
+}
+
+
+
+/* Calculates the 24-bit CRC sum. */
+static u32 CRC_24(u32 crc, u8 byte1, u8 byte2)
+{
+	static const u32 crcpoly = 0x80001B;
+	u32 result;
+	u32 data_word;
+
+	data_word = ((((u16) byte2) << 8u) | byte1);
+	result = ((crc << 1u) ^ data_word);
+	if (result & 0x1000000)
+		result ^= crcpoly;
+	return result;
+}
+
+/* Returns object address in mXT chip, or zero if object is not found */
+static u16 get_object_address(uint8_t object_type,
+			      uint8_t instance,
+			      struct mxt_object *object_table,
+			      int max_objs)
+{
+	uint8_t object_table_index = 0;
+	uint8_t address_found = 0;
+	uint16_t address = 0;
+	struct mxt_object *obj;
+
+	while ((object_table_index < max_objs) && !address_found) {
+		obj = &object_table[object_table_index];
+		if (obj->type == object_type) {
+			address_found = 1;
+			/* Are there enough instances defined in the FW? */
+			if (obj->instances >= instance) {
+				address = obj->chip_addr +
+					  (obj->size + 1) * instance;
+			} else {
+				return 0;
+			}
+		}
+		object_table_index++;
+	}
+	return address;
+}
+
+
+/*
+ * Reads a block of bytes from given address from mXT chip. If we are
+ * reading from message window, and previous read was from message window,
+ * there's no need to write the address pointer: the mXT chip will
+ * automatically set the address pointer back to message window start.
+ */
+
+static int mxt_read_block(struct i2c_client *client,
+		   u16 addr,
+		   u16 length,
+		   u8 *value)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	struct i2c_msg msg[2];
+	__le16	le_addr;
+	struct mxt_data *mxt;
+
+	mxt = i2c_get_clientdata(client);
+
+	if (mxt != NULL) {
+		if ((mxt->last_read_addr == addr) &&
+			(addr == mxt->msg_proc_addr)) {
+			if  (i2c_master_recv(client, value, length) == length)
+				return length;
+			else
+				return -EIO;
+		} else {
+			mxt->last_read_addr = addr;
+		}
+	}
+
+	mxt_debug(DEBUG_TRACE, "Writing address pointer & reading %d bytes "
+		"in on i2c transaction...\n", length);
+
+	le_addr = cpu_to_le16(addr);
+	msg[0].addr  = client->addr;
+	msg[0].flags = 0x00;
+	msg[0].len   = 2;
+	msg[0].buf   = (u8 *) &le_addr;
+
+	msg[1].addr  = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len   = length;
+	msg[1].buf   = (u8 *) value;
+	if  (i2c_transfer(adapter, msg, 2) == 2)
+		return length;
+	else
+		return -EIO;
+
+}
+
+/* Reads a block of bytes from current address from mXT chip. */
+
+static int mxt_read_block_wo_addr(struct i2c_client *client,
+			   u16 length,
+			   u8 *value)
+{
+
+
+	if  (i2c_master_recv(client, value, length) == length) {
+		mxt_debug(DEBUG_TRACE, "I2C block read ok\n");
+		return length;
+	} else {
+		mxt_debug(DEBUG_INFO, "I2C block read failed\n");
+		return -EIO;
+	}
+
+}
+
+
+/* Writes one byte to given address in mXT chip. */
+
+static int mxt_write_byte(struct i2c_client *client, u16 addr, u8 value)
+{
+	struct {
+		__le16 le_addr;
+		u8 data;
+
+	} i2c_byte_transfer;
+
+	struct mxt_data *mxt;
+
+	mxt = i2c_get_clientdata(client);
+	if (mxt != NULL)
+		mxt->last_read_addr = -1;
+	i2c_byte_transfer.le_addr = cpu_to_le16(addr);
+	i2c_byte_transfer.data = value;
+	if  (i2c_master_send(client, (u8 *) &i2c_byte_transfer, 3) == 3)
+		return 0;
+	else
+		return -EIO;
+}
+
+
+/* Writes a block of bytes (max 256) to given address in mXT chip. */
+static int mxt_write_block(struct i2c_client *client,
+		    u16 addr,
+		    u16 length,
+		    u8 *value)
+{
+	int i;
+	struct {
+		__le16	le_addr;
+		u8	data[256];
+
+	} i2c_block_transfer;
+
+	struct mxt_data *mxt;
+
+	mxt_debug(DEBUG_TRACE, "Writing %d bytes to %d...", length, addr);
+	if (length > 256)
+		return -EINVAL;
+	mxt = i2c_get_clientdata(client);
+	if (mxt != NULL)
+		mxt->last_read_addr = -1;
+	for (i = 0; i < length; i++)
+		i2c_block_transfer.data[i] = *value++;
+	i2c_block_transfer.le_addr = cpu_to_le16(addr);
+	i = i2c_master_send(client, (u8 *) &i2c_block_transfer, length + 2);
+	if (i == (length + 2))
+		return length;
+	else
+		return -EIO;
+}
+
+/* Calculates the CRC value for mXT infoblock. */
+int calculate_infoblock_crc(u32 *crc_result, u8 *data, int crc_area_size)
+{
+	u32 crc = 0;
+	int i;
+
+	for (i = 0; i < (crc_area_size - 1); i = i + 2)
+		crc = CRC_24(crc, *(data + i), *(data + i + 1));
+	/* If uneven size, pad with zero */
+	if (crc_area_size & 0x0001)
+		crc = CRC_24(crc, *(data + i), 0);
+	/* Return only 24 bits of CRC. */
+	*crc_result = (crc & 0x00FFFFFF);
+
+	return 0;
+}
+
+/* Processes a touchscreen message. */
+void process_T9_message(u8 *message, struct mxt_data *mxt, int last_touch)
+{
+
+	struct	input_dev *input;
+	u8  status;
+	u16 xpos = 0xFFFF;
+	u16 ypos = 0xFFFF;
+	u8  touch_size = 255;
+	u8  touch_number;
+	u8  amplitude;
+	u8  report_id;
+
+	static int stored_size[MXT_MAX_NUM_TOUCHES];
+	static int stored_x[MXT_MAX_NUM_TOUCHES];
+	static int stored_y[MXT_MAX_NUM_TOUCHES];
+	int i;
+	int active_touches = 0;
+	/*
+	 * If the 'last_touch' flag is set, we have received all the touch
+	 * messages there are available in this cycle, so send the events for
+	 * touches that are active.
+	 */
+	if (last_touch) {
+		/*
+		 * For compatibility with single-touch systems, send also
+		 * ABS_X & ABS_Y & BTN_TOUCH events.
+		 */
+		if (stored_size[0]) {
+			input_report_abs(mxt->input, BTN_TOUCH, 1);
+			input_report_abs(mxt->input, ABS_X, stored_x[0]);
+			input_report_abs(mxt->input, ABS_Y, stored_y[0]);
+		} else {
+			input_report_abs(mxt->input, BTN_TOUCH, 0);
+		}
+
+		for (i = 0; i < mxt->numtouch; i++) {
+			if (stored_size[i]) {
+				active_touches++;
+				input_report_abs(mxt->input,
+						ABS_MT_TRACKING_ID,
+						i);
+				input_report_abs(mxt->input,
+						ABS_MT_TOUCH_MAJOR,
+						stored_size[i]);
+				input_report_abs(mxt->input,
+						ABS_MT_POSITION_X,
+						stored_x[i]);
+				input_report_abs(mxt->input,
+						ABS_MT_POSITION_Y,
+						stored_y[i]);
+				input_mt_sync(mxt->input);
+			}
+		}
+		if (active_touches == 0)
+			input_mt_sync(mxt->input);
+		input_sync(mxt->input);
+	} else {
+		input = mxt->input;
+		status = message[MXT_MSG_T9_STATUS];
+		report_id = message[0];
+
+		if (status & MXT_MSGB_T9_SUPPRESS) {
+			/* Touch has been suppressed by grip/face */
+			/* detection                              */
+			mxt_debug(DEBUG_TRACE, "SUPRESS");
+		} else {
+			/* Put together the 10-/12-bit coordinate values. */
+			xpos = message[MXT_MSG_T9_XPOSMSB] * 16 +
+				((message[MXT_MSG_T9_XYPOSLSB] >> 4) & 0xF);
+			ypos = message[MXT_MSG_T9_YPOSMSB] * 16 +
+				((message[MXT_MSG_T9_XYPOSLSB] >> 0) & 0xF);
+
+			if (mxt->max_x_val < 1024)
+				xpos >>= 2;
+			if (mxt->max_y_val < 1024)
+				ypos >>= 2;
+
+			touch_number = message[MXT_MSG_REPORTID] -
+				mxt->rid_map[report_id].first_rid;
+
+			stored_x[touch_number] = xpos;
+			stored_y[touch_number] = ypos;
+
+			if (status & MXT_MSGB_T9_DETECT) {
+				/*
+				 * mXT224 reports the number of touched nodes,
+				 * so the exact value for touch ellipse major
+				 * axis length in nodes would be
+				 * 2*sqrt(touch_size/pi)
+				 * (assuming round touch shape), which would
+				 * then need to be scaled using information
+				 * about how many sensor lines we do have. So
+				 * this is very much simplified,
+				 * but sufficient for most if not all apps?
+				 */
+				touch_size = message[MXT_MSG_T9_TCHAREA];
+				touch_size = touch_size >> 2;
+				if (!touch_size)
+					touch_size = 1;
+				stored_size[touch_number] = touch_size;
+				if (status & MXT_MSGB_T9_AMP)
+					/* Amplitude of touch has changed */
+					amplitude =
+					    message[MXT_MSG_T9_TCHAMPLITUDE];
+			}
+
+			if (status & MXT_MSGB_T9_RELEASE) {
+				/* The previously reported touch has been
+				 * removed. */
+				stored_size[touch_number] = 0;
+			}
+		}
+
+		if (status & MXT_MSGB_T9_SUPPRESS) {
+			mxt_debug(DEBUG_TRACE, "SUPRESS");
+		} else {
+			if (status & MXT_MSGB_T9_DETECT) {
+				mxt_debug(DEBUG_TRACE, "DETECT:%s%s%s%s",
+					((status & MXT_MSGB_T9_PRESS) ?
+						" PRESS" : ""),
+					((status & MXT_MSGB_T9_MOVE) ?
+						" MOVE" : ""),
+					((status & MXT_MSGB_T9_AMP) ?
+						" AMP" : ""),
+					((status & MXT_MSGB_T9_VECTOR) ?
+						" VECT" : ""));
+			} else if (status & MXT_MSGB_T9_RELEASE) {
+				mxt_debug(DEBUG_TRACE, "RELEASE");
+			}
+		}
+		mxt_debug(DEBUG_TRACE, "X=%d, Y=%d, TOUCHSIZE=%d",
+			xpos, ypos, touch_size);
+	}
+	return;
+}
+
+
+int process_message(u8 *message, u8 object, struct mxt_data *mxt)
+{
+	struct i2c_client *client;
+	u8  status;
+	u16 xpos = 0xFFFF;
+	u16 ypos = 0xFFFF;
+	u8  event;
+	u8  direction;
+	u16 distance;
+	u8  length;
+	u8  report_id;
+	static u8 error_cond;
+
+	client = mxt->client;
+	length = mxt->message_size;
+	report_id = message[0];
+
+	if ((mxt->nontouch_msg_only == 0) ||
+	    (!IS_TOUCH_OBJECT(object))) {
+		mutex_lock(&mxt->msg_mutex);
+		/* Copy the message to buffer */
+		if (mxt->msg_buffer_startp < MXT_MESSAGE_BUFFER_SIZE)
+			mxt->msg_buffer_startp++;
+		else
+			mxt->msg_buffer_startp = 0;
+		if (mxt->msg_buffer_startp == mxt->msg_buffer_endp) {
+			mxt_debug(DEBUG_TRACE,
+				  "Message buf full, discarding last entry.\n");
+			if (mxt->msg_buffer_endp < MXT_MESSAGE_BUFFER_SIZE)
+				mxt->msg_buffer_endp++;
+			else
+				mxt->msg_buffer_endp = 0;
+		}
+		memcpy((mxt->messages + mxt->msg_buffer_startp * length),
+		       message,
+		       length);
+		mutex_unlock(&mxt->msg_mutex);
+	}
+
+	switch (object) {
+	case MXT_GEN_COMMANDPROCESSOR_T6:
+		status = message[1];
+
+		if (status & MXT_MSGB_T6_COMSERR) {
+			if (!(error_cond & MXT_MSGB_T6_COMSERR)) {
+				dev_err(&client->dev,
+					"maXTouch checksum error\n");
+				error_cond |= MXT_MSGB_T6_COMSERR;
+			}
+		}
+		if (status & MXT_MSGB_T6_CFGERR) {
+			/*
+			 * Configuration error. A proper configuration
+			 * needs to be written to chip and backed up.
+			 */
+			if (!(error_cond & MXT_MSGB_T6_CFGERR)) {
+				dev_err(&client->dev,
+					"maXTouch configuration error\n");
+				error_cond |= MXT_MSGB_T6_CFGERR;
+			}
+		}
+		if (status & MXT_MSGB_T6_CAL) {
+			/* Calibration in action, no need to react */
+			dev_info(&client->dev,
+				"maXTouch calibration in progress\n");
+		}
+		if (status & MXT_MSGB_T6_SIGERR) {
+			/*
+			 * Signal acquisition error, something is seriously
+			 * wrong, not much we can in the driver to correct
+			 * this
+			 */
+			if (!(error_cond & MXT_MSGB_T6_SIGERR)) {
+				dev_err(&client->dev,
+					"maXTouch acquisition error\n");
+				error_cond |= MXT_MSGB_T6_SIGERR;
+			}
+		}
+		if (status & MXT_MSGB_T6_OFL) {
+			/*
+			 * Cycle overflow, the acquisition interval is too
+			 * short.
+			 */
+			dev_err(&client->dev,
+				"maXTouch cycle overflow\n");
+		}
+		if (status & MXT_MSGB_T6_RESET) {
+			/* Chip has reseted, no need to react. */
+			dev_info(&client->dev,
+				"maXTouch chip reset\n");
+		}
+		if (status == 0) {
+			/* Chip status back to normal. */
+			dev_info(&client->dev,
+				"maXTouch status normal\n");
+			error_cond = 0;
+		}
+		break;
+
+	case MXT_TOUCH_MULTITOUCHSCREEN_T9:
+		process_T9_message(message, mxt, 0);
+		break;
+
+	case MXT_SPT_GPIOPWM_T19:
+		if (debug >= DEBUG_TRACE)
+			dev_info(&client->dev,
+				"Receiving GPIO message\n");
+		break;
+
+	case MXT_PROCI_GRIPFACESUPPRESSION_T20:
+		if (debug >= DEBUG_TRACE)
+			dev_info(&client->dev,
+				"Receiving face suppression msg\n");
+		break;
+
+	case MXT_PROCG_NOISESUPPRESSION_T22:
+		if (debug >= DEBUG_TRACE)
+			dev_info(&client->dev,
+				"Receiving noise suppression msg\n");
+		status = message[MXT_MSG_T22_STATUS];
+		if (status & MXT_MSGB_T22_FHCHG) {
+			if (debug >= DEBUG_TRACE)
+				dev_info(&client->dev,
+					"maXTouch: Freq changed\n");
+		}
+		if (status & MXT_MSGB_T22_GCAFERR) {
+			if (debug >= DEBUG_TRACE)
+				dev_info(&client->dev,
+					"maXTouch: High noise "
+					"level\n");
+		}
+		if (status & MXT_MSGB_T22_FHERR) {
+			if (debug >= DEBUG_TRACE)
+				dev_info(&client->dev,
+					"maXTouch: Freq changed - "
+					"Noise level too high\n");
+		}
+		break;
+
+	case MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24:
+		if (debug >= DEBUG_TRACE)
+			dev_info(&client->dev,
+				"Receiving one-touch gesture msg\n");
+
+		event = message[MXT_MSG_T24_STATUS] & 0x0F;
+		xpos = message[MXT_MSG_T24_XPOSMSB] * 16 +
+			((message[MXT_MSG_T24_XYPOSLSB] >> 4) & 0x0F);
+		ypos = message[MXT_MSG_T24_YPOSMSB] * 16 +
+			((message[MXT_MSG_T24_XYPOSLSB] >> 0) & 0x0F);
+		if (mxt->max_x_val < 1024)
+			xpos >>= 2;
+		if (mxt->max_y_val < 1024)
+			ypos >>= 2;
+		direction = message[MXT_MSG_T24_DIR];
+		distance = message[MXT_MSG_T24_DIST] +
+			   (message[MXT_MSG_T24_DIST + 1] << 16);
+
+		report_gesture((event << 24) | (direction << 16) | distance,
+			mxt);
+		report_gesture((xpos << 16) | ypos, mxt);
+
+		break;
+
+	case MXT_SPT_SELFTEST_T25:
+		if (debug >= DEBUG_TRACE)
+			dev_info(&client->dev,
+				"Receiving Self-Test msg\n");
+
+		if (message[MXT_MSG_T25_STATUS] == MXT_MSGR_T25_OK) {
+			if (debug >= DEBUG_TRACE)
+				dev_info(&client->dev,
+					"maXTouch: Self-Test OK\n");
+
+		} else  {
+			dev_err(&client->dev,
+				"maXTouch: Self-Test Failed [%02x]:"
+				"{%02x,%02x,%02x,%02x,%02x}\n",
+				message[MXT_MSG_T25_STATUS],
+				message[MXT_MSG_T25_STATUS + 0],
+				message[MXT_MSG_T25_STATUS + 1],
+				message[MXT_MSG_T25_STATUS + 2],
+				message[MXT_MSG_T25_STATUS + 3],
+				message[MXT_MSG_T25_STATUS + 4]
+				);
+		}
+		break;
+
+	case MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27:
+		if (debug >= DEBUG_TRACE)
+			dev_info(&client->dev,
+				"Receiving 2-touch gesture message\n");
+
+		event = message[MXT_MSG_T27_STATUS] & 0xF0;
+		xpos = message[MXT_MSG_T27_XPOSMSB] * 16 +
+			((message[MXT_MSG_T27_XYPOSLSB] >> 4) & 0x0F);
+		ypos = message[MXT_MSG_T27_YPOSMSB] * 16 +
+			((message[MXT_MSG_T27_XYPOSLSB] >> 0) & 0x0F);
+		if (mxt->max_x_val < 1024)
+			xpos >>= 2;
+		if (mxt->max_y_val < 1024)
+			ypos >>= 2;
+
+		direction = message[MXT_MSG_T27_ANGLE];
+		distance = message[MXT_MSG_T27_SEPARATION] +
+			   (message[MXT_MSG_T27_SEPARATION + 1] << 16);
+
+		report_gesture((event << 24) | (direction << 16) | distance,
+			mxt);
+		report_gesture((xpos << 16) | ypos, mxt);
+
+
+		break;
+
+	case MXT_SPT_CTECONFIG_T28:
+		if (debug >= DEBUG_TRACE)
+			dev_info(&client->dev,
+				"Receiving CTE message...\n");
+		status = message[MXT_MSG_T28_STATUS];
+		if (status & MXT_MSGB_T28_CHKERR)
+			dev_err(&client->dev,
+				"maXTouch: Power-Up CRC failure\n");
+
+		break;
+	default:
+		if (debug >= DEBUG_TRACE)
+			dev_info(&client->dev,
+				"maXTouch: Unknown message!\n");
+
+		break;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Processes messages when the interrupt line (CHG) is asserted. Keeps
+ * reading messages until a message with report ID 0xFF is received,
+ * which indicates that there is no more new messages.
+ *
+ */
+
+static void mxt_worker(struct work_struct *work)
+{
+	struct	mxt_data *mxt;
+	struct	i2c_client *client;
+
+	u8	*message;
+	u16	message_length;
+	u16	message_addr;
+	u8	report_id;
+	u8	object;
+	int	error;
+	int	i;
+	char    *message_string;
+	char    *message_start;
+
+	message = NULL;
+	mxt = container_of(work, struct mxt_data, dwork.work);
+	disable_irq(mxt->irq);
+	client = mxt->client;
+	message_addr = mxt->msg_proc_addr;
+	message_length = mxt->message_size;
+
+	if (message_length < 256) {
+		message = kmalloc(message_length, GFP_KERNEL);
+		if (message == NULL) {
+			dev_err(&client->dev, "Error allocating memory\n");
+			return;
+		}
+	} else {
+		dev_err(&client->dev,
+			"Message length larger than 256 bytes not supported\n");
+		return;
+	}
+
+	mxt_debug("maXTouch worker active:\n");
+
+	do {
+		/* Read next message, reread on failure. */
+		/* This driver currently does not request messages with CRC
+		 * byte, so we can read one byte less than message_length. */
+		mxt->message_counter++;
+		for (i = 1; i < I2C_RETRY_COUNT; i++) {
+			error = mxt_read_block(client,
+					       message_addr,
+					       message_length - 1,
+					       message);
+			if (error >= 0)
+				break;
+			mxt->read_fail_counter++;
+			dev_err(&client->dev,
+				"Failure reading maxTouch device\n");
+		}
+		if (error < 0) {
+			kfree(message);
+			return;
+		}
+
+		if (mxt->address_pointer != message_addr)
+			mxt->valid_ap = 0;
+		report_id = message[0];
+
+		if (debug >= DEBUG_RAW) {
+			mxt_debug(DEBUG_RAW, "%s message [msg count: %08x]:",
+				  REPORT_ID_TO_OBJECT_NAME(report_id, mxt),
+				  mxt->message_counter
+			);
+			/* 5 characters per one byte */
+			message_string = kmalloc(message_length * 5,
+						 GFP_KERNEL);
+			if (message_string == NULL) {
+				dev_err(&client->dev,
+					"Error allocating memory\n");
+				kfree(message);
+				return;
+			}
+			message_start = message_string;
+			for (i = 0; i < message_length; i++) {
+				message_string +=
+					sprintf(message_string,
+						"0x%02X ", message[i]);
+			}
+			mxt_debug(DEBUG_RAW, "%s", message_start);
+			kfree(message_start);
+		}
+
+		if ((report_id != MXT_END_OF_MESSAGES) && (report_id != 0)) {
+			memcpy(mxt->last_message, message, message_length);
+			mxt->new_msgs = 1;
+			smp_wmb();
+			/* Get type of object and process the message */
+			object = mxt->rid_map[report_id].object;
+			process_message(message, object, mxt);
+		}
+
+		mxt_debug(DEBUG_TRACE, "chgline: %d\n", mxt->read_chg());
+	} while (comms ? (mxt->read_chg() == 0) :
+		((report_id != MXT_END_OF_MESSAGES) && (report_id != 0)));
+
+	/* All messages processed, send the events) */
+	process_T9_message(NULL, mxt, 1);
+
+	kfree(message);
+	enable_irq(mxt->irq);
+	/* Make sure we just didn't miss a interrupt. */
+	if (mxt->read_chg() == 0)
+		schedule_delayed_work(&mxt->dwork, 0);
+}
+
+
+/*
+ * The maXTouch device will signal the host about a new message by asserting
+ * the CHG line. This ISR schedules a worker routine to read the message when
+ * that happens.
+ */
+
+static irqreturn_t mxt_irq_handler(int irq, void *_mxt)
+{
+	struct mxt_data *mxt = _mxt;
+
+	mxt->irq_counter++;
+	if (mxt->valid_interrupt()) {
+		/* Send the signal only if falling edge generated the irq. */
+		cancel_delayed_work(&mxt->dwork);
+		schedule_delayed_work(&mxt->dwork, 0);
+		mxt->valid_irq_counter++;
+	} else {
+		mxt->invalid_irq_counter++;
+		return IRQ_NONE;
+	}
+
+	return IRQ_HANDLED;
+}
+
+
+
+/******************************************************************************/
+/* Initialization of driver                                                   */
+/******************************************************************************/
+
+static int __devinit mxt_identify(struct i2c_client *client,
+				  struct mxt_data *mxt,
+				  u8 *id_block_data)
+{
+	u8 buf[MXT_ID_BLOCK_SIZE];
+	int error;
+	int identified;
+
+	identified = 0;
+
+	/* Read Device info to check if chip is valid */
+	error = mxt_read_block(client, MXT_ADDR_INFO_BLOCK, MXT_ID_BLOCK_SIZE,
+			       (u8 *) buf);
+
+	if (error < 0) {
+		mxt->read_fail_counter++;
+		dev_err(&client->dev, "Failure accessing maXTouch device\n");
+		return -EIO;
+	}
+
+	memcpy(id_block_data, buf, MXT_ID_BLOCK_SIZE);
+
+	mxt->device_info.family_id  = buf[0];
+	mxt->device_info.variant_id = buf[1];
+	mxt->device_info.major	    = ((buf[2] >> 4) & 0x0F);
+	mxt->device_info.minor      = (buf[2] & 0x0F);
+	mxt->device_info.build	    = buf[3];
+	mxt->device_info.x_size	    = buf[4];
+	mxt->device_info.y_size	    = buf[5];
+	mxt->device_info.num_objs   = buf[6];
+	mxt->device_info.num_nodes  = mxt->device_info.x_size *
+				      mxt->device_info.y_size;
+
+	/*
+	 * Check Family & Variant Info; warn if not recognized but
+	 * still continue.
+	 */
+
+	/* MXT224 */
+	if (mxt->device_info.family_id == MXT224_FAMILYID) {
+		strcpy(mxt->device_info.family_name, "mXT224");
+
+		if (mxt->device_info.variant_id == MXT224_CAL_VARIANTID) {
+			strcpy(mxt->device_info.variant_name, "Calibrated");
+		} else if (mxt->device_info.variant_id ==
+			MXT224_UNCAL_VARIANTID) {
+			strcpy(mxt->device_info.variant_name, "Uncalibrated");
+		} else {
+			dev_err(&client->dev,
+				"Warning: maXTouch Variant ID [%d] not "
+				"supported\n",
+				mxt->device_info.variant_id);
+			strcpy(mxt->device_info.variant_name, "UNKNOWN");
+			/* identified = -ENXIO; */
+		}
+
+	/* MXT1386 */
+	} else if (mxt->device_info.family_id == MXT1386_FAMILYID) {
+		strcpy(mxt->device_info.family_name, "mXT1386");
+
+		if (mxt->device_info.variant_id == MXT1386_CAL_VARIANTID) {
+			strcpy(mxt->device_info.variant_name, "Calibrated");
+		} else {
+			dev_err(&client->dev,
+				"Warning: maXTouch Variant ID [%d] not "
+				"supported\n",
+				mxt->device_info.variant_id);
+			strcpy(mxt->device_info.variant_name, "UNKNOWN");
+			/* identified = -ENXIO; */
+		}
+	/* Unknown family ID! */
+	} else {
+		dev_err(&client->dev,
+			"Warning: maXTouch Family ID [%d] not supported\n",
+			mxt->device_info.family_id);
+		strcpy(mxt->device_info.family_name, "UNKNOWN");
+		strcpy(mxt->device_info.variant_name, "UNKNOWN");
+		/* identified = -ENXIO; */
+	}
+
+	dev_info(
+		&client->dev,
+		"Atmel maXTouch (Family %s (%X), Variant %s (%X)) Firmware "
+		"version [%d.%d] Build %d\n",
+		mxt->device_info.family_name,
+		mxt->device_info.family_id,
+		mxt->device_info.variant_name,
+		mxt->device_info.variant_id,
+		mxt->device_info.major,
+		mxt->device_info.minor,
+		mxt->device_info.build
+	);
+	dev_info(
+		&client->dev,
+		"Atmel maXTouch Configuration "
+		"[X: %d] x [Y: %d]\n",
+		mxt->device_info.x_size,
+		mxt->device_info.y_size
+	);
+	return identified;
+}
+
+/*
+ * Reads the object table from maXTouch chip to get object data like
+ * address, size, report id. For Info Block CRC calculation, already read
+ * id data is passed to this function too (Info Block consists of the ID
+ * block and object table).
+ *
+ */
+static int __devinit mxt_read_object_table(struct i2c_client *client,
+					   struct mxt_data *mxt,
+					   u8 *raw_id_data)
+{
+	u16	report_id_count;
+	u8	buf[MXT_OBJECT_TABLE_ELEMENT_SIZE];
+	u8      *raw_ib_data;
+	u8	object_type;
+	u16	object_address;
+	u16	object_size;
+	u8	object_instances;
+	u8	object_report_ids;
+	u16	object_info_address;
+	u32	crc;
+	u32     calculated_crc;
+	int	i;
+	int	error;
+
+	u8	object_instance;
+	u8	object_report_id;
+	u8	report_id;
+	int     first_report_id;
+	int     ib_pointer;
+	struct mxt_object *object_table;
+
+	mxt_debug(DEBUG_TRACE, "maXTouch driver reading configuration\n");
+
+	object_table = kzalloc(sizeof(struct mxt_object) *
+			       mxt->device_info.num_objs,
+			       GFP_KERNEL);
+	if (object_table == NULL) {
+		printk(KERN_WARNING "maXTouch: Memory allocation failed!\n");
+		error = -ENOMEM;
+		goto err_object_table_alloc;
+	}
+
+	raw_ib_data = kmalloc(MXT_OBJECT_TABLE_ELEMENT_SIZE *
+			mxt->device_info.num_objs + MXT_ID_BLOCK_SIZE,
+			GFP_KERNEL);
+	if (raw_ib_data == NULL) {
+		printk(KERN_WARNING "maXTouch: Memory allocation failed!\n");
+		error = -ENOMEM;
+		goto err_ib_alloc;
+	}
+
+	/* Copy the ID data for CRC calculation. */
+	memcpy(raw_ib_data, raw_id_data, MXT_ID_BLOCK_SIZE);
+	ib_pointer = MXT_ID_BLOCK_SIZE;
+
+	mxt->object_table = object_table;
+
+	mxt_debug(DEBUG_TRACE, "maXTouch driver Memory allocated\n");
+
+	object_info_address = MXT_ADDR_OBJECT_TABLE;
+
+	report_id_count = 0;
+	for (i = 0; i < mxt->device_info.num_objs; i++) {
+		mxt_debug(DEBUG_TRACE, "Reading maXTouch at [0x%04x]: ",
+			  object_info_address);
+
+		error = mxt_read_block(client, object_info_address,
+				       MXT_OBJECT_TABLE_ELEMENT_SIZE, buf);
+
+		if (error < 0) {
+			mxt->read_fail_counter++;
+			dev_err(&client->dev,
+				"maXTouch Object %d could not be read\n", i);
+			error = -EIO;
+			goto err_object_read;
+		}
+
+		memcpy(raw_ib_data + ib_pointer, buf,
+		       MXT_OBJECT_TABLE_ELEMENT_SIZE);
+		ib_pointer += MXT_OBJECT_TABLE_ELEMENT_SIZE;
+
+		object_type       =  buf[0];
+		object_address    = (buf[2] << 8) + buf[1];
+		object_size       =  buf[3] + 1;
+		object_instances  =  buf[4] + 1;
+		object_report_ids =  buf[5];
+		mxt_debug(DEBUG_TRACE, "Type=%03d, Address=0x%04x, "
+			  "Size=0x%02x, %d instances, %d report id's\n",
+			  object_type,
+			  object_address,
+			  object_size,
+			  object_instances,
+			  object_report_ids
+		);
+
+		/* TODO: check whether object is known and supported? */
+		/* Save frequently needed info. */
+		if (object_type == MXT_GEN_MESSAGEPROCESSOR_T5) {
+			mxt->msg_proc_addr = object_address;
+			mxt->message_size = object_size;
+		}
+
+		object_table[i].type            = object_type;
+		object_table[i].chip_addr       = object_address;
+		object_table[i].size            = object_size;
+		object_table[i].instances       = object_instances;
+		object_table[i].num_report_ids  = object_report_ids;
+		report_id_count += object_instances * object_report_ids;
+
+		object_info_address += MXT_OBJECT_TABLE_ELEMENT_SIZE;
+	}
+
+	mxt->rid_map =
+		kzalloc(sizeof(struct report_id_map) * (report_id_count + 1),
+			/* allocate for report_id 0, even if not used */
+			GFP_KERNEL);
+	if (mxt->rid_map == NULL) {
+		printk(KERN_WARNING "maXTouch: Can't allocate memory!\n");
+		error = -ENOMEM;
+		goto err_rid_map_alloc;
+	}
+
+	mxt->messages = kzalloc(mxt->message_size * MXT_MESSAGE_BUFFER_SIZE,
+				GFP_KERNEL);
+	if (mxt->messages == NULL) {
+		printk(KERN_WARNING "maXTouch: Can't allocate memory!\n");
+		error = -ENOMEM;
+		goto err_msg_alloc;
+	}
+
+	mxt->last_message = kzalloc(mxt->message_size, GFP_KERNEL);
+	if (mxt->last_message == NULL) {
+		printk(KERN_WARNING "maXTouch: Can't allocate memory!\n");
+		error = -ENOMEM;
+		goto err_msg_alloc;
+	}
+
+	mxt->report_id_count = report_id_count;
+	if (report_id_count > 254) {	/* 0 & 255 are reserved */
+			dev_err(&client->dev,
+				"Too many maXTouch report id's [%d]\n",
+				report_id_count);
+			error = -ENXIO;
+			goto err_max_rid;
+	}
+
+	/* Create a mapping from report id to object type */
+	report_id = 1; /* Start from 1, 0 is reserved. */
+
+	/* Create table associating report id's with objects & instances */
+	for (i = 0; i < mxt->device_info.num_objs; i++) {
+		for (object_instance = 0;
+		     object_instance < object_table[i].instances;
+		     object_instance++){
+			first_report_id = report_id;
+			for (object_report_id = 0;
+			     object_report_id < object_table[i].num_report_ids;
+			     object_report_id++) {
+				mxt->rid_map[report_id].object =
+					object_table[i].type;
+				mxt->rid_map[report_id].instance =
+					object_instance;
+				mxt->rid_map[report_id].first_rid =
+					first_report_id;
+				report_id++;
+			}
+		}
+	}
+
+	/* Read 3 byte CRC */
+	error = mxt_read_block(client, object_info_address, 3, buf);
+	if (error < 0) {
+		mxt->read_fail_counter++;
+		dev_err(&client->dev, "Error reading CRC\n");
+	}
+
+	crc = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+	if (calculate_infoblock_crc(&calculated_crc, raw_ib_data,
+				    ib_pointer)) {
+		printk(KERN_WARNING "Error while calculating CRC!\n");
+		calculated_crc = 0;
+	}
+	kfree(raw_ib_data);
+
+	mxt_debug(DEBUG_TRACE, "\nReported info block CRC = 0x%6X\n", crc);
+	mxt_debug(DEBUG_TRACE, "Calculated info block CRC = 0x%6X\n\n",
+		       calculated_crc);
+
+	if (crc == calculated_crc) {
+		mxt->info_block_crc = crc;
+	} else {
+		mxt->info_block_crc = 0;
+		printk(KERN_ALERT "maXTouch: Info block CRC invalid!\n");
+	}
+
+	if (debug >= DEBUG_VERBOSE) {
+
+		dev_info(&client->dev, "maXTouch: %d Objects\n",
+				mxt->device_info.num_objs);
+
+		for (i = 0; i < mxt->device_info.num_objs; i++) {
+			dev_info(&client->dev, "Type:\t\t\t[%d]: %s\n",
+				 object_table[i].type,
+				 object_type_name[object_table[i].type]);
+			dev_info(&client->dev, "\tAddress:\t0x%04X\n",
+				object_table[i].chip_addr);
+			dev_info(&client->dev, "\tSize:\t\t%d Bytes\n",
+				 object_table[i].size);
+			dev_info(&client->dev, "\tInstances:\t%d\n",
+				 object_table[i].instances);
+			dev_info(&client->dev, "\tReport Id's:\t%d\n",
+				 object_table[i].num_report_ids);
+		}
+	}
+
+	return 0;
+
+
+err_max_rid:
+	kfree(mxt->last_message);
+err_msg_alloc:
+	kfree(mxt->rid_map);
+err_rid_map_alloc:
+err_object_read:
+	kfree(raw_ib_data);
+err_ib_alloc:
+	kfree(object_table);
+err_object_table_alloc:
+	return error;
+}
+
+static int __devinit mxt_probe(struct i2c_client *client,
+			       const struct i2c_device_id *id)
+{
+	struct mxt_data          *mxt;
+	struct mxt_platform_data *pdata;
+	struct input_dev         *input;
+	u8 *id_data;
+	int error;
+
+	mxt_debug(DEBUG_INFO, "mXT224: mxt_probe\n");
+
+	if (client == NULL) {
+		pr_debug("maXTouch: client == NULL\n");
+		return	-EINVAL;
+	} else if (client->adapter == NULL) {
+		pr_debug("maXTouch: client->adapter == NULL\n");
+		return	-EINVAL;
+	} else if (&client->dev == NULL) {
+		pr_debug("maXTouch: client->dev == NULL\n");
+		return	-EINVAL;
+	} else if (&client->adapter->dev == NULL) {
+		pr_debug("maXTouch: client->adapter->dev == NULL\n");
+		return	-EINVAL;
+	} else if (id == NULL) {
+		pr_debug("maXTouch: id == NULL\n");
+		return	-EINVAL;
+	}
+
+	mxt_debug(DEBUG_INFO, "maXTouch driver v. %s\n", DRIVER_VERSION);
+	mxt_debug(DEBUG_INFO, "\t \"%s\"\n", client->name);
+	mxt_debug(DEBUG_INFO, "\taddr:\t0x%04x\n", client->addr);
+	mxt_debug(DEBUG_INFO, "\tirq:\t%d\n", client->irq);
+	mxt_debug(DEBUG_INFO, "\tflags:\t0x%04x\n", client->flags);
+	mxt_debug(DEBUG_INFO, "\tadapter:\"%s\"\n", client->adapter->name);
+	mxt_debug(DEBUG_INFO, "\tdevice:\t\"%s\"\n", client->dev.init_name);
+
+	mxt_debug(DEBUG_TRACE, "maXTouch driver functionality OK\n");
+
+	/* Allocate structure - we need it to identify device */
+	mxt = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
+	if (mxt == NULL) {
+		dev_err(&client->dev, "insufficient memory\n");
+		error = -ENOMEM;
+		goto err_mxt_alloc;
+	}
+
+	id_data = kmalloc(MXT_ID_BLOCK_SIZE, GFP_KERNEL);
+	if (id_data == NULL) {
+		dev_err(&client->dev, "insufficient memory\n");
+		error = -ENOMEM;
+		goto err_id_alloc;
+	}
+
+	input = input_allocate_device();
+	if (!input) {
+		dev_err(&client->dev, "error allocating input device\n");
+		error = -ENOMEM;
+		goto err_input_dev_alloc;
+	}
+
+	/* Initialize Platform data */
+
+	pdata = client->dev.platform_data;
+	if (pdata == NULL) {
+		dev_err(&client->dev, "platform data is required!\n");
+		error = -EINVAL;
+		goto err_pdata;
+	}
+	if (debug >= DEBUG_TRACE)
+		printk(KERN_INFO "Platform OK: pdata = 0x%08x\n",
+		       (unsigned int) pdata);
+
+	mxt->read_fail_counter = 0;
+	mxt->message_counter   = 0;
+	mxt->max_x_val         = pdata->max_x;
+	mxt->max_y_val         = pdata->max_y;
+	mxt->numtouch          = pdata->numtouch;
+
+	/* Get data that is defined in board specific code. */
+	mxt->init_hw = pdata->init_platform_hw;
+	mxt->exit_hw = pdata->exit_platform_hw;
+	mxt->read_chg = pdata->read_chg;
+
+	if (pdata->valid_interrupt != NULL)
+		mxt->valid_interrupt = pdata->valid_interrupt;
+	else
+		mxt->valid_interrupt = mxt_valid_interrupt_dummy;
+
+	if (mxt->init_hw != NULL)
+		mxt->init_hw();
+
+	if (debug >= DEBUG_TRACE)
+		printk(KERN_INFO "maXTouch driver identifying chip\n");
+
+	if (mxt_identify(client, mxt, id_data) < 0) {
+		dev_err(&client->dev, "Chip could not be identified\n");
+		error = -ENODEV;
+		goto err_identify;
+	}
+	/* Chip is valid and active. */
+	if (debug >= DEBUG_TRACE)
+		printk(KERN_INFO "maXTouch driver allocating input device\n");
+
+	mxt->client = client;
+	mxt->input  = input;
+
+	INIT_DELAYED_WORK(&mxt->dwork, mxt_worker);
+	mutex_init(&mxt->debug_mutex);
+	mutex_init(&mxt->msg_mutex);
+	mxt_debug(DEBUG_TRACE, "maXTouch driver creating device name\n");
+
+	snprintf(
+		mxt->phys_name,
+		sizeof(mxt->phys_name),
+		"%s/input0",
+		dev_name(&client->dev)
+	);
+	input->name = "Atmel maXTouch Touchscreen controller";
+	input->phys = mxt->phys_name;
+	input->id.bustype = BUS_I2C;
+	input->dev.parent = &client->dev;
+
+	mxt_debug(DEBUG_INFO, "maXTouch name: \"%s\"\n", input->name);
+	mxt_debug(DEBUG_INFO, "maXTouch phys: \"%s\"\n", input->phys);
+	mxt_debug(DEBUG_INFO, "maXTouch driver setting abs parameters\n");
+
+	set_bit(BTN_TOUCH, input->keybit);
+
+	/* Single touch */
+	input_set_abs_params(input, ABS_X, 0, mxt->max_x_val, 0, 0);
+	input_set_abs_params(input, ABS_Y, 0, mxt->max_y_val, 0, 0);
+	input_set_abs_params(input, ABS_PRESSURE, 0, MXT_MAX_REPORTED_PRESSURE,
+			     0, 0);
+	input_set_abs_params(input, ABS_TOOL_WIDTH, 0, MXT_MAX_REPORTED_WIDTH,
+			     0, 0);
+
+	/* Multitouch */
+	input_set_abs_params(input, ABS_MT_POSITION_X, 0, mxt->max_x_val, 0, 0);
+	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, mxt->max_y_val, 0, 0);
+	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, MXT_MAX_TOUCH_SIZE,
+			     0, 0);
+	input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, MXT_MAX_NUM_TOUCHES,
+			     0, 0);
+
+	__set_bit(EV_ABS, input->evbit);
+	__set_bit(EV_SYN, input->evbit);
+	__set_bit(EV_KEY, input->evbit);
+	__set_bit(EV_MSC, input->evbit);
+	input->mscbit[0] = BIT_MASK(MSC_GESTURE);
+
+	mxt_debug(DEBUG_TRACE, "maXTouch driver setting client data\n");
+	i2c_set_clientdata(client, mxt);
+	mxt_debug(DEBUG_TRACE, "maXTouch driver setting drv data\n");
+	input_set_drvdata(input, mxt);
+	mxt_debug(DEBUG_TRACE, "maXTouch driver input register device\n");
+	error = input_register_device(mxt->input);
+	if (error < 0) {
+		dev_err(&client->dev,
+			"Failed to register input device\n");
+		goto err_register_device;
+	}
+
+	error = mxt_read_object_table(client, mxt, id_data);
+	if (error < 0)
+		goto err_read_ot;
+
+
+	/* Create debugfs entries. */
+	mxt->debug_dir = debugfs_create_dir("maXTouch", NULL);
+	if (mxt->debug_dir == -ENODEV) {
+		/* debugfs is not enabled. */
+		printk(KERN_WARNING "debugfs not enabled in kernel\n");
+	} else if (mxt->debug_dir == NULL) {
+		printk(KERN_WARNING "error creating debugfs dir\n");
+	} else {
+		mxt_debug(DEBUG_TRACE, "created \"maXTouch\" debugfs dir\n");
+		debugfs_create_file("deltas", S_IRUSR, mxt->debug_dir, mxt,
+				    &delta_fops);
+		debugfs_create_file("refs", S_IRUSR, mxt->debug_dir, mxt,
+				    &refs_fops);
+	}
+
+	/* Create character device nodes for reading & writing registers */
+	mxt->mxt_class = class_create(THIS_MODULE, "maXTouch_memory");
+	if (IS_ERR(mxt->mxt_class)) {
+		printk(KERN_WARNING "class create failed! exiting...");
+		goto err_read_ot;
+	}
+	/* 2 numbers; one for memory and one for messages */
+	error = alloc_chrdev_region(&mxt->dev_num, 0, 2,
+				    "maXTouch_memory");
+	mxt_debug(DEBUG_VERBOSE,
+		"device number %d allocated!\n", MAJOR(mxt->dev_num));
+	if (error)
+		printk(KERN_WARNING "Error registering device\n");
+
+	cdev_init(&mxt->cdev, &mxt_memory_fops);
+	cdev_init(&mxt->cdev_messages, &mxt_message_fops);
+
+	mxt_debug(DEBUG_VERBOSE, "cdev initialized\n");
+	mxt->cdev.owner = THIS_MODULE;
+	mxt->cdev_messages.owner = THIS_MODULE;
+
+	error = cdev_add(&mxt->cdev, mxt->dev_num, 1);
+	if (error)
+		printk(KERN_WARNING "Bad cdev\n");
+
+	error = cdev_add(&mxt->cdev_messages, mxt->dev_num + 1, 1);
+	if (error)
+		printk(KERN_WARNING "Bad cdev\n");
+
+	mxt_debug(DEBUG_VERBOSE, "cdev added\n");
+
+	device_create(mxt->mxt_class, NULL, MKDEV(MAJOR(mxt->dev_num), 0), NULL,
+		"maXTouch");
+
+	device_create(mxt->mxt_class, NULL, MKDEV(MAJOR(mxt->dev_num), 1), NULL,
+		"maXTouch_messages");
+
+	mxt->msg_buffer_startp = 0;
+	mxt->msg_buffer_endp = 0;
+
+	/* Allocate the interrupt */
+	mxt_debug(DEBUG_TRACE, "maXTouch driver allocating interrupt...\n");
+	mxt->irq = client->irq;
+	mxt->valid_irq_counter = 0;
+	mxt->invalid_irq_counter = 0;
+	mxt->irq_counter = 0;
+	if (mxt->irq) {
+		/* Try to request IRQ with falling edge first. This is
+		 * not always supported. If it fails, try with any edge. */
+		error = request_irq(mxt->irq,
+				    mxt_irq_handler,
+				    IRQF_TRIGGER_FALLING,
+				    client->dev.driver->name,
+				    mxt);
+		if (error < 0) {
+			/* TODO: why only 0 works on STK1000? */
+			error = request_irq(mxt->irq,
+					    mxt_irq_handler,
+					    0,
+					    client->dev.driver->name,
+					    mxt);
+		}
+
+		if (error < 0) {
+			dev_err(&client->dev,
+				"failed to allocate irq %d\n", mxt->irq);
+			goto err_irq;
+		}
+	}
+
+	if (debug > DEBUG_INFO)
+		dev_info(&client->dev, "touchscreen, irq %d\n", mxt->irq);
+
+	/* Schedule a worker routine to read any messages that might have
+	 * been sent before interrupts were enabled. */
+	cancel_delayed_work(&mxt->dwork);
+	schedule_delayed_work(&mxt->dwork, 0);
+	kfree(id_data);
+
+	return 0;
+
+
+err_irq:
+	kfree(mxt->rid_map);
+	kfree(mxt->object_table);
+	kfree(mxt->last_message);
+err_read_ot:
+err_register_device:
+err_identify:
+err_pdata:
+	input_free_device(input);
+err_input_dev_alloc:
+	kfree(id_data);
+err_id_alloc:
+	if (mxt->exit_hw != NULL)
+		mxt->exit_hw();
+	kfree(mxt);
+err_mxt_alloc:
+	return error;
+}
+
+static int __devexit mxt_remove(struct i2c_client *client)
+{
+	struct mxt_data *mxt;
+
+	mxt = i2c_get_clientdata(client);
+
+	/* Remove debug dir entries */
+	debugfs_remove_recursive(mxt->debug_dir);
+
+	if (mxt != NULL) {
+		if (mxt->exit_hw != NULL)
+			mxt->exit_hw();
+		if (mxt->irq)
+			free_irq(mxt->irq, mxt);
+		unregister_chrdev_region(mxt->dev_num, 2);
+		device_destroy(mxt->mxt_class, MKDEV(MAJOR(mxt->dev_num), 0));
+		device_destroy(mxt->mxt_class, MKDEV(MAJOR(mxt->dev_num), 1));
+		cdev_del(&mxt->cdev);
+		cdev_del(&mxt->cdev_messages);
+		cancel_delayed_work_sync(&mxt->dwork);
+		input_unregister_device(mxt->input);
+		class_destroy(mxt->mxt_class);
+		debugfs_remove(mxt->debug_dir);
+
+		kfree(mxt->rid_map);
+		kfree(mxt->object_table);
+		kfree(mxt->last_message);
+	}
+	kfree(mxt);
+
+	i2c_set_clientdata(client, NULL);
+	if (debug >= DEBUG_TRACE)
+		dev_info(&client->dev, "Touchscreen unregistered\n");
+
+	return 0;
+}
+
+#if defined(CONFIG_PM)
+/*
+ * Allow the touchscreen to resume the system from sleep.
+ * Alternatively we could put the maXTouch to deep sleep mode and use
+ * something else to resume.
+ *
+ * TODO: set ACQINT to some high value, and restore to original at resume?
+ */
+
+static int mxt_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct mxt_data *mxt = i2c_get_clientdata(client);
+	if (device_may_wakeup(&client->dev))
+		enable_irq_wake(mxt->irq);
+	return 0;
+}
+
+static int mxt_resume(struct i2c_client *client)
+{
+	struct mxt_data *mxt = i2c_get_clientdata(client);
+	if (device_may_wakeup(&client->dev))
+		disable_irq_wake(mxt->irq);
+	return 0;
+}
+#else
+#define mxt_suspend NULL
+#define mxt_resume NULL
+#endif
+
+static const struct i2c_device_id mxt_idtable[] = {
+	{"maXTouch", 0,},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, mxt_idtable);
+
+static struct i2c_driver mxt_driver = {
+	.driver = {
+		.name	= "maXTouch",
+		.owner  = THIS_MODULE,
+	},
+
+	.id_table	= mxt_idtable,
+	.probe		= mxt_probe,
+	.remove		= __devexit_p(mxt_remove),
+	.suspend	= mxt_suspend,
+	.resume		= mxt_resume,
+
+};
+
+static int __init mxt_init(void)
+{
+	int err;
+	err = i2c_add_driver(&mxt_driver);
+	if (err)
+		printk(KERN_WARNING "Adding maXTouch driver failed "
+		       "(errno = %d)\n", err);
+	else
+		mxt_debug(DEBUG_TRACE, "Successfully added driver %s\n",
+			  mxt_driver.driver.name);
+	return err;
+}
+
+static void __exit mxt_cleanup(void)
+{
+	i2c_del_driver(&mxt_driver);
+}
+
+
+module_init(mxt_init);
+module_exit(mxt_cleanup);
+
+MODULE_AUTHOR("Iiro Valkonen");
+MODULE_DESCRIPTION("Driver for Atmel maXTouch Touchscreen Controller");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/atmel_maxtouch.h b/include/linux/atmel_maxtouch.h
new file mode 100644
index 0000000..0f2904e
--- /dev/null
+++ b/include/linux/atmel_maxtouch.h
@@ -0,0 +1,310 @@ 
+/*
+ *  Atmel maXTouch header file
+ *
+ *  Copyright (c) 2010 Atmel Corporation
+ *  Copyright (C) 2010 Ulf Samuelsson (ulf@atmel.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 or 3 as
+ *  published by the Free Software Foundation.
+ *  See the file "COPYING" in the main directory of this archive
+ *  for more details.
+ *
+ */
+
+#define	MXT224_I2C_ADDR1				0x4A
+#define	MXT224_I2C_ADDR2				0x4B
+#define	MXT1386_I2C_ADDR1				0x4C
+#define	MXT1386_I2C_ADDR2				0x4D
+#define	MXT1386_I2C_ADDR3				0x5A
+#define	MXT1386_I2C_ADDR4				0x5B
+
+/*
+ * Select this address from above depending on what maXTouch
+ * chip you have and how it's address pins are configured;
+ * see datasheet.
+ */
+
+#define MXT_I2C_ADDRESS                                 MXT1386_I2C_ADDR1
+
+#define	MXT224_FAMILYID				        0x80
+#define MXT1386_FAMILYID                                0xA0
+
+#define	MXT224_CAL_VARIANTID				0x01
+#define MXT224_UNCAL_VARIANTID                          0x00
+#define MXT1386_CAL_VARIANTID                           0x00
+
+#define MXT_MAX_REPORTED_WIDTH                          255
+#define MXT_MAX_REPORTED_PRESSURE                       255
+#define MXT_MAX_TOUCH_SIZE                              255
+#define MXT_MAX_NUM_TOUCHES                             10
+
+/* Fixed addresses inside maXTouch device */
+#define	MXT_ADDR_INFO_BLOCK				0
+#define	MXT_ADDR_OBJECT_TABLE				7
+#define MXT_ID_BLOCK_SIZE                               7
+#define	MXT_OBJECT_TABLE_ELEMENT_SIZE			6
+
+/* Object types */
+#define	MXT_DEBUG_DELTAS_T2				2
+#define	MXT_DEBUG_REFERENCES_T3				3
+#define	MXT_GEN_MESSAGEPROCESSOR_T5			5
+#define	MXT_GEN_COMMANDPROCESSOR_T6			6
+#define	MXT_GEN_POWERCONFIG_T7				7
+#define	MXT_GEN_ACQUIRECONFIG_T8			8
+#define	MXT_TOUCH_MULTITOUCHSCREEN_T9			9
+#define MXT_TOUCH_SINGLETOUCHSCREEN_T10                 10
+#define MXT_TOUCH_XSLIDER_T11                           11
+#define MXT_TOUCH_YSLIDER_T12                           12
+#define MXT_TOUCH_XWHEEL_T13                            13
+#define MXT_TOUCH_YWHEEL_T14                            14
+#define	MXT_TOUCH_KEYARRAY_T15				15
+#define	MXT_SPT_GPIOPWM_T19				19
+#define	MXT_PROCI_GRIPFACESUPPRESSION_T20		20
+#define	MXT_PROCG_NOISESUPPRESSION_T22			22
+#define	MXT_TOUCH_PROXIMITY_T23				23
+#define	MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24		24
+#define	MXT_SPT_SELFTEST_T25				25
+#define MXT_DEBUG_CTERANGE_T26				26
+#define	MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27		27
+#define	MXT_SPT_CTECONFIG_T28				28
+#define	MXT_TOUCH_KEYSET_T31				31
+#define	MXT_TOUCH_XSLIDERSET_T32			32
+#define	MXT_DEBUG_DIAGNOSTIC_T37			37
+#define	MXT_USER_INFO_T38				38
+
+
+/*
+ * If a message is read from mXT when there's no new messages available,
+ * the report ID of the message will be 0xFF.
+ */
+#define	MXT_END_OF_MESSAGES				0xFF
+
+
+/* GEN_COMMANDPROCESSOR_T6 Register offsets from T6 base address */
+#define	MXT_ADR_T6_RESET				0x00
+#define	MXT_ADR_T6_BACKUPNV				0x01
+#define	MXT_ADR_T6_CALIBRATE				0x02
+#define	MXT_ADR_T6_REPORTALL				0x03
+#define	MXT_ADR_T6_RESERVED				0x04
+#define	MXT_ADR_T6_DIAGNOSTIC				0x05
+
+/* T6 Debug Diagnostics Commands */
+#define	MXT_CMD_T6_PAGE_UP          0x01
+#define	MXT_CMD_T6_PAGE_DOWN        0x02
+#define	MXT_CMD_T6_DELTAS_MODE      0x10
+#define	MXT_CMD_T6_REFERENCES_MODE  0x11
+#define	MXT_CMD_T6_CTE_MODE         0x31
+
+/* T6 Backup Command */
+#define MXT_CMD_T6_BACKUP           0x55
+
+/* SPT_DEBUG_DIAGNOSTIC_T37 Register offsets from T37 base address */
+#define MXT_ADR_T37_PAGE                                0x01
+#define	MXT_ADR_T37_DATA				0x02
+
+
+
+/************************************************************************
+ * MESSAGE OBJECTS ADDRESS FIELDS
+ *
+ ************************************************************************/
+#define MXT_MSG_REPORTID                                0x00
+
+
+/* MXT_GEN_MESSAGEPROCESSOR_T5 Message address definitions		*/
+#define	MXT_MSG_T5_REPORTID				0x00
+#define	MXT_MSG_T5_MESSAGE				0x01
+#define	MXT_MSG_T5_CHECKSUM				0x08
+
+/* MXT_GEN_COMMANDPROCESSOR_T6 Message address definitions		*/
+#define	MXT_MSG_T6_STATUS				0x01
+#define		MXT_MSGB_T6_COMSERR		0x04
+#define		MXT_MSGB_T6_CFGERR		0x08
+#define		MXT_MSGB_T6_CAL			0x10
+#define		MXT_MSGB_T6_SIGERR		0x20
+#define		MXT_MSGB_T6_OFL			0x40
+#define		MXT_MSGB_T6_RESET		0x80
+/* Three bytes */
+#define	MXT_MSG_T6_CHECKSUM				0x02
+
+/* MXT_GEN_POWERCONFIG_T7 NO Message address definitions		*/
+/* MXT_GEN_ACQUIRECONFIG_T8 Message address definitions			*/
+/* MXT_TOUCH_MULTITOUCHSCREEN_T9 Message address definitions		*/
+
+#define	MXT_MSG_T9_STATUS				0x01
+/* Status bit field */
+#define		MXT_MSGB_T9_SUPPRESS		0x02
+#define		MXT_MSGB_T9_AMP			0x04
+#define		MXT_MSGB_T9_VECTOR		0x08
+#define		MXT_MSGB_T9_MOVE		0x10
+#define		MXT_MSGB_T9_RELEASE		0x20
+#define		MXT_MSGB_T9_PRESS		0x40
+#define		MXT_MSGB_T9_DETECT		0x80
+
+#define	MXT_MSG_T9_XPOSMSB				0x02
+#define	MXT_MSG_T9_YPOSMSB				0x03
+#define	MXT_MSG_T9_XYPOSLSB				0x04
+#define	MXT_MSG_T9_TCHAREA				0x05
+#define	MXT_MSG_T9_TCHAMPLITUDE				0x06
+#define	MXT_MSG_T9_TCHVECTOR				0x07
+
+
+/* MXT_SPT_GPIOPWM_T19 Message address definitions			*/
+#define	MXT_MSG_T19_STATUS				0x01
+
+/* MXT_PROCI_GRIPFACESUPPRESSION_T20 Message address definitions	*/
+#define	MXT_MSG_T20_STATUS				0x01
+#define		MXT_MSGB_T20_FACE_SUPPRESS	0x01
+/* MXT_PROCG_NOISESUPPRESSION_T22 Message address definitions		*/
+#define	MXT_MSG_T22_STATUS				0x01
+#define		MXT_MSGB_T22_FHCHG		0x01
+#define		MXT_MSGB_T22_GCAFERR		0x04
+#define		MXT_MSGB_T22_FHERR		0x08
+#define	MXT_MSG_T22_GCAFDEPTH				0x02
+
+/* MXT_TOUCH_PROXIMITY_T23 Message address definitions			*/
+#define	MXT_MSG_T23_STATUS				0x01
+#define		MXT_MSGB_T23_FALL		0x20
+#define		MXT_MSGB_T23_RISE		0x40
+#define		MXT_MSGB_T23_DETECT		0x80
+/* 16 bit */
+#define	MXT_MSG_T23_PROXDELTA				0x02
+
+/* MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24 Message address definitions	*/
+#define	MXT_MSG_T24_STATUS				0x01
+#define	MXT_MSG_T24_XPOSMSB				0x02
+#define	MXT_MSG_T24_YPOSMSB				0x03
+#define	MXT_MSG_T24_XYPOSLSB				0x04
+#define	MXT_MSG_T24_DIR					0x05
+/* 16 bit */
+#define	MXT_MSG_T24_DIST				0x06
+
+/* MXT_SPT_SELFTEST_T25 Message address definitions			*/
+#define	MXT_MSG_T25_STATUS				0x01
+/* 5 Bytes */
+#define		MXT_MSGR_T25_OK			0xFE
+#define		MXT_MSGR_T25_INVALID_TEST	0xFD
+#define		MXT_MSGR_T25_PIN_FAULT		0x11
+#define		MXT_MSGR_T25_SIGNAL_LIMIT_FAULT	0x17
+#define		MXT_MSGR_T25_GAIN_ERROR		0x20
+#define	MXT_MSG_T25_INFO				0x02
+
+/* MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27 Message address definitions	*/
+#define	MXT_MSG_T27_STATUS			0x01
+#define		MXT_MSGB_T27_ROTATEDIR		0x10
+#define		MXT_MSGB_T27_PINCH		0x20
+#define		MXT_MSGB_T27_ROTATE		0x40
+#define		MXT_MSGB_T27_STRETCH		0x80
+#define	MXT_MSG_T27_XPOSMSB			0x02
+#define	MXT_MSG_T27_YPOSMSB			0x03
+#define	MXT_MSG_T27_XYPOSLSB			0x04
+#define	MXT_MSG_T27_ANGLE			0x05
+
+/* 16 bit */
+#define	MXT_MSG_T27_SEPARATION				0x06
+
+/* MXT_SPT_CTECONFIG_T28 Message address definitions			*/
+#define	MXT_MSG_T28_STATUS				0x01
+#define	MXT_MSGB_T28_CHKERR		0x01
+
+
+/* One Touch Events */
+#define	MXT_GESTURE_RESERVED		0x00
+#define	MXT_GESTURE_PRESS		0x01
+#define	MXT_GESTURE_RELEASE		0x02
+#define	MXT_GESTURE_TAP			0x03
+#define	MXT_GESTURE_DOUBLE_TAP		0x04
+#define	MXT_GESTURE_FLICK		0x05
+#define	MXT_GESTURE_DRAG		0x06
+#define	MXT_GESTURE_SHORT_PRESS		0x07
+#define	MXT_GESTURE_LONG_PRESS		0x08
+#define	MXT_GESTURE_REPEAT_PRESS	0x09
+#define	MXT_GESTURE_TAP_AND_PRESS	0x0a
+#define	MXT_GESTURE_THROW		0x0b
+
+/* Two-touch events */
+#define MXT_GESTURE_STRETCH             (1 << 7)
+#define MXT_GESTURE_ROTATE              (1 << 6)
+#define MXT_GESTURE_PINCH               (1 << 5)
+#define MXT_GESTURE_ROTATEDIR           (1 << 4)
+
+
+
+/* Bootloader states */
+#define WAITING_BOOTLOAD_COMMAND   0xC0
+#define WAITING_FRAME_DATA         0x80
+#define APP_CRC_FAIL               0x40
+#define FRAME_CRC_CHECK            0x02
+#define FRAME_CRC_PASS             0x04
+#define FRAME_CRC_FAIL             0x03
+
+#define MXT_MAX_FRAME_SIZE         276
+
+/* Debug levels */
+#define DEBUG_INFO     1
+#define DEBUG_VERBOSE  2
+#define DEBUG_MESSAGES 5
+#define DEBUG_RAW      8
+#define DEBUG_TRACE   10
+
+/* IOCTL commands */
+#define MXT_SET_ADDRESS_IOCTL _IOW('x', 0x01, int)  /* Sets the internal address pointer */
+#define MXT_RESET_IOCTL       _IO('x', 0x02)  /* Resets the device */
+#define MXT_CALIBRATE_IOCTL   _IO('x', 0x03)  /* Calibrates the device */
+/* Backups the current state of registers to NVM */
+#define MXT_BACKUP_IOCTL      _IO('x', 0x04)
+/*
+ * Only non-touch messages can be read from the message buffer
+ * (/dev/maXTouch_messages)
+ */
+#define MXT_NONTOUCH_MSG_IOCTL _IO('x', 0x05)
+/* All messages can be read from the message buffer */
+#define MXT_ALL_MSG_IOCTL _IO('x', 0x06)
+
+/* Message buffer size. This is a ring buffer, and when full, the oldest entry
+   will be overwritten. */
+#define MXT_MESSAGE_BUFFER_SIZE  128
+
+/* Routines for memory access within a 16 bit address space */
+
+static int mxt_read_block(struct i2c_client *client, u16 addr, u16 length,
+			  u8 *value);
+static int mxt_write_byte(struct i2c_client *client, u16 addr, u8 value);
+static int mxt_write_block(struct i2c_client *client, u16 addr, u16 length,
+			   u8 *value);
+
+
+/**
+ * struct mxt_platform_data - includes platform specific informatio
+ * related to Atmel maXTouch touchscreen controller.
+ *
+ * @numtouch:           Number of simultaneous touches supported
+ * @init_platform_hw(): Initialization function, which can for example
+ *                      trigger a hardware reset by toggling a GPIO pin
+ * @exit_platform_hw(): Function to run when the driver is unloaded.
+ * @valid_interrupt():  Function that checks the validity of the interrupt -
+ *                      function that check the validity of a interrupt (by
+ *                      reading the changeline interrupt pin and checking that
+ *                      it really is low for example).
+ * @max_x:              Reported X range
+ * @max_y:              Reported Y range
+ */
+
+struct mxt_platform_data {
+	u8    numtouch;	/* Number of touches to report	*/
+	void  (*init_platform_hw)(void);
+	void  (*exit_platform_hw)(void);
+	int   max_x;    /* The default reported X range   */
+	int   max_y;    /* The default reported Y range   */
+	u8    (*valid_interrupt) (void);
+	u8    (*read_chg) (void);
+};
+
+
+static u8 mxt_valid_interrupt_dummy(void)
+{
+	return 1;
+}
+
+void	mxt_hw_reset(void);