diff --git a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt
index 1852906517ab1c1b691fb4df75f8b5bdd7c9c78c..23e3abc3fdef0c084ed61a78d15c49597f075c72 100644
--- a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt
+++ b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt
@@ -22,6 +22,8 @@ Optional properties for main touchpad device:
     experiment to determine which bit corresponds to which input. Use
     KEY_RESERVED for unused padding values.
 
+- reset-gpios: GPIO specifier for the touchscreen's reset pin (active low)
+
 Example:
 
 	touch@4b {
diff --git a/Documentation/devicetree/bindings/serio/ps2-gpio.txt b/Documentation/devicetree/bindings/serio/ps2-gpio.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7b7bc9cdf9861257f6886029c432b1b08ce1e52b
--- /dev/null
+++ b/Documentation/devicetree/bindings/serio/ps2-gpio.txt
@@ -0,0 +1,23 @@
+Device-Tree binding for ps/2 gpio device
+
+Required properties:
+	- compatible = "ps2-gpio"
+	- data-gpios: the data pin
+	- clk-gpios: the clock pin
+	- interrupts: Should trigger on the falling edge of the clock line.
+
+Optional properties:
+	- write-enable: Indicates whether write function is provided
+	to serio device. Possibly providing the write fn will not work, because
+	of the tough timing requirements.
+
+Example nodes:
+
+ps2@0 {
+	compatible = "ps2-gpio";
+	interrupt-parent = <&gpio>;
+	interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
+	data-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
+	clk-gpios = <&gpio 23 GPIO_ACTIVE_HIGH>;
+	write-enable;
+};
diff --git a/Documentation/gpio/drivers-on-gpio.txt b/Documentation/gpio/drivers-on-gpio.txt
index 3065132517135c231d28d4a9d3be87fd3c81f27b..9a78d385b92e86661f38ad265e474f0e88945087 100644
--- a/Documentation/gpio/drivers-on-gpio.txt
+++ b/Documentation/gpio/drivers-on-gpio.txt
@@ -84,6 +84,11 @@ hardware descriptions such as device tree or ACPI:
   NAND flash MTD subsystem and provides chip access and partition parsing like
   any other NAND driving hardware.
 
+- ps2-gpio: drivers/input/serio/ps2-gpio.c is used to drive a PS/2 (IBM) serio
+  bus, data and clock line, by bit banging two GPIO lines. It will appear as
+  any other serio bus to the system and makes it possible to connect drivers
+  for e.g. keyboards and other PS/2 protocol based devices.
+
 Apart from this there are special GPIO drivers in subsystems like MMC/SD to
 read card detect and write protect GPIO lines, and in the TTY serial subsystem
 to emulate MCTRL (modem control) signals CTS/RTS by using two GPIO lines. The
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index e2c97728b3c6b2890431cdd017e118c4f2ce7e57..9d662fed03ec7ae7fbf05bd22775185b00e571b6 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -377,7 +377,7 @@ static struct gpiod_lookup_table raumfeld_rotary_gpios_table = {
 	},
 };
 
-static struct property_entry raumfeld_rotary_properties[] = {
+static const struct property_entry raumfeld_rotary_properties[] __initconst = {
 	PROPERTY_ENTRY_INTEGER("rotary-encoder,steps-per-period", u32, 24),
 	PROPERTY_ENTRY_INTEGER("linux,axis",			  u32, REL_X),
 	PROPERTY_ENTRY_INTEGER("rotary-encoder,relative_axis",	  u32, 1),
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 7e6842bd525c679a808c0e39bab7c5c4711f72ba..d268fdc23c6419e2540cc941edb66231be3a900d 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1398,7 +1398,7 @@ static struct attribute *input_dev_attrs[] = {
 	NULL
 };
 
-static struct attribute_group input_dev_attr_group = {
+static const struct attribute_group input_dev_attr_group = {
 	.attrs	= input_dev_attrs,
 };
 
@@ -1425,7 +1425,7 @@ static struct attribute *input_dev_id_attrs[] = {
 	NULL
 };
 
-static struct attribute_group input_dev_id_attr_group = {
+static const struct attribute_group input_dev_id_attr_group = {
 	.name	= "id",
 	.attrs	= input_dev_id_attrs,
 };
@@ -1495,7 +1495,7 @@ static struct attribute *input_dev_caps_attrs[] = {
 	NULL
 };
 
-static struct attribute_group input_dev_caps_attr_group = {
+static const struct attribute_group input_dev_caps_attr_group = {
 	.name	= "capabilities",
 	.attrs	= input_dev_caps_attrs,
 };
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 46d5041d2d9dbbdf174d1ed66ac74c85c60f7c5b..154e827b559b34ba956f86f7f2400ad9c7fc29ee 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -164,7 +164,7 @@ static void iforce_serio_disconnect(struct serio *serio)
 	kfree(iforce);
 }
 
-static struct serio_device_id iforce_serio_ids[] = {
+static const struct serio_device_id iforce_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_IFORCE,
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index db64adfbe1aff092b4418832c1c81cce0901e044..e8724f1a4a25148eb0727576005a0b1ee3d7818a 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -209,7 +209,7 @@ static void iforce_usb_disconnect(struct usb_interface *intf)
 	kfree(iforce);
 }
 
-static struct usb_device_id iforce_usb_ids [] = {
+static const struct usb_device_id iforce_usb_ids[] = {
 	{ USB_DEVICE(0x044f, 0xa01c) },		/* Thrustmaster Motor Sport GT */
 	{ USB_DEVICE(0x046d, 0xc281) },		/* Logitech WingMan Force */
 	{ USB_DEVICE(0x046d, 0xc291) },		/* Logitech WingMan Formula Force */
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index c5358ba1f571ff18792c6491d6a6762ccaeb34a9..a9d0e3edca940f2d815b8e96df2690e1c727ac91 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -198,7 +198,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id magellan_serio_ids[] = {
+static const struct serio_device_id magellan_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_MAGELLAN,
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index f4445a4e8d6a5c937fabe921aad21b0ae8f65159..e9712a1b7cad93a35ed244a647ddeb494f0e494f 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -272,7 +272,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id spaceball_serio_ids[] = {
+static const struct serio_device_id spaceball_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_SPACEBALL,
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index f2667820e8c5f0177a635eb62afa9736f49d5f4f..05da0ed514e2aa7bfa338553b16460b3ce402733 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -213,7 +213,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id spaceorb_serio_ids[] = {
+static const struct serio_device_id spaceorb_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_SPACEORB,
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index 099c6d7b5e08732a2e0a1d26f0f4c25d1f3921cd..cb10e7b097ae25e894860de3810c4665c174fdda 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -184,7 +184,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id stinger_serio_ids[] = {
+static const struct serio_device_id stinger_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_STINGER,
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 7f7e5ab3f9e303871de01d681f0453af1bb3e52a..e60cb004cb8c6f225955042c8f0e47f88044d0e8 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -233,7 +233,7 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id twidjoy_serio_ids[] = {
+static const struct serio_device_id twidjoy_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_TWIDJOY,
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index e13a9144a25da517b3c1754abaa68599ddef2427..ef5391ba4470badbd40e1b07afea0ab361cb547a 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -193,7 +193,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id warrior_serio_ids[] = {
+static const struct serio_device_id warrior_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_WARRIOR,
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index ca0e19ae7a90f0a2854938f926c5d7ece0675686..f8e34ef643c73fe6dc1aa8caf3be57a619e31713 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -408,7 +408,7 @@ static const signed short xpad_abs_triggers[] = {
 #define XPAD_XBOXONE_VENDOR(vend) \
 	{ XPAD_XBOXONE_VENDOR_PROTOCOL(vend, 208) }
 
-static struct usb_device_id xpad_table[] = {
+static const struct usb_device_id xpad_table[] = {
 	{ USB_INTERFACE_INFO('X', 'B', 0) },	/* X-Box USB-IF not approved class */
 	XPAD_XBOX360_VENDOR(0x044f),		/* Thrustmaster X-Box 360 controllers */
 	XPAD_XBOX360_VENDOR(0x045e),		/* Microsoft X-Box 360 controllers */
diff --git a/drivers/input/joystick/zhenhua.c b/drivers/input/joystick/zhenhua.c
index 4a8258bf13fd4e1c0d39ef6e41401ec82483b287..5c6d5de743f1609c919079eb2d0f836bb5ced911 100644
--- a/drivers/input/joystick/zhenhua.c
+++ b/drivers/input/joystick/zhenhua.c
@@ -192,7 +192,7 @@ static int zhenhua_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id zhenhua_serio_ids[] = {
+static const struct serio_device_id zhenhua_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_ZHENHUA,
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ec876b5b1382ff7da2e28b1eed6e953f0729ed32..7e75835e220f29f2140f26d50ab0403e774f16dd 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -1270,7 +1270,7 @@ static int atkbd_reconnect(struct serio *serio)
 	return retval;
 }
 
-static struct serio_device_id atkbd_serio_ids[] = {
+static const struct serio_device_id atkbd_serio_ids[] = {
 	{
 		.type	= SERIO_8042,
 		.proto	= SERIO_ANY,
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 0b10d4b356db82fda14ccd3a1768f1181687e5d6..e9f0ebf3267add21d8c372a7853312fa1998a7e6 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -353,7 +353,7 @@ static struct attribute *gpio_keys_attrs[] = {
 	NULL,
 };
 
-static struct attribute_group gpio_keys_attr_group = {
+static const struct attribute_group gpio_keys_attr_group = {
 	.attrs = gpio_keys_attrs,
 };
 
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index 5b152f25a8e1ff72e613608f08876b3098627469..bb29a7c9a1c0cf51d81b338834e149ab8555d50d 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -559,7 +559,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv)
 	return error;
 }
 
-static struct serio_device_id hil_dev_ids[] = {
+static const struct serio_device_id hil_dev_ids[] = {
 	{
 		.type = SERIO_HIL_MLC,
 		.proto = SERIO_HIL,
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 9fcd9f1d5dc8edc2547c5d303df87e5b666b8059..471d53815c6daa7c8c913d4c76b0f747ac7ae7f9 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -707,7 +707,7 @@ static void lkkbd_disconnect(struct serio *serio)
 	kfree(lk);
 }
 
-static struct serio_device_id lkkbd_serio_ids[] = {
+static const struct serio_device_id lkkbd_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_LKKBD,
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index 20f0443779907d8306e56a8bc75ba02f5f91d2d9..fb9b8e23ab937c59055af721ae8eb5f947011759 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -142,7 +142,7 @@ static void nkbd_disconnect(struct serio *serio)
 	kfree(nkbd);
 }
 
-static struct serio_device_id nkbd_serio_ids[] = {
+static const struct serio_device_id nkbd_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_NEWTON,
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 3841fa30db3343c2a7a4d464ea4d5ad77335830a..d0bdaeadf86d8ab0af2468ff07b94541845700f9 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -644,9 +644,12 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
 static int pxa27x_keypad_open(struct input_dev *dev)
 {
 	struct pxa27x_keypad *keypad = input_get_drvdata(dev);
-
+	int ret;
 	/* Enable unit clock */
-	clk_prepare_enable(keypad->clk);
+	ret = clk_prepare_enable(keypad->clk);
+	if (ret)
+		return ret;
+
 	pxa27x_keypad_config(keypad);
 
 	return 0;
@@ -683,6 +686,7 @@ static int pxa27x_keypad_resume(struct device *dev)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
 	struct input_dev *input_dev = keypad->input_dev;
+	int ret = 0;
 
 	/*
 	 * If the keypad is used as wake up source, the clock is not turned
@@ -695,14 +699,15 @@ static int pxa27x_keypad_resume(struct device *dev)
 
 		if (input_dev->users) {
 			/* Enable unit clock */
-			clk_prepare_enable(keypad->clk);
-			pxa27x_keypad_config(keypad);
+			ret = clk_prepare_enable(keypad->clk);
+			if (!ret)
+				pxa27x_keypad_config(keypad);
 		}
 
 		mutex_unlock(&input_dev->mutex);
 	}
 
-	return 0;
+	return ret;
 }
 #endif
 
diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c
index a6e0d565e30667551dd9f4ca00a2a547868b13f8..8b6de9a692dc9fe7b328f54db714cad52bea5bfb 100644
--- a/drivers/input/keyboard/stowaway.c
+++ b/drivers/input/keyboard/stowaway.c
@@ -146,7 +146,7 @@ static void skbd_disconnect(struct serio *serio)
 	kfree(skbd);
 }
 
-static struct serio_device_id skbd_serio_ids[] = {
+static const struct serio_device_id skbd_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_STOWAWAY,
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index dc6bb9d5b4f0287ab3cbba6fbb1fdb0121f532d5..c95707ea2656713e08edb6378d17d12105a96202 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -339,7 +339,7 @@ static void sunkbd_disconnect(struct serio *serio)
 	kfree(sunkbd);
 }
 
-static struct serio_device_id sunkbd_serio_ids[] = {
+static const struct serio_device_id sunkbd_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_SUNKBD,
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index 0c07e1023a4693ac705acea1b26068c65c54b39f..edc1385ca00bbde87f80268ecac3c21ed9b8a9e5 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -370,8 +370,11 @@ static int tegra_kbc_start(struct tegra_kbc *kbc)
 {
 	unsigned int debounce_cnt;
 	u32 val = 0;
+	int ret;
 
-	clk_prepare_enable(kbc->clk);
+	ret = clk_prepare_enable(kbc->clk);
+	if (ret)
+		return ret;
 
 	/* Reset the KBC controller to clear all previous status.*/
 	reset_control_assert(kbc->rst);
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 7c2325bd7408d2f0a6a83e18b8a83720508cfa9b..8f64b9ded8d0ef4c82fc83326e287e0306629422 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -145,7 +145,7 @@ static void xtkbd_disconnect(struct serio *serio)
 	kfree(xtkbd);
 }
 
-static struct serio_device_id xtkbd_serio_ids[] = {
+static const struct serio_device_id xtkbd_serio_ids[] = {
 	{
 		.type	= SERIO_XT,
 		.proto	= SERIO_ANY,
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 3872488c3fd7b9766c852a752dfcc3742efc9532..f47e836eaa0f6de06071a3299be8f91b61687db5 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -581,6 +581,17 @@ config INPUT_PWM_BEEPER
 	  To compile this driver as a module, choose M here: the module will be
 	  called pwm-beeper.
 
+config INPUT_RK805_PWRKEY
+	tristate "Rockchip RK805 PMIC power key support"
+	depends on MFD_RK808
+	help
+	  Select this option to enable power key driver for RK805.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called rk805_pwrkey.
+
 config INPUT_GPIO_ROTARY_ENCODER
 	tristate "Rotary encoders connected to GPIO pins"
 	depends on GPIOLIB || COMPILE_TEST
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index b923a9828c888d51db32ad4139417a9ee838bea9..1072e0760c1989f28c0236faaf9e408912e80d88 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_INPUT_REGULATOR_HAPTIC)	+= regulator-haptic.o
 obj-$(CONFIG_INPUT_RETU_PWRBUTTON)	+= retu-pwrbutton.o
 obj-$(CONFIG_INPUT_AXP20X_PEK)		+= axp20x-pek.o
 obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)	+= rotary_encoder.o
+obj-$(CONFIG_INPUT_RK805_PWRKEY)	+= rk805-pwrkey.o
 obj-$(CONFIG_INPUT_SGI_BTNS)		+= sgi_btns.o
 obj-$(CONFIG_INPUT_SIRFSOC_ONKEY)	+= sirfsoc-onkey.o
 obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY)	+= soc_button_array.o
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
index 1c5914cae8533326e17b878b406bedca130912d6..ebf4448b31b90c1338e545acc6c3dc1c917126d1 100644
--- a/drivers/input/misc/ati_remote2.c
+++ b/drivers/input/misc/ati_remote2.c
@@ -110,7 +110,7 @@ static const struct kernel_param_ops param_ops_mode_mask = {
 module_param(mode_mask, mode_mask, 0644);
 MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>");
 
-static struct usb_device_id ati_remote2_id_table[] = {
+static const struct usb_device_id ati_remote2_id_table[] = {
 	{ USB_DEVICE(0x0471, 0x0602) },	/* ATI Remote Wonder II */
 	{ }
 };
diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c
index cfeb0e943de69519779508a65fab961222dfce27..6cee5adc3b5cfa1ec322db10c49d84f1bcbc2ae3 100644
--- a/drivers/input/misc/axp20x-pek.c
+++ b/drivers/input/misc/axp20x-pek.c
@@ -29,9 +29,17 @@
 #define AXP20X_PEK_STARTUP_MASK		(0xc0)
 #define AXP20X_PEK_SHUTDOWN_MASK	(0x03)
 
+struct axp20x_info {
+	const struct axp20x_time *startup_time;
+	unsigned int startup_mask;
+	const struct axp20x_time *shutdown_time;
+	unsigned int shutdown_mask;
+};
+
 struct axp20x_pek {
 	struct axp20x_dev *axp20x;
 	struct input_dev *input;
+	struct axp20x_info *info;
 	int irq_dbr;
 	int irq_dbf;
 };
@@ -48,6 +56,13 @@ static const struct axp20x_time startup_time[] = {
 	{ .time = 2000, .idx = 3 },
 };
 
+static const struct axp20x_time axp221_startup_time[] = {
+	{ .time = 128,  .idx = 0 },
+	{ .time = 1000, .idx = 1 },
+	{ .time = 2000, .idx = 2 },
+	{ .time = 3000, .idx = 3 },
+};
+
 static const struct axp20x_time shutdown_time[] = {
 	{ .time = 4000,  .idx = 0 },
 	{ .time = 6000,  .idx = 1 },
@@ -55,31 +70,25 @@ static const struct axp20x_time shutdown_time[] = {
 	{ .time = 10000, .idx = 3 },
 };
 
-struct axp20x_pek_ext_attr {
-	const struct axp20x_time *p_time;
-	unsigned int mask;
+static const struct axp20x_info axp20x_info = {
+	.startup_time = startup_time,
+	.startup_mask = AXP20X_PEK_STARTUP_MASK,
+	.shutdown_time = shutdown_time,
+	.shutdown_mask = AXP20X_PEK_SHUTDOWN_MASK,
 };
 
-static struct axp20x_pek_ext_attr axp20x_pek_startup_ext_attr = {
-	.p_time	= startup_time,
-	.mask	= AXP20X_PEK_STARTUP_MASK,
+static const struct axp20x_info axp221_info = {
+	.startup_time = axp221_startup_time,
+	.startup_mask = AXP20X_PEK_STARTUP_MASK,
+	.shutdown_time = shutdown_time,
+	.shutdown_mask = AXP20X_PEK_SHUTDOWN_MASK,
 };
 
-static struct axp20x_pek_ext_attr axp20x_pek_shutdown_ext_attr = {
-	.p_time	= shutdown_time,
-	.mask	= AXP20X_PEK_SHUTDOWN_MASK,
-};
-
-static struct axp20x_pek_ext_attr *get_axp_ext_attr(struct device_attribute *attr)
-{
-	return container_of(attr, struct dev_ext_attribute, attr)->var;
-}
-
-static ssize_t axp20x_show_ext_attr(struct device *dev,
-				    struct device_attribute *attr, char *buf)
+static ssize_t axp20x_show_attr(struct device *dev,
+				const struct axp20x_time *time,
+				unsigned int mask, char *buf)
 {
 	struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
-	struct axp20x_pek_ext_attr *axp20x_ea = get_axp_ext_attr(attr);
 	unsigned int val;
 	int ret, i;
 
@@ -87,22 +96,42 @@ static ssize_t axp20x_show_ext_attr(struct device *dev,
 	if (ret != 0)
 		return ret;
 
-	val &= axp20x_ea->mask;
-	val >>= ffs(axp20x_ea->mask) - 1;
+	val &= mask;
+	val >>= ffs(mask) - 1;
 
 	for (i = 0; i < 4; i++)
-		if (val == axp20x_ea->p_time[i].idx)
-			val = axp20x_ea->p_time[i].time;
+		if (val == time[i].idx)
+			val = time[i].time;
 
 	return sprintf(buf, "%u\n", val);
 }
 
-static ssize_t axp20x_store_ext_attr(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
+static ssize_t axp20x_show_attr_startup(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
+
+	return axp20x_show_attr(dev, axp20x_pek->info->startup_time,
+				axp20x_pek->info->startup_mask, buf);
+}
+
+static ssize_t axp20x_show_attr_shutdown(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
+
+	return axp20x_show_attr(dev, axp20x_pek->info->shutdown_time,
+				axp20x_pek->info->shutdown_mask, buf);
+}
+
+static ssize_t axp20x_store_attr(struct device *dev,
+				 const struct axp20x_time *time,
+				 unsigned int mask, const char *buf,
+				 size_t count)
 {
 	struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
-	struct axp20x_pek_ext_attr *axp20x_ea = get_axp_ext_attr(attr);
 	char val_str[20];
 	size_t len;
 	int ret, i;
@@ -123,39 +152,52 @@ static ssize_t axp20x_store_ext_attr(struct device *dev,
 	for (i = 3; i >= 0; i--) {
 		unsigned int err;
 
-		err = abs(axp20x_ea->p_time[i].time - val);
+		err = abs(time[i].time - val);
 		if (err < best_err) {
 			best_err = err;
-			idx = axp20x_ea->p_time[i].idx;
+			idx = time[i].idx;
 		}
 
 		if (!err)
 			break;
 	}
 
-	idx <<= ffs(axp20x_ea->mask) - 1;
-	ret = regmap_update_bits(axp20x_pek->axp20x->regmap,
-				 AXP20X_PEK_KEY,
-				 axp20x_ea->mask, idx);
+	idx <<= ffs(mask) - 1;
+	ret = regmap_update_bits(axp20x_pek->axp20x->regmap, AXP20X_PEK_KEY,
+				 mask, idx);
 	if (ret != 0)
 		return -EINVAL;
 
 	return count;
 }
 
-static struct dev_ext_attribute axp20x_dev_attr_startup = {
-	.attr	= __ATTR(startup, 0644, axp20x_show_ext_attr, axp20x_store_ext_attr),
-	.var	= &axp20x_pek_startup_ext_attr,
-};
+static ssize_t axp20x_store_attr_startup(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
+{
+	struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
 
-static struct dev_ext_attribute axp20x_dev_attr_shutdown = {
-	.attr	= __ATTR(shutdown, 0644, axp20x_show_ext_attr, axp20x_store_ext_attr),
-	.var	= &axp20x_pek_shutdown_ext_attr,
-};
+	return axp20x_store_attr(dev, axp20x_pek->info->startup_time,
+				 axp20x_pek->info->startup_mask, buf, count);
+}
+
+static ssize_t axp20x_store_attr_shutdown(struct device *dev,
+					  struct device_attribute *attr,
+					  const char *buf, size_t count)
+{
+	struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
+
+	return axp20x_store_attr(dev, axp20x_pek->info->shutdown_time,
+				 axp20x_pek->info->shutdown_mask, buf, count);
+}
+
+DEVICE_ATTR(startup, 0644, axp20x_show_attr_startup, axp20x_store_attr_startup);
+DEVICE_ATTR(shutdown, 0644, axp20x_show_attr_shutdown,
+	    axp20x_store_attr_shutdown);
 
 static struct attribute *axp20x_attributes[] = {
-	&axp20x_dev_attr_startup.attr.attr,
-	&axp20x_dev_attr_shutdown.attr.attr,
+	&dev_attr_startup.attr,
+	&dev_attr_shutdown.attr,
 	NULL,
 };
 
@@ -291,8 +333,14 @@ static bool axp20x_pek_should_register_input(struct axp20x_pek *axp20x_pek,
 static int axp20x_pek_probe(struct platform_device *pdev)
 {
 	struct axp20x_pek *axp20x_pek;
+	const struct platform_device_id *match = platform_get_device_id(pdev);
 	int error;
 
+	if (!match) {
+		dev_err(&pdev->dev, "Failed to get platform_device_id\n");
+		return -EINVAL;
+	}
+
 	axp20x_pek = devm_kzalloc(&pdev->dev, sizeof(struct axp20x_pek),
 				  GFP_KERNEL);
 	if (!axp20x_pek)
@@ -306,6 +354,8 @@ static int axp20x_pek_probe(struct platform_device *pdev)
 			return error;
 	}
 
+	axp20x_pek->info = (struct axp20x_info *)match->driver_data;
+
 	error = devm_device_add_group(&pdev->dev, &axp20x_attribute_group);
 	if (error) {
 		dev_err(&pdev->dev, "Failed to create sysfs attributes: %d\n",
@@ -342,8 +392,21 @@ static const struct dev_pm_ops axp20x_pek_pm_ops = {
 #endif
 };
 
+static const struct platform_device_id axp_pek_id_match[] = {
+	{
+		.name = "axp20x-pek",
+		.driver_data = (kernel_ulong_t)&axp20x_info,
+	},
+	{
+		.name = "axp221-pek",
+		.driver_data = (kernel_ulong_t)&axp221_info,
+	},
+	{ /* sentinel */ }
+};
+
 static struct platform_driver axp20x_pek_driver = {
 	.probe		= axp20x_pek_probe,
+	.id_table	= axp_pek_id_match,
 	.driver		= {
 		.name		= "axp20x-pek",
 		.pm		= &axp20x_pek_pm_ops,
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index f4e8fbec6a942a8ea7a48e268b1e96f9fe458369..6bf82ea8c918adcbbba700100ead7d270a60695c 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -1261,7 +1261,7 @@ static umode_t ims_pcu_is_attr_visible(struct kobject *kobj,
 	return mode;
 }
 
-static struct attribute_group ims_pcu_attr_group = {
+static const struct attribute_group ims_pcu_attr_group = {
 	.is_visible	= ims_pcu_is_attr_visible,
 	.attrs		= ims_pcu_attrs,
 };
@@ -1480,7 +1480,7 @@ static struct attribute *ims_pcu_ofn_attrs[] = {
 	NULL
 };
 
-static struct attribute_group ims_pcu_ofn_attr_group = {
+static const struct attribute_group ims_pcu_ofn_attr_group = {
 	.name	= "ofn",
 	.attrs	= ims_pcu_ofn_attrs,
 };
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c
index a3fe4a990cc95c8f228b7abf5b725532c07086ca..77c47d6325fe91dca54f5b18d6c2a43c561b7f4c 100644
--- a/drivers/input/misc/keyspan_remote.c
+++ b/drivers/input/misc/keyspan_remote.c
@@ -85,7 +85,7 @@ static const unsigned short keyspan_key_table[] = {
 };
 
 /* table of devices that work with this driver */
-static struct usb_device_id keyspan_table[] = {
+static const struct usb_device_id keyspan_table[] = {
 	{ USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) },
 	{ }					/* Terminating entry */
 };
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 72b1fc3ab91072dd351eb34146b1e1ab2f697f9e..56ddba21de843324051eed7809f2aba3c42f0292 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -18,25 +18,30 @@
 #include <linux/input.h>
 #include <linux/platform_device.h>
 #include <linux/timex.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("PC Speaker beeper driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:pcspkr");
 
-static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static int pcspkr_event(struct input_dev *dev, unsigned int type,
+			unsigned int code, int value)
 {
 	unsigned int count = 0;
 	unsigned long flags;
 
 	if (type != EV_SND)
-		return -1;
+		return -EINVAL;
 
 	switch (code) {
-		case SND_BELL: if (value) value = 1000;
-		case SND_TONE: break;
-		default: return -1;
+	case SND_BELL:
+		if (value)
+			value = 1000;
+	case SND_TONE:
+		break;
+	default:
+		return -EINVAL;
 	}
 
 	if (value > 20 && value < 32767)
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c
index 84909a12ff36c231e7bcfc545bc2ce180c6cd26f..5c8c79623c8744ac82042154836b36a51cfc9723 100644
--- a/drivers/input/misc/powermate.c
+++ b/drivers/input/misc/powermate.c
@@ -432,7 +432,7 @@ static void powermate_disconnect(struct usb_interface *intf)
 	}
 }
 
-static struct usb_device_id powermate_devices [] = {
+static const struct usb_device_id powermate_devices[] = {
 	{ USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_NEW) },
 	{ USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_OLD) },
 	{ USB_DEVICE(CONTOUR_VENDOR, CONTOUR_JOG) },
diff --git a/drivers/input/misc/rk805-pwrkey.c b/drivers/input/misc/rk805-pwrkey.c
new file mode 100644
index 0000000000000000000000000000000000000000..921003963a53cc8a8a2f8812cad739d7a0434423
--- /dev/null
+++ b/drivers/input/misc/rk805-pwrkey.c
@@ -0,0 +1,111 @@
+/*
+ * Rockchip RK805 PMIC Power Key driver
+ *
+ * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * Author: Joseph Chen <chenjh@rock-chips.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.
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static irqreturn_t pwrkey_fall_irq(int irq, void *_pwr)
+{
+	struct input_dev *pwr = _pwr;
+
+	input_report_key(pwr, KEY_POWER, 1);
+	input_sync(pwr);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t pwrkey_rise_irq(int irq, void *_pwr)
+{
+	struct input_dev *pwr = _pwr;
+
+	input_report_key(pwr, KEY_POWER, 0);
+	input_sync(pwr);
+
+	return IRQ_HANDLED;
+}
+
+static int rk805_pwrkey_probe(struct platform_device *pdev)
+{
+	struct input_dev *pwr;
+	int fall_irq, rise_irq;
+	int err;
+
+	pwr = devm_input_allocate_device(&pdev->dev);
+	if (!pwr) {
+		dev_err(&pdev->dev, "Can't allocate power button\n");
+		return -ENOMEM;
+	}
+
+	pwr->name = "rk805 pwrkey";
+	pwr->phys = "rk805_pwrkey/input0";
+	pwr->id.bustype = BUS_HOST;
+	input_set_capability(pwr, EV_KEY, KEY_POWER);
+
+	fall_irq = platform_get_irq(pdev, 0);
+	if (fall_irq < 0) {
+		dev_err(&pdev->dev, "Can't get fall irq: %d\n", fall_irq);
+		return fall_irq;
+	}
+
+	rise_irq = platform_get_irq(pdev, 1);
+	if (rise_irq < 0) {
+		dev_err(&pdev->dev, "Can't get rise irq: %d\n", rise_irq);
+		return rise_irq;
+	}
+
+	err = devm_request_any_context_irq(&pwr->dev, fall_irq,
+					   pwrkey_fall_irq,
+					   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					   "rk805_pwrkey_fall", pwr);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Can't register fall irq: %d\n", err);
+		return err;
+	}
+
+	err = devm_request_any_context_irq(&pwr->dev, rise_irq,
+					   pwrkey_rise_irq,
+					   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					   "rk805_pwrkey_rise", pwr);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Can't register rise irq: %d\n", err);
+		return err;
+	}
+
+	err = input_register_device(pwr);
+	if (err) {
+		dev_err(&pdev->dev, "Can't register power button: %d\n", err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, pwr);
+	device_init_wakeup(&pdev->dev, true);
+
+	return 0;
+}
+
+static struct platform_driver rk805_pwrkey_driver = {
+	.probe	= rk805_pwrkey_probe,
+	.driver	= {
+		.name = "rk805-pwrkey",
+	},
+};
+module_platform_driver(rk805_pwrkey_driver);
+
+MODULE_AUTHOR("Joseph Chen <chenjh@rock-chips.com>");
+MODULE_DESCRIPTION("RK805 PMIC Power Key driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c
index fa130e7b734c79b28c34c25e89ca53cc24408300..6bf56bb5f8d97dd4b5835e54c7e7ca764db98434 100644
--- a/drivers/input/misc/xen-kbdfront.c
+++ b/drivers/input/misc/xen-kbdfront.c
@@ -84,17 +84,20 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info,
 				    struct xenkbd_key *key)
 {
 	struct input_dev *dev;
+	int value = key->pressed;
 
 	if (test_bit(key->keycode, info->ptr->keybit)) {
 		dev = info->ptr;
 	} else if (test_bit(key->keycode, info->kbd->keybit)) {
 		dev = info->kbd;
+		if (key->pressed && test_bit(key->keycode, info->kbd->key))
+			value = 2; /* Mark as autorepeat */
 	} else {
 		pr_warn("unhandled keycode 0x%x\n", key->keycode);
 		return;
 	}
 
-	input_report_key(dev, key->keycode, key->pressed);
+	input_event(dev, EV_KEY, key->keycode, value);
 	input_sync(dev);
 }
 
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
index 6e7ff9561d9261f31f919720925e12d8f1720b98..a1e0ff59d2f23095873d123b2e252c2466b68573 100644
--- a/drivers/input/misc/yealink.c
+++ b/drivers/input/misc/yealink.c
@@ -798,7 +798,7 @@ static struct attribute *yld_attributes[] = {
 	NULL
 };
 
-static struct attribute_group yld_attr_group = {
+static const struct attribute_group yld_attr_group = {
 	.attrs = yld_attributes
 };
 
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index ef234c9b2f2f5cce7e365951df37cef4bc8b08e4..81a695d0b4e04600e60f62949bd07ca01fda8062 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -125,7 +125,7 @@ static const struct atp_info geyser4_info = {
  *  According to Info.plist Geyser IV is the same as Geyser III.)
  */
 
-static struct usb_device_id atp_table[] = {
+static const struct usb_device_id atp_table[] = {
 	/* PowerBooks Feb 2005, iBooks G4 */
 	ATP_DEVICE(0x020e, fountain_info),	/* FOUNTAIN ANSI */
 	ATP_DEVICE(0x020f, fountain_info),	/* FOUNTAIN ISO */
diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c
index b27aa637f877203dc26ab372ce001d4e9aceb73f..b64b81599f7ec01da5e9bc1ae43dd46c934677d5 100644
--- a/drivers/input/mouse/byd.c
+++ b/drivers/input/mouse/byd.c
@@ -344,7 +344,7 @@ static int byd_reset_touchpad(struct psmouse *psmouse)
 	u8 param[4];
 	size_t i;
 
-	const struct {
+	static const struct {
 		u16 command;
 		u8 arg;
 	} seq[] = {
diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h
index 61c2024362508548a076dcc1dd9a1d22e3bbf27a..599544c1a91cd365261b6ca2ec4e4f3149b0a63d 100644
--- a/drivers/input/mouse/elan_i2c.h
+++ b/drivers/input/mouse/elan_i2c.h
@@ -58,7 +58,7 @@ struct elan_transport_ops {
 
 	int (*get_version)(struct i2c_client *client, bool iap, u8 *version);
 	int (*get_sm_version)(struct i2c_client *client,
-			      u16 *ic_type, u8 *version);
+			      u16 *ic_type, u8 *version, u8 *clickpad);
 	int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum);
 	int (*get_product_id)(struct i2c_client *client, u16 *id);
 
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index cfbc8ba4c96c7bedda89e1b79f8ee23b5cd36f47..0e761d079dc4669720d2d4899f13ecbbfdb22b52 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -95,6 +95,7 @@ struct elan_tp_data {
 	u8			min_baseline;
 	u8			max_baseline;
 	bool			baseline_ready;
+	u8			clickpad;
 };
 
 static int elan_get_fwinfo(u16 ic_type, u16 *validpage_count,
@@ -213,7 +214,7 @@ static int elan_query_product(struct elan_tp_data *data)
 		return error;
 
 	error = data->ops->get_sm_version(data->client, &data->ic_type,
-					  &data->sm_version);
+					  &data->sm_version, &data->clickpad);
 	if (error)
 		return error;
 
@@ -923,6 +924,7 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet)
 	}
 
 	input_report_key(input, BTN_LEFT, tp_info & 0x01);
+	input_report_key(input, BTN_RIGHT, tp_info & 0x02);
 	input_report_abs(input, ABS_DISTANCE, hover_event != 0);
 	input_mt_report_pointer_emulation(input, true);
 	input_sync(input);
@@ -991,7 +993,10 @@ static int elan_setup_input_device(struct elan_tp_data *data)
 
 	__set_bit(EV_ABS, input->evbit);
 	__set_bit(INPUT_PROP_POINTER, input->propbit);
-	__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+	if (data->clickpad)
+		__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+	else
+		__set_bit(BTN_RIGHT, input->keybit);
 	__set_bit(BTN_LEFT, input->keybit);
 
 	/* Set up ST parameters */
diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c
index 80172f25974db01e1c39e9db3688b4b48b723dad..15b1330606c1c3fcfc28cf109f89987d0425f75a 100644
--- a/drivers/input/mouse/elan_i2c_i2c.c
+++ b/drivers/input/mouse/elan_i2c_i2c.c
@@ -288,7 +288,8 @@ static int elan_i2c_get_version(struct i2c_client *client,
 }
 
 static int elan_i2c_get_sm_version(struct i2c_client *client,
-				   u16 *ic_type, u8 *version)
+				   u16 *ic_type, u8 *version,
+				   u8 *clickpad)
 {
 	int error;
 	u8 pattern_ver;
@@ -317,6 +318,7 @@ static int elan_i2c_get_sm_version(struct i2c_client *client,
 			return error;
 		}
 		*version = val[1];
+		*clickpad = val[0] & 0x10;
 	} else {
 		error = elan_i2c_read_cmd(client, ETP_I2C_OSM_VERSION_CMD, val);
 		if (error) {
@@ -326,6 +328,15 @@ static int elan_i2c_get_sm_version(struct i2c_client *client,
 		}
 		*version = val[0];
 		*ic_type = val[1];
+
+		error = elan_i2c_read_cmd(client, ETP_I2C_NSM_VERSION_CMD,
+					  val);
+		if (error) {
+			dev_err(&client->dev, "failed to get SM version: %d\n",
+				error);
+			return error;
+		}
+		*clickpad = val[0] & 0x10;
 	}
 
 	return 0;
diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c
index df7a57ca73318849d6519f661802ea933ff007d3..29f99529b1876a9c995dfa16e0430ad8ca4706cb 100644
--- a/drivers/input/mouse/elan_i2c_smbus.c
+++ b/drivers/input/mouse/elan_i2c_smbus.c
@@ -166,7 +166,8 @@ static int elan_smbus_get_version(struct i2c_client *client,
 }
 
 static int elan_smbus_get_sm_version(struct i2c_client *client,
-				     u16 *ic_type, u8 *version)
+				     u16 *ic_type, u8 *version,
+				     u8 *clickpad)
 {
 	int error;
 	u8 val[3];
@@ -180,6 +181,7 @@ static int elan_smbus_get_sm_version(struct i2c_client *client,
 
 	*version = val[0];
 	*ic_type = val[1];
+	*clickpad = val[0] & 0x10;
 	return 0;
 }
 
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 791993215ea34c8f88242ea94719746db240742d..6428d6f4d568d4e5bfbcbd0bcce2c8b913892489 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1377,7 +1377,7 @@ static struct attribute *elantech_attrs[] = {
 	NULL
 };
 
-static struct attribute_group elantech_attr_group = {
+static const struct attribute_group elantech_attr_group = {
 	.attrs = elantech_attrs,
 };
 
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index f73b47b8c578cfbe779d7204f3fa11992979691a..6a5649e52eed932226b87dd76c86fbcfaaa8d33a 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -101,7 +101,7 @@ static struct attribute *psmouse_attributes[] = {
 	NULL
 };
 
-static struct attribute_group psmouse_attribute_group = {
+static const struct attribute_group psmouse_attribute_group = {
 	.attrs	= psmouse_attributes,
 };
 
diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c
index 6bcc0189c1c99898dc39bd5ced920f60c13bd553..cb7d15d826d0d420ad426c1c491939d11bd65e34 100644
--- a/drivers/input/mouse/synaptics_usb.c
+++ b/drivers/input/mouse/synaptics_usb.c
@@ -525,7 +525,7 @@ static int synusb_reset_resume(struct usb_interface *intf)
 	return synusb_resume(intf);
 }
 
-static struct usb_device_id synusb_idtable[] = {
+static const struct usb_device_id synusb_idtable[] = {
 	{ USB_DEVICE_SYNAPTICS(TP, SYNUSB_TOUCHPAD) },
 	{ USB_DEVICE_SYNAPTICS(INT_TP, SYNUSB_TOUCHPAD) },
 	{ USB_DEVICE_SYNAPTICS(CPAD,
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 0e0ff84088fda19381207ffaa4dd561324aff6db..2d7f691ec71cef2af59ace5bb7c493c7f1755ad8 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -15,6 +15,7 @@
 #define MOUSEDEV_MINORS		31
 #define MOUSEDEV_MIX		63
 
+#include <linux/bitops.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
@@ -103,7 +104,7 @@ struct mousedev_client {
 	spinlock_t packet_lock;
 	int pos_x, pos_y;
 
-	signed char ps2[6];
+	u8 ps2[6];
 	unsigned char ready, buffer, bufsiz;
 	unsigned char imexseq, impsseq;
 	enum mousedev_emul mode;
@@ -291,11 +292,10 @@ static void mousedev_notify_readers(struct mousedev *mousedev,
 		}
 
 		client->pos_x += packet->dx;
-		client->pos_x = client->pos_x < 0 ?
-			0 : (client->pos_x >= xres ? xres : client->pos_x);
+		client->pos_x = clamp_val(client->pos_x, 0, xres);
+
 		client->pos_y += packet->dy;
-		client->pos_y = client->pos_y < 0 ?
-			0 : (client->pos_y >= yres ? yres : client->pos_y);
+		client->pos_y = clamp_val(client->pos_y, 0, yres);
 
 		p->dx += packet->dx;
 		p->dy += packet->dy;
@@ -571,44 +571,50 @@ static int mousedev_open(struct inode *inode, struct file *file)
 	return error;
 }
 
-static inline int mousedev_limit_delta(int delta, int limit)
-{
-	return delta > limit ? limit : (delta < -limit ? -limit : delta);
-}
-
-static void mousedev_packet(struct mousedev_client *client,
-			    signed char *ps2_data)
+static void mousedev_packet(struct mousedev_client *client, u8 *ps2_data)
 {
 	struct mousedev_motion *p = &client->packets[client->tail];
+	s8 dx, dy, dz;
+
+	dx = clamp_val(p->dx, -127, 127);
+	p->dx -= dx;
+
+	dy = clamp_val(p->dy, -127, 127);
+	p->dy -= dy;
 
-	ps2_data[0] = 0x08 |
-		((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
-	ps2_data[1] = mousedev_limit_delta(p->dx, 127);
-	ps2_data[2] = mousedev_limit_delta(p->dy, 127);
-	p->dx -= ps2_data[1];
-	p->dy -= ps2_data[2];
+	ps2_data[0] = BIT(3);
+	ps2_data[0] |= ((dx & BIT(7)) >> 3) | ((dy & BIT(7)) >> 2);
+	ps2_data[0] |= p->buttons & 0x07;
+	ps2_data[1] = dx;
+	ps2_data[2] = dy;
 
 	switch (client->mode) {
 	case MOUSEDEV_EMUL_EXPS:
-		ps2_data[3] = mousedev_limit_delta(p->dz, 7);
-		p->dz -= ps2_data[3];
-		ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
+		dz = clamp_val(p->dz, -7, 7);
+		p->dz -= dz;
+
+		ps2_data[3] = (dz & 0x0f) | ((p->buttons & 0x18) << 1);
 		client->bufsiz = 4;
 		break;
 
 	case MOUSEDEV_EMUL_IMPS:
-		ps2_data[0] |=
-			((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
-		ps2_data[3] = mousedev_limit_delta(p->dz, 127);
-		p->dz -= ps2_data[3];
+		dz = clamp_val(p->dz, -127, 127);
+		p->dz -= dz;
+
+		ps2_data[0] |= ((p->buttons & 0x10) >> 3) |
+			       ((p->buttons & 0x08) >> 1);
+		ps2_data[3] = dz;
+
 		client->bufsiz = 4;
 		break;
 
 	case MOUSEDEV_EMUL_PS2:
 	default:
-		ps2_data[0] |=
-			((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
 		p->dz = 0;
+
+		ps2_data[0] |= ((p->buttons & 0x10) >> 3) |
+			       ((p->buttons & 0x08) >> 1);
+
 		client->bufsiz = 3;
 		break;
 	}
@@ -714,7 +720,7 @@ static ssize_t mousedev_read(struct file *file, char __user *buffer,
 {
 	struct mousedev_client *client = file->private_data;
 	struct mousedev *mousedev = client->mousedev;
-	signed char data[sizeof(client->ps2)];
+	u8 data[sizeof(client->ps2)];
 	int retval = 0;
 
 	if (!client->ready && !client->buffer && mousedev->exist &&
diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
index 6dca3c0fbb4a0f5607a04588e4b4cf79e40caa10..ae966e333a2f47242eca6443eabf4d38c575813a 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -334,7 +334,7 @@ static struct attribute *rmi_f01_attrs[] = {
 	NULL
 };
 
-static struct attribute_group rmi_f01_attr_group = {
+static const struct attribute_group rmi_f01_attr_group = {
 	.attrs = rmi_f01_attrs,
 };
 
diff --git a/drivers/input/rmi4/rmi_f34.c b/drivers/input/rmi4/rmi_f34.c
index b8ee78e0d61f03d4cafc1d8bc441d545ded1210d..4cfe9703a8e712f3f116ece40f04cd33f00feb0f 100644
--- a/drivers/input/rmi4/rmi_f34.c
+++ b/drivers/input/rmi4/rmi_f34.c
@@ -516,7 +516,7 @@ static struct attribute *rmi_firmware_attrs[] = {
 	NULL
 };
 
-static struct attribute_group rmi_firmware_attr_group = {
+static const struct attribute_group rmi_firmware_attr_group = {
 	.attrs = rmi_firmware_attrs,
 };
 
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index c3d05b4d3118d908434eb594659a97e0b4703b05..21488c048fa37c94b363c863046a069ccd046403 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -292,6 +292,17 @@ config SERIO_SUN4I_PS2
 	  To compile this driver as a module, choose M here: the
 	  module will be called sun4i-ps2.
 
+config SERIO_GPIO_PS2
+	tristate "GPIO PS/2 bit banging driver"
+	depends on GPIOLIB
+	help
+	  Say Y here if you want PS/2 bit banging support via GPIO.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ps2-gpio.
+
+	  If you are unsure, say N.
+
 config USERIO
 	tristate "User space serio port driver support"
 	help
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 2374ef9b33d788cee5693bb52905aabcd965df61..767bd9b6e1ed05861836f0879f4de9ceb08c64c3 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -30,4 +30,5 @@ obj-$(CONFIG_SERIO_APBPS2)	+= apbps2.o
 obj-$(CONFIG_SERIO_OLPC_APSP)	+= olpc_apsp.o
 obj-$(CONFIG_HYPERV_KEYBOARD)	+= hyperv-keyboard.o
 obj-$(CONFIG_SERIO_SUN4I_PS2)	+= sun4i-ps2.o
+obj-$(CONFIG_SERIO_GPIO_PS2)	+= ps2-gpio.o
 obj-$(CONFIG_USERIO)		+= userio.o
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index c6606cacb6a7ad0925d27a51138ad7a9c36ca5ac..ff3875cf3da1e615d792fb6e41274d314d5475ad 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -187,7 +187,7 @@ static int __maybe_unused amba_kmi_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(amba_kmi_dev_pm_ops, NULL, amba_kmi_resume);
 
-static struct amba_id amba_kmi_idtable[] = {
+static const struct amba_id amba_kmi_idtable[] = {
 	{
 		.id	= 0x00041050,
 		.mask	= 0x000fffff,
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index f932a83b4990210d8daeb25c1d2482b958c3719e..ae81e57e13b9519dbe3b49697a0db5322f2dd0a7 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -927,7 +927,7 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
 	return 0;
 }
 
-static struct pnp_device_id pnp_kbd_devids[] = {
+static const struct pnp_device_id pnp_kbd_devids[] = {
 	{ .id = "PNP0300", .driver_data = 0 },
 	{ .id = "PNP0301", .driver_data = 0 },
 	{ .id = "PNP0302", .driver_data = 0 },
@@ -957,7 +957,7 @@ static struct pnp_driver i8042_pnp_kbd_driver = {
 	},
 };
 
-static struct pnp_device_id pnp_aux_devids[] = {
+static const struct pnp_device_id pnp_aux_devids[] = {
 	{ .id = "AUI0200", .driver_data = 0 },
 	{ .id = "FJC6000", .driver_data = 0 },
 	{ .id = "FJC6001", .driver_data = 0 },
diff --git a/drivers/input/serio/ps2-gpio.c b/drivers/input/serio/ps2-gpio.c
new file mode 100644
index 0000000000000000000000000000000000000000..b50e3817f3c40917535fb3230d884952115cb058
--- /dev/null
+++ b/drivers/input/serio/ps2-gpio.c
@@ -0,0 +1,453 @@
+/*
+ * GPIO based serio bus driver for bit banging the PS/2 protocol
+ *
+ * Author: Danilo Krummrich <danilokrummrich@dk-develop.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/preempt.h>
+#include <linux/property.h>
+#include <linux/of.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+
+#define DRIVER_NAME		"ps2-gpio"
+
+#define PS2_MODE_RX		0
+#define PS2_MODE_TX		1
+
+#define PS2_START_BIT		0
+#define PS2_DATA_BIT0		1
+#define PS2_DATA_BIT1		2
+#define PS2_DATA_BIT2		3
+#define PS2_DATA_BIT3		4
+#define PS2_DATA_BIT4		5
+#define PS2_DATA_BIT5		6
+#define PS2_DATA_BIT6		7
+#define PS2_DATA_BIT7		8
+#define PS2_PARITY_BIT		9
+#define PS2_STOP_BIT		10
+#define PS2_TX_TIMEOUT		11
+#define PS2_ACK_BIT		12
+
+#define PS2_DEV_RET_ACK		0xfa
+#define PS2_DEV_RET_NACK	0xfe
+
+#define PS2_CMD_RESEND		0xfe
+
+struct ps2_gpio_data {
+	struct device *dev;
+	struct serio *serio;
+	unsigned char mode;
+	struct gpio_desc *gpio_clk;
+	struct gpio_desc *gpio_data;
+	bool write_enable;
+	int irq;
+	unsigned char rx_cnt;
+	unsigned char rx_byte;
+	unsigned char tx_cnt;
+	unsigned char tx_byte;
+	struct completion tx_done;
+	struct mutex tx_mutex;
+	struct delayed_work tx_work;
+};
+
+static int ps2_gpio_open(struct serio *serio)
+{
+	struct ps2_gpio_data *drvdata = serio->port_data;
+
+	enable_irq(drvdata->irq);
+	return 0;
+}
+
+static void ps2_gpio_close(struct serio *serio)
+{
+	struct ps2_gpio_data *drvdata = serio->port_data;
+
+	disable_irq(drvdata->irq);
+}
+
+static int __ps2_gpio_write(struct serio *serio, unsigned char val)
+{
+	struct ps2_gpio_data *drvdata = serio->port_data;
+
+	disable_irq_nosync(drvdata->irq);
+	gpiod_direction_output(drvdata->gpio_clk, 0);
+
+	drvdata->mode = PS2_MODE_TX;
+	drvdata->tx_byte = val;
+
+	schedule_delayed_work(&drvdata->tx_work, usecs_to_jiffies(200));
+
+	return 0;
+}
+
+static int ps2_gpio_write(struct serio *serio, unsigned char val)
+{
+	struct ps2_gpio_data *drvdata = serio->port_data;
+	int ret = 0;
+
+	if (in_task()) {
+		mutex_lock(&drvdata->tx_mutex);
+		__ps2_gpio_write(serio, val);
+		if (!wait_for_completion_timeout(&drvdata->tx_done,
+						 msecs_to_jiffies(10000)))
+			ret = SERIO_TIMEOUT;
+		mutex_unlock(&drvdata->tx_mutex);
+	} else {
+		__ps2_gpio_write(serio, val);
+	}
+
+	return ret;
+}
+
+static void ps2_gpio_tx_work_fn(struct work_struct *work)
+{
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct ps2_gpio_data *drvdata = container_of(dwork,
+						    struct ps2_gpio_data,
+						    tx_work);
+
+	enable_irq(drvdata->irq);
+	gpiod_direction_output(drvdata->gpio_data, 0);
+	gpiod_direction_input(drvdata->gpio_clk);
+}
+
+static irqreturn_t ps2_gpio_irq_rx(struct ps2_gpio_data *drvdata)
+{
+	unsigned char byte, cnt;
+	int data;
+	int rxflags = 0;
+	static unsigned long old_jiffies;
+
+	byte = drvdata->rx_byte;
+	cnt = drvdata->rx_cnt;
+
+	if (old_jiffies == 0)
+		old_jiffies = jiffies;
+
+	if ((jiffies - old_jiffies) > usecs_to_jiffies(100)) {
+		dev_err(drvdata->dev,
+			"RX: timeout, probably we missed an interrupt\n");
+		goto err;
+	}
+	old_jiffies = jiffies;
+
+	data = gpiod_get_value(drvdata->gpio_data);
+	if (unlikely(data < 0)) {
+		dev_err(drvdata->dev, "RX: failed to get data gpio val: %d\n",
+			data);
+		goto err;
+	}
+
+	switch (cnt) {
+	case PS2_START_BIT:
+		/* start bit should be low */
+		if (unlikely(data)) {
+			dev_err(drvdata->dev, "RX: start bit should be low\n");
+			goto err;
+		}
+		break;
+	case PS2_DATA_BIT0:
+	case PS2_DATA_BIT1:
+	case PS2_DATA_BIT2:
+	case PS2_DATA_BIT3:
+	case PS2_DATA_BIT4:
+	case PS2_DATA_BIT5:
+	case PS2_DATA_BIT6:
+	case PS2_DATA_BIT7:
+		/* processing data bits */
+		if (data)
+			byte |= (data << (cnt - 1));
+		break;
+	case PS2_PARITY_BIT:
+		/* check odd parity */
+		if (!((hweight8(byte) & 1) ^ data)) {
+			rxflags |= SERIO_PARITY;
+			dev_warn(drvdata->dev, "RX: parity error\n");
+			if (!drvdata->write_enable)
+				goto err;
+		}
+
+		/* Do not send spurious ACK's and NACK's when write fn is
+		 * not provided.
+		 */
+		if (!drvdata->write_enable) {
+			if (byte == PS2_DEV_RET_NACK)
+				goto err;
+			else if (byte == PS2_DEV_RET_ACK)
+				break;
+		}
+
+		/* Let's send the data without waiting for the stop bit to be
+		 * sent. It may happen that we miss the stop bit. When this
+		 * happens we have no way to recover from this, certainly
+		 * missing the parity bit would be recognized when processing
+		 * the stop bit. When missing both, data is lost.
+		 */
+		serio_interrupt(drvdata->serio, byte, rxflags);
+		dev_dbg(drvdata->dev, "RX: sending byte 0x%x\n", byte);
+		break;
+	case PS2_STOP_BIT:
+		/* stop bit should be high */
+		if (unlikely(!data)) {
+			dev_err(drvdata->dev, "RX: stop bit should be high\n");
+			goto err;
+		}
+		cnt = byte = 0;
+		old_jiffies = 0;
+		goto end; /* success */
+	default:
+		dev_err(drvdata->dev, "RX: got out of sync with the device\n");
+		goto err;
+	}
+
+	cnt++;
+	goto end; /* success */
+
+err:
+	cnt = byte = 0;
+	old_jiffies = 0;
+	__ps2_gpio_write(drvdata->serio, PS2_CMD_RESEND);
+end:
+	drvdata->rx_cnt = cnt;
+	drvdata->rx_byte = byte;
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ps2_gpio_irq_tx(struct ps2_gpio_data *drvdata)
+{
+	unsigned char byte, cnt;
+	int data;
+	static unsigned long old_jiffies;
+
+	cnt = drvdata->tx_cnt;
+	byte = drvdata->tx_byte;
+
+	if (old_jiffies == 0)
+		old_jiffies = jiffies;
+
+	if ((jiffies - old_jiffies) > usecs_to_jiffies(100)) {
+		dev_err(drvdata->dev,
+			"TX: timeout, probably we missed an interrupt\n");
+		goto err;
+	}
+	old_jiffies = jiffies;
+
+	switch (cnt) {
+	case PS2_START_BIT:
+		/* should never happen */
+		dev_err(drvdata->dev,
+			"TX: start bit should have been sent already\n");
+		goto err;
+	case PS2_DATA_BIT0:
+	case PS2_DATA_BIT1:
+	case PS2_DATA_BIT2:
+	case PS2_DATA_BIT3:
+	case PS2_DATA_BIT4:
+	case PS2_DATA_BIT5:
+	case PS2_DATA_BIT6:
+	case PS2_DATA_BIT7:
+		data = byte & BIT(cnt - 1);
+		gpiod_set_value(drvdata->gpio_data, data);
+		break;
+	case PS2_PARITY_BIT:
+		/* do odd parity */
+		data = !(hweight8(byte) & 1);
+		gpiod_set_value(drvdata->gpio_data, data);
+		break;
+	case PS2_STOP_BIT:
+		/* release data line to generate stop bit */
+		gpiod_direction_input(drvdata->gpio_data);
+		break;
+	case PS2_TX_TIMEOUT:
+		/* Devices generate one extra clock pulse before sending the
+		 * acknowledgment.
+		 */
+		break;
+	case PS2_ACK_BIT:
+		gpiod_direction_input(drvdata->gpio_data);
+		data = gpiod_get_value(drvdata->gpio_data);
+		if (data) {
+			dev_warn(drvdata->dev, "TX: received NACK, retry\n");
+			goto err;
+		}
+
+		drvdata->mode = PS2_MODE_RX;
+		complete(&drvdata->tx_done);
+
+		cnt = 1;
+		old_jiffies = 0;
+		goto end; /* success */
+	default:
+		/* Probably we missed the stop bit. Therefore we release data
+		 * line and try again.
+		 */
+		gpiod_direction_input(drvdata->gpio_data);
+		dev_err(drvdata->dev, "TX: got out of sync with the device\n");
+		goto err;
+	}
+
+	cnt++;
+	goto end; /* success */
+
+err:
+	cnt = 1;
+	old_jiffies = 0;
+	gpiod_direction_input(drvdata->gpio_data);
+	__ps2_gpio_write(drvdata->serio, drvdata->tx_byte);
+end:
+	drvdata->tx_cnt = cnt;
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ps2_gpio_irq(int irq, void *dev_id)
+{
+	struct ps2_gpio_data *drvdata = dev_id;
+
+	return drvdata->mode ? ps2_gpio_irq_tx(drvdata) :
+		ps2_gpio_irq_rx(drvdata);
+}
+
+static int ps2_gpio_get_props(struct device *dev,
+				 struct ps2_gpio_data *drvdata)
+{
+	drvdata->gpio_data = devm_gpiod_get(dev, "data", GPIOD_IN);
+	if (IS_ERR(drvdata->gpio_data)) {
+		dev_err(dev, "failed to request data gpio: %ld",
+			PTR_ERR(drvdata->gpio_data));
+		return PTR_ERR(drvdata->gpio_data);
+	}
+
+	drvdata->gpio_clk = devm_gpiod_get(dev, "clk", GPIOD_IN);
+	if (IS_ERR(drvdata->gpio_clk)) {
+		dev_err(dev, "failed to request clock gpio: %ld",
+			PTR_ERR(drvdata->gpio_clk));
+		return PTR_ERR(drvdata->gpio_clk);
+	}
+
+	drvdata->write_enable = device_property_read_bool(dev,
+				"write-enable");
+
+	return 0;
+}
+
+static int ps2_gpio_probe(struct platform_device *pdev)
+{
+	struct ps2_gpio_data *drvdata;
+	struct serio *serio;
+	struct device *dev = &pdev->dev;
+	int error;
+
+	drvdata = devm_kzalloc(dev, sizeof(struct ps2_gpio_data), GFP_KERNEL);
+	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!drvdata || !serio) {
+		error = -ENOMEM;
+		goto err_free_serio;
+	}
+
+	error = ps2_gpio_get_props(dev, drvdata);
+	if (error)
+		goto err_free_serio;
+
+	if (gpiod_cansleep(drvdata->gpio_data) ||
+	    gpiod_cansleep(drvdata->gpio_clk)) {
+		dev_err(dev, "GPIO data or clk are connected via slow bus\n");
+		error = -EINVAL;
+	}
+
+	drvdata->irq = platform_get_irq(pdev, 0);
+	if (drvdata->irq < 0) {
+		dev_err(dev, "failed to get irq from platform resource: %d\n",
+			drvdata->irq);
+		error = drvdata->irq;
+		goto err_free_serio;
+	}
+
+	error = devm_request_irq(dev, drvdata->irq, ps2_gpio_irq,
+				 IRQF_NO_THREAD, DRIVER_NAME, drvdata);
+	if (error) {
+		dev_err(dev, "failed to request irq %d: %d\n",
+			drvdata->irq, error);
+		goto err_free_serio;
+	}
+
+	/* Keep irq disabled until serio->open is called. */
+	disable_irq(drvdata->irq);
+
+	serio->id.type = SERIO_8042;
+	serio->open = ps2_gpio_open;
+	serio->close = ps2_gpio_close;
+	/* Write can be enabled in platform/dt data, but possibly it will not
+	 * work because of the tough timings.
+	 */
+	serio->write = drvdata->write_enable ? ps2_gpio_write : NULL;
+	serio->port_data = drvdata;
+	serio->dev.parent = dev;
+	strlcpy(serio->name, dev_name(dev), sizeof(serio->name));
+	strlcpy(serio->phys, dev_name(dev), sizeof(serio->phys));
+
+	drvdata->serio = serio;
+	drvdata->dev = dev;
+	drvdata->mode = PS2_MODE_RX;
+
+	/* Tx count always starts at 1, as the start bit is sent implicitly by
+	 * host-to-device communication initialization.
+	 */
+	drvdata->tx_cnt = 1;
+
+	INIT_DELAYED_WORK(&drvdata->tx_work, ps2_gpio_tx_work_fn);
+	init_completion(&drvdata->tx_done);
+	mutex_init(&drvdata->tx_mutex);
+
+	serio_register_port(serio);
+	platform_set_drvdata(pdev, drvdata);
+
+	return 0;	/* success */
+
+err_free_serio:
+	kfree(serio);
+	return error;
+}
+
+static int ps2_gpio_remove(struct platform_device *pdev)
+{
+	struct ps2_gpio_data *drvdata = platform_get_drvdata(pdev);
+
+	serio_unregister_port(drvdata->serio);
+	return 0;
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id ps2_gpio_match[] = {
+	{ .compatible = "ps2-gpio", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ps2_gpio_match);
+#endif
+
+static struct platform_driver ps2_gpio_driver = {
+	.probe		= ps2_gpio_probe,
+	.remove		= ps2_gpio_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = of_match_ptr(ps2_gpio_match),
+	},
+};
+module_platform_driver(ps2_gpio_driver);
+
+MODULE_AUTHOR("Danilo Krummrich <danilokrummrich@dk-develop.de>");
+MODULE_DESCRIPTION("GPIO PS2 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 30d6230d48f7c45d216f7fcdcb04056cc7448df1..24a90c8db5b3c6499da513dd6e60ee9483484e66 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -469,7 +469,7 @@ static struct attribute *serio_device_id_attrs[] = {
 	NULL
 };
 
-static struct attribute_group serio_id_attr_group = {
+static const struct attribute_group serio_id_attr_group = {
 	.name	= "id",
 	.attrs	= serio_device_id_attrs,
 };
@@ -489,7 +489,7 @@ static struct attribute *serio_device_attrs[] = {
 	NULL
 };
 
-static struct attribute_group serio_device_attr_group = {
+static const struct attribute_group serio_device_attr_group = {
 	.attrs	= serio_device_attrs,
 };
 
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 71ef5d65a0c63a493e8252f2ba2639c33c711b13..516f9fe77a1770b414ea69da4633277d44ab105e 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -410,7 +410,7 @@ static void serio_raw_disconnect(struct serio *serio)
 	serio_set_drvdata(serio, NULL);
 }
 
-static struct serio_device_id serio_raw_serio_ids[] = {
+static const struct serio_device_id serio_raw_serio_ids[] = {
 	{
 		.type	= SERIO_8042,
 		.proto	= SERIO_ANY,
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index 14c40892ed82718246be6a60deed23e71e33e4d4..07de1b49293caf67874555885356af2a27a05559 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -45,8 +45,10 @@
 #define XPS2_STATUS_RX_FULL	0x00000001 /* Receive Full  */
 #define XPS2_STATUS_TX_FULL	0x00000002 /* Transmit Full  */
 
-/* Bit definitions for ISR/IER registers. Both the registers have the same bit
- * definitions and are only defined once. */
+/*
+ * Bit definitions for ISR/IER registers. Both the registers have the same bit
+ * definitions and are only defined once.
+ */
 #define XPS2_IPIXR_WDT_TOUT	0x00000001 /* Watchdog Timeout Interrupt */
 #define XPS2_IPIXR_TX_NOACK	0x00000002 /* Transmit No ACK Interrupt */
 #define XPS2_IPIXR_TX_ACK	0x00000004 /* Transmit ACK (Data) Interrupt */
@@ -292,8 +294,10 @@ static int xps2_of_probe(struct platform_device *ofdev)
 	/* Disable all the interrupts, just in case */
 	out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0);
 
-	/* Reset the PS2 device and abort any current transaction, to make sure
-	 * we have the PS2 in a good state */
+	/*
+	 * Reset the PS2 device and abort any current transaction,
+	 * to make sure we have the PS2 in a good state.
+	 */
 	out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET);
 
 	dev_info(dev, "Xilinx PS2 at 0x%08llX mapped to 0x%p, irq=%d\n",
diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c
index e86e377a90f5252b1e7acf5147b476e8149d3af2..aebb3f9090cd24f8d1438efa991544e66e3fd4be 100644
--- a/drivers/input/tablet/acecad.c
+++ b/drivers/input/tablet/acecad.c
@@ -260,7 +260,7 @@ static void usb_acecad_disconnect(struct usb_interface *intf)
 	kfree(acecad);
 }
 
-static struct usb_device_id usb_acecad_id_table [] = {
+static const struct usb_device_id usb_acecad_id_table[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 },
 	{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302),	 .driver_info = 1 },
 	{ }
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index d67547bded3ea844e396280e406ce723a08198d5..0b55e1f375b397627915790e1876a509ae1d5276 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -1676,7 +1676,7 @@ static struct attribute *aiptek_attributes[] = {
 	NULL
 };
 
-static struct attribute_group aiptek_attribute_group = {
+static const struct attribute_group aiptek_attribute_group = {
 	.attrs	= aiptek_attributes,
 };
 
diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c
index 4d9d64908b595f9828e8e82e47e57b6b2935c07f..a41c3ff7c9afa197fffca585e929c6b878ddad39 100644
--- a/drivers/input/tablet/kbtab.c
+++ b/drivers/input/tablet/kbtab.c
@@ -88,7 +88,7 @@ static void kbtab_irq(struct urb *urb)
 			__func__, retval);
 }
 
-static struct usb_device_id kbtab_ids[] = {
+static const struct usb_device_id kbtab_ids[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_KBGEAR, 0x1001), .driver_info = 0 },
 	{ }
 };
diff --git a/drivers/input/tablet/wacom_serial4.c b/drivers/input/tablet/wacom_serial4.c
index 20ab802461e774c6199801cffed3967f804256a2..38bfaca48eab188cd50404428976a2e1661a172b 100644
--- a/drivers/input/tablet/wacom_serial4.c
+++ b/drivers/input/tablet/wacom_serial4.c
@@ -594,7 +594,7 @@ static int wacom_connect(struct serio *serio, struct serio_driver *drv)
 	return err;
 }
 
-static struct serio_device_id wacom_serio_ids[] = {
+static const struct serio_device_id wacom_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_WACOM_IV,
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 735a0be1ad9533f66954e402dcd88766d6322a1e..a2f45aefce08a166749e6fd89067dafaced7eaa2 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -499,7 +499,7 @@ static struct attribute *ads7846_attributes[] = {
 	NULL,
 };
 
-static struct attribute_group ads7846_attr_group = {
+static const struct attribute_group ads7846_attr_group = {
 	.attrs = ads7846_attributes,
 	.is_visible = ads7846_is_visible,
 };
@@ -599,7 +599,7 @@ static struct attribute *ads784x_attributes[] = {
 	NULL,
 };
 
-static struct attribute_group ads784x_attr_group = {
+static const struct attribute_group ads784x_attr_group = {
 	.attrs = ads784x_attributes,
 };
 
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index dd042a9b0aaacc208056376b27a5fd7bf5755f6c..7659bc48f1db8e76490e2451ad552aa1b7e17fcb 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -28,6 +28,7 @@
 #include <linux/interrupt.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <linux/gpio/consumer.h>
 #include <asm/unaligned.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -300,6 +301,7 @@ struct mxt_data {
 	u8 multitouch;
 	struct t7_config t7_cfg;
 	struct mxt_dbg dbg;
+	struct gpio_desc *reset_gpio;
 
 	/* Cached parameters from object table */
 	u16 T5_address;
@@ -3117,11 +3119,9 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	if (IS_ERR(pdata))
 		return PTR_ERR(pdata);
 
-	data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
-	if (!data) {
-		dev_err(&client->dev, "Failed to allocate memory\n");
+	data = devm_kzalloc(&client->dev, sizeof(struct mxt_data), GFP_KERNEL);
+	if (!data)
 		return -ENOMEM;
-	}
 
 	snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
 		 client->adapter->nr, client->addr);
@@ -3135,19 +3135,40 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	init_completion(&data->reset_completion);
 	init_completion(&data->crc_completion);
 
-	error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
-				     pdata->irqflags | IRQF_ONESHOT,
-				     client->name, data);
+	data->reset_gpio = devm_gpiod_get_optional(&client->dev,
+						   "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(data->reset_gpio)) {
+		error = PTR_ERR(data->reset_gpio);
+		dev_err(&client->dev, "Failed to get reset gpio: %d\n", error);
+		return error;
+	}
+
+	error = devm_request_threaded_irq(&client->dev, client->irq,
+					  NULL, mxt_interrupt,
+					  pdata->irqflags | IRQF_ONESHOT,
+					  client->name, data);
 	if (error) {
 		dev_err(&client->dev, "Failed to register interrupt\n");
-		goto err_free_mem;
+		return error;
+	}
+
+	if (data->reset_gpio) {
+		data->in_bootloader = true;
+		msleep(MXT_RESET_TIME);
+		reinit_completion(&data->bl_completion);
+		gpiod_set_value(data->reset_gpio, 1);
+		error = mxt_wait_for_completion(data, &data->bl_completion,
+						MXT_RESET_TIMEOUT);
+		if (error)
+			return error;
+		data->in_bootloader = false;
 	}
 
 	disable_irq(client->irq);
 
 	error = mxt_initialize(data);
 	if (error)
-		goto err_free_irq;
+		return error;
 
 	error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
 	if (error) {
@@ -3161,10 +3182,6 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 err_free_object:
 	mxt_free_input_device(data);
 	mxt_free_object_table(data);
-err_free_irq:
-	free_irq(client->irq, data);
-err_free_mem:
-	kfree(data);
 	return error;
 }
 
@@ -3172,11 +3189,10 @@ static int mxt_remove(struct i2c_client *client)
 {
 	struct mxt_data *data = i2c_get_clientdata(client);
 
+	disable_irq(data->irq);
 	sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
-	free_irq(data->irq, data);
 	mxt_free_input_device(data);
 	mxt_free_object_table(data);
-	kfree(data);
 
 	return 0;
 }
diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c
index 86237a910876ef30ba9b0af5090c135b75ab4f66..5b1b66fffbe301b0fcb9a83a2f16f4fb13058eb4 100644
--- a/drivers/input/touchscreen/dynapro.c
+++ b/drivers/input/touchscreen/dynapro.c
@@ -164,7 +164,7 @@ static int dynapro_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id dynapro_serio_ids[] = {
+static const struct serio_device_id dynapro_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_DYNAPRO,
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index 872750eeca9325cbb3a9140b0686da4a2f5cbdfa..0f4cda7282a2c72779dc8cb131945ffa97200303 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -1066,7 +1066,7 @@ static struct attribute *elants_attributes[] = {
 	NULL
 };
 
-static struct attribute_group elants_attribute_group = {
+static const struct attribute_group elants_attribute_group = {
 	.attrs = elants_attributes,
 };
 
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index 8051a4b704ea3b99f5d11ebc4dfd8857bfbb7a09..83433e8efff7066c864f61268c023ac946f90151 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -381,7 +381,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id elo_serio_ids[] = {
+static const struct serio_device_id elo_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_ELO,
diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c
index d0e46a7e183b7aa346f89979eb6589918bff859c..a0fbb454499dd2b03e61487b55c2b0a810899b50 100644
--- a/drivers/input/touchscreen/fujitsu_ts.c
+++ b/drivers/input/touchscreen/fujitsu_ts.c
@@ -151,7 +151,7 @@ static int fujitsu_connect(struct serio *serio, struct serio_driver *drv)
 /*
  * The serio driver structure.
  */
-static struct serio_device_id fujitsu_serio_ids[] = {
+static const struct serio_device_id fujitsu_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_FUJITSU,
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index e2ee626152730795519f57e51e0ac99810112f21..481586909d281f5fd86d6655bddb7747536344f8 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -162,7 +162,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id gunze_serio_ids[] = {
+static const struct serio_device_id gunze_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_GUNZE,
diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c
index ecb1e0e01328a95680d3d8f7c64c5dd38c5ccd7f..eb052d559e547f4422a7294d3a6601fa13be4234 100644
--- a/drivers/input/touchscreen/hampshire.c
+++ b/drivers/input/touchscreen/hampshire.c
@@ -163,7 +163,7 @@ static int hampshire_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id hampshire_serio_ids[] = {
+static const struct serio_device_id hampshire_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_HAMPSHIRE,
diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c
index adb80b65a259683983a041d86bc6a3c0b28fcad6..b9bc56233ccce742daeecc4df42b0530fbe9328c 100644
--- a/drivers/input/touchscreen/inexio.c
+++ b/drivers/input/touchscreen/inexio.c
@@ -165,7 +165,7 @@ static int inexio_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id inexio_serio_ids[] = {
+static const struct serio_device_id inexio_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_INEXIO,
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index 9b5552a2616922a849573bad553080c130a976c9..a3707fad4d1c8b4862e121c38c0ba54f9beffbc6 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -178,7 +178,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id mtouch_serio_ids[] = {
+static const struct serio_device_id mtouch_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_MICROTOUCH,
diff --git a/drivers/input/touchscreen/mxs-lradc-ts.c b/drivers/input/touchscreen/mxs-lradc-ts.c
index 58c016cd68098dbd54b7c3a56e5f62e06ed03211..3707e927f770c8763c277768d0c872b87c4bf048 100644
--- a/drivers/input/touchscreen/mxs-lradc-ts.c
+++ b/drivers/input/touchscreen/mxs-lradc-ts.c
@@ -30,7 +30,7 @@
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
 
-const char *mxs_lradc_ts_irq_names[] = {
+static const char * const mxs_lradc_ts_irq_names[] = {
 	"mxs-lradc-touchscreen",
 	"mxs-lradc-channel6",
 	"mxs-lradc-channel7",
@@ -630,9 +630,11 @@ static int mxs_lradc_ts_probe(struct platform_device *pdev)
 	spin_lock_init(&ts->lock);
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iores)
+		return -EINVAL;
 	ts->base = devm_ioremap(dev, iores->start, resource_size(iores));
-	if (IS_ERR(ts->base))
-		return PTR_ERR(ts->base);
+	if (!ts->base)
+		return -ENOMEM;
 
 	ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires",
 				   &ts_wires);
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index 417d87379265db4fcafccb0f5de355ccb3b1ae46..6e6d7fd98cd2681e4818a62f79836f1ddaa86dfa 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -293,7 +293,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id pm_serio_ids[] = {
+static const struct serio_device_id pm_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_PENMOUNT,
diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index 1252e49ccfa1c42455667e7b775343107853d5ba..4f1d3fd5d4121dbd6c517eda7c862ea9ae6b802e 100644
--- a/drivers/input/touchscreen/raydium_i2c_ts.c
+++ b/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -939,7 +939,7 @@ static struct attribute *raydium_i2c_attributes[] = {
 	NULL
 };
 
-static struct attribute_group raydium_i2c_attribute_group = {
+static const struct attribute_group raydium_i2c_attribute_group = {
 	.attrs = raydium_i2c_attributes,
 };
 
diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c
index d07dd29d4848f03d91e40bd762078b969a23bac1..d2e14d9e59753288168d50de4d8e2e880ed40ce3 100644
--- a/drivers/input/touchscreen/sun4i-ts.c
+++ b/drivers/input/touchscreen/sun4i-ts.c
@@ -206,7 +206,7 @@ static int sun4i_get_tz_temp(void *data, int *temp)
 	return sun4i_get_temp(data, temp);
 }
 
-static struct thermal_zone_of_device_ops sun4i_ts_tz_ops = {
+static const struct thermal_zone_of_device_ops sun4i_ts_tz_ops = {
 	.get_temp = sun4i_get_tz_temp,
 };
 
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index 128e5bd747203b92b9eae68777d44b01b946fddc..f16f8358c70aab09da0cda18a4fa623f7d8a027a 100644
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -59,7 +59,7 @@ struct sur40_blob {
 	__le16 blob_id;
 
 	u8 action;         /* 0x02 = enter/exit, 0x03 = update (?) */
-	u8 unknown;        /* always 0x01 or 0x02 (no idea what this is?) */
+	u8 type;           /* bitmask (0x01 blob,  0x02 touch, 0x04 tag) */
 
 	__le16 bb_pos_x;   /* upper left corner of bounding box */
 	__le16 bb_pos_y;
@@ -133,12 +133,19 @@ struct sur40_image_header {
 
 /* control commands */
 #define SUR40_GET_VERSION 0xb0 /* 12 bytes string    */
-#define SUR40_UNKNOWN1    0xb3 /*  5 bytes           */
-#define SUR40_UNKNOWN2    0xc1 /* 24 bytes           */
+#define SUR40_ACCEL_CAPS  0xb3 /*  5 bytes           */
+#define SUR40_SENSOR_CAPS 0xc1 /* 24 bytes           */
+
+#define SUR40_POKE        0xc5 /* poke register byte */
+#define SUR40_PEEK        0xc4 /* 48 bytes registers */
 
 #define SUR40_GET_STATE   0xc5 /*  4 bytes state (?) */
 #define SUR40_GET_SENSORS 0xb1 /*  8 bytes sensors   */
 
+#define SUR40_BLOB	0x01
+#define SUR40_TOUCH	0x02
+#define SUR40_TAG	0x04
+
 static const struct v4l2_pix_format sur40_pix_format[] = {
 	{
 		.pixelformat = V4L2_TCH_FMT_TU08,
@@ -238,11 +245,11 @@ static int sur40_init(struct sur40_state *dev)
 	if (result < 0)
 		goto error;
 
-	result = sur40_command(dev, SUR40_UNKNOWN2,    0x00, buffer, 24);
+	result = sur40_command(dev, SUR40_SENSOR_CAPS, 0x00, buffer, 24);
 	if (result < 0)
 		goto error;
 
-	result = sur40_command(dev, SUR40_UNKNOWN1,    0x00, buffer,  5);
+	result = sur40_command(dev, SUR40_ACCEL_CAPS, 0x00, buffer, 5);
 	if (result < 0)
 		goto error;
 
@@ -289,20 +296,24 @@ static void sur40_close(struct input_polled_dev *polldev)
 static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input)
 {
 	int wide, major, minor;
+	int bb_size_x, bb_size_y, pos_x, pos_y, ctr_x, ctr_y, slotnum;
 
-	int bb_size_x = le16_to_cpu(blob->bb_size_x);
-	int bb_size_y = le16_to_cpu(blob->bb_size_y);
-
-	int pos_x = le16_to_cpu(blob->pos_x);
-	int pos_y = le16_to_cpu(blob->pos_y);
-
-	int ctr_x = le16_to_cpu(blob->ctr_x);
-	int ctr_y = le16_to_cpu(blob->ctr_y);
+	if (blob->type != SUR40_TOUCH)
+		return;
 
-	int slotnum = input_mt_get_slot_by_key(input, blob->blob_id);
+	slotnum = input_mt_get_slot_by_key(input, blob->blob_id);
 	if (slotnum < 0 || slotnum >= MAX_CONTACTS)
 		return;
 
+	bb_size_x = le16_to_cpu(blob->bb_size_x);
+	bb_size_y = le16_to_cpu(blob->bb_size_y);
+
+	pos_x = le16_to_cpu(blob->pos_x);
+	pos_y = le16_to_cpu(blob->pos_y);
+
+	ctr_x = le16_to_cpu(blob->ctr_x);
+	ctr_y = le16_to_cpu(blob->ctr_y);
+
 	input_mt_slot(input, slotnum);
 	input_mt_report_slot_state(input, MT_TOOL_FINGER, 1);
 	wide = (bb_size_x > bb_size_y);
@@ -367,10 +378,13 @@ static void sur40_poll(struct input_polled_dev *polldev)
 		/*
 		 * Sanity check. when video data is also being retrieved, the
 		 * packet ID will usually increase in the middle of a series
-		 * instead of at the end.
-		 */
+		 * instead of at the end. However, the data is still consistent,
+		 * so the packet ID is probably just valid for the first packet
+		 * in a series.
+
 		if (packet_id != le32_to_cpu(header->packet_id))
 			dev_dbg(sur40->dev, "packet ID mismatch\n");
+		 */
 
 		packet_blobs = result / sizeof(struct sur40_blob);
 		dev_dbg(sur40->dev, "received %d blobs\n", packet_blobs);
diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c
index c27cf8f3d1ca9bb58699eca8b0ad93ea331518e0..98a16698be8ef6f8d07ff67e64b6379f31e2eaa9 100644
--- a/drivers/input/touchscreen/touchit213.c
+++ b/drivers/input/touchscreen/touchit213.c
@@ -192,7 +192,7 @@ static int touchit213_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id touchit213_serio_ids[] = {
+static const struct serio_device_id touchit213_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_TOUCHIT213,
diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c
index 4000e52054075acb33b2dae5dcf2fe5d34eb1ce8..45c325c33f21de698f84d15c32fd55dc68704a9d 100644
--- a/drivers/input/touchscreen/touchright.c
+++ b/drivers/input/touchscreen/touchright.c
@@ -152,7 +152,7 @@ static int tr_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id tr_serio_ids[] = {
+static const struct serio_device_id tr_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_TOUCHRIGHT,
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c
index ba90f447df75f4d21d02c445f4de15481c27a938..2ba6b4ca28cbeff53395b372dfe3e12ec4959e24 100644
--- a/drivers/input/touchscreen/touchwin.c
+++ b/drivers/input/touchscreen/touchwin.c
@@ -159,7 +159,7 @@ static int tw_connect(struct serio *serio, struct serio_driver *drv)
  * The serio driver structure.
  */
 
-static struct serio_device_id tw_serio_ids[] = {
+static const struct serio_device_id tw_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_TOUCHWIN,
diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c
index 29687872cb945356253b0dd017f74cb0a0acc3ef..d4ae4ba84c1f7ba357d474feaa7aa567df8a75de 100644
--- a/drivers/input/touchscreen/tsc40.c
+++ b/drivers/input/touchscreen/tsc40.c
@@ -141,7 +141,7 @@ static void tsc_disconnect(struct serio *serio)
 	serio_set_drvdata(serio, NULL);
 }
 
-static struct serio_device_id tsc_serio_ids[] = {
+static const struct serio_device_id tsc_serio_ids[] = {
 	{
 		.type   = SERIO_RS232,
 		.proto  = SERIO_TSC40,
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 85e95725d0dfe08c4c38fa73097c51236514dff5..3715d1eace9282a6d754d04c84be17f78b0a453c 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -681,7 +681,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
 	return err;
 }
 
-static struct serio_device_id w8001_serio_ids[] = {
+static const struct serio_device_id w8001_serio_ids[] = {
 	{
 		.type	= SERIO_RS232,
 		.proto	= SERIO_W8001,