Merge "Revert "msm: kgsl: Try to run soft reset on all targets that support it""
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index b93dc4d..7ca741c 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -126,6 +126,7 @@
 
 Required properties :
 - compatible : should be "qcom,hsic-smsc-hub"
+- smsc,model-id : should be either <3503> or <4604> depending on hub model
 - smsc,<gpio-name>-gpio : handle to the GPIO node, see "gpios property"
   in Documentation/devicetree/bindings/gpio/gpio.txt.
   Required "gpio-name" is "reset" and optionally - "refclk", "int".
@@ -137,6 +138,7 @@
 Example SMSC HSIC HUB :
 	hsic_hub {
 		compatible = "qcom,hsic-smsc-hub";
+		smsc,model-id = <4604>;
 		ranges;
 		smsc,reset-gpio = <&pm8941_gpios 8 0x00>;
 		smsc,refclk-gpio = <&pm8941_gpios 16 0x00>;
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index acd0bb9..46f5f22 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -62,6 +62,7 @@
 
 	hsic_hub {
 		compatible = "qcom,hsic-smsc-hub";
+		smsc,model-id = <4604>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
@@ -604,7 +605,7 @@
 	};
 
 	qcom,dc-chgpth@1400 {
-		status = "ok";
+		status = "disabled";
 	};
 
 	qcom,boost@1500 {
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index f90599a..1803f91 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -375,6 +375,7 @@
 
 	hsic_hub {
 		compatible = "qcom,hsic-smsc-hub";
+		smsc,model-id = <3503>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 37567ed..f234712 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -75,7 +75,7 @@
 #include <linux/mfd/wcd9xxx/pdata.h>
 #endif
 
-#include <linux/smsc3503.h>
+#include <linux/smsc_hub.h>
 #include <linux/msm_ion.h>
 #include <mach/ion.h>
 #include <mach/mdm2.h>
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index a779b24..1deee5c 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -459,6 +459,7 @@
 	if ((read_len + 9) >= USER_SPACE_DATA) {
 		pr_err("diag: dci: Invalid length while forming dci pkt in %s",
 								__func__);
+		mutex_unlock(&driver->dci_mutex);
 		return -EIO;
 	}
 
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index b725200..06ca31c 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -394,7 +394,7 @@
 	const char *fw_name;
 	bool no_force_update;
 	bool lpm_support;
-	bool regs_enabled;
+	bool dev_sleep;
 
 #if defined(CONFIG_SECURE_TOUCH)
 	atomic_t st_enabled;
@@ -2162,11 +2162,6 @@
 	if (on == false)
 		goto power_off;
 
-	if (data->regs_enabled) {
-		dev_dbg(&data->client->dev, "regs are already enabled\n");
-		return 0;
-	}
-
 	rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
 	if (rc < 0) {
 		dev_err(&data->client->dev,
@@ -2215,8 +2210,6 @@
 		}
 	}
 
-	data->regs_enabled = true;
-
 	msleep(130);
 
 	return 0;
@@ -2237,12 +2230,6 @@
 	return rc;
 
 power_off:
-
-	if (!data->regs_enabled) {
-		dev_dbg(&data->client->dev, "regs are already disabled\n");
-		return 0;
-	}
-
 	reg_set_optimum_mode_check(data->vcc_ana, 0);
 	regulator_disable(data->vcc_ana);
 	if (data->pdata->digital_pwr_regulator) {
@@ -2254,8 +2241,6 @@
 		regulator_disable(data->vcc_i2c);
 	}
 
-	data->regs_enabled = false;
-
 	msleep(50);
 	return 0;
 }
@@ -2455,6 +2440,11 @@
 	struct input_dev *input_dev = data->input_dev;
 	int error;
 
+	if (data->dev_sleep) {
+		dev_dbg(dev, "Device already in sleep\n");
+		return 0;
+	}
+
 	disable_irq(data->irq);
 
 	mutex_lock(&input_dev->mutex);
@@ -2485,6 +2475,7 @@
 		}
 	}
 
+	data->dev_sleep = true;
 	return 0;
 }
 
@@ -2495,6 +2486,11 @@
 	struct input_dev *input_dev = data->input_dev;
 	int error;
 
+	if (!data->dev_sleep) {
+		dev_dbg(dev, "Device already in resume\n");
+		return 0;
+	}
+
 	/* put regulators back in active power mode */
 	if (data->lpm_support) {
 		error = mxt_regulator_lpm(data, false);
@@ -2538,6 +2534,7 @@
 
 	enable_irq(data->irq);
 
+	data->dev_sleep = false;
 	return 0;
 }
 
@@ -2924,6 +2921,7 @@
 	data->pdata = pdata;
 	data->no_force_update = pdata->no_force_update;
 	data->lpm_support = !pdata->no_lpm_support;
+	data->dev_sleep = false;
 
 	__set_bit(EV_ABS, input_dev->evbit);
 	__set_bit(EV_KEY, input_dev->evbit);
diff --git a/drivers/misc/smsc_hub.c b/drivers/misc/smsc_hub.c
index 41d9ff8..0147e66 100644
--- a/drivers/misc/smsc_hub.c
+++ b/drivers/misc/smsc_hub.c
@@ -21,14 +21,12 @@
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/smsc3503.h>
+#include <linux/smsc_hub.h>
 #include <linux/module.h>
 #include <mach/msm_xo.h>
 
-#define SMSC3503_I2C_ADDR 0x08
-#define SMSC_GSBI_I2C_BUS_ID 10
-static const unsigned short normal_i2c[] = {
-SMSC3503_I2C_ADDR, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = {
+0, I2C_CLIENT_END };
 
 struct hsic_hub {
 	struct device *dev;
@@ -111,6 +109,22 @@
 	return i2c_smbus_write_byte_data(client, reg, (ret & ~value));
 }
 
+static int smsc4604_send_connect_cmd(struct i2c_client *client)
+{
+	u8 buf[3];
+
+	buf[0] = 0xAA;
+	buf[1] = 0x55;
+	buf[2] = 0x00;
+
+	if (i2c_master_send(client, buf, 3) != 3) {
+		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static int i2c_hsic_hub_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
@@ -118,21 +132,37 @@
 				     I2C_FUNC_SMBUS_WORD_DATA))
 		return -EIO;
 
-	/* CONFIG_N bit in SP_ILOCK register has to be set before changing
-	 * other registers to change default configuration of hsic hub.
-	 */
-	hsic_hub_set_bits(client, SMSC3503_SP_ILOCK, CONFIG_N);
+	switch (smsc_hub->pdata->model_id) {
+	case SMSC3503_ID:
+		/*
+		 * CONFIG_N bit in SP_ILOCK register has to be set before
+		 * changing other registers to change default configuration
+		 * of hsic hub.
+		 */
+		hsic_hub_set_bits(client, SMSC3503_SP_ILOCK, CONFIG_N);
 
-	/* Can change default configuartion like VID,PID, strings etc
-	 * by writing new values to hsic hub registers.
-	 */
-	hsic_hub_write_word_data(client, SMSC3503_VENDORID, 0x05C6);
+		/*
+		 * Can change default configuartion like VID,PID,
+		 * strings etc by writing new values to hsic hub registers
+		 */
+		hsic_hub_write_word_data(client, SMSC3503_VENDORID, 0x05C6);
 
-	/* CONFIG_N bit in SP_ILOCK register has to be cleared for new
-	 * values in registers to be effective after writing to
-	 * other registers.
-	 */
-	hsic_hub_clear_bits(client, SMSC3503_SP_ILOCK, CONFIG_N);
+		/*
+		 * CONFIG_N bit in SP_ILOCK register has to be cleared
+		 * for new values in registers to be effective after
+		 * writing to other registers.
+		 */
+		hsic_hub_clear_bits(client, SMSC3503_SP_ILOCK, CONFIG_N);
+		break;
+	case SMSC4604_ID:
+		/*
+		 * SMSC4604 requires an I2C attach command to be issued
+		 * if I2C bus is connected
+		 */
+		return smsc4604_send_connect_cmd(client);
+	default:
+		return -EINVAL;
+	}
 
 	return 0;
 }
@@ -318,6 +348,8 @@
 struct smsc_hub_platform_data *msm_hub_dt_to_pdata(
 				struct platform_device *pdev)
 {
+	int rc;
+	u32 temp_val;
 	struct device_node *node = pdev->dev.of_node;
 	struct smsc_hub_platform_data *pdata;
 
@@ -327,6 +359,14 @@
 		return ERR_PTR(-ENOMEM);
 	}
 
+	rc = of_property_read_u32(node, "smsc,model-id", &temp_val);
+	if (rc) {
+		dev_err(&pdev->dev, "Unable to read smsc,model-id\n");
+		return ERR_PTR(rc);
+	} else {
+		pdata->model_id = temp_val;
+	}
+
 	pdata->hub_reset = of_get_named_gpio(node, "smsc,reset-gpio", 0);
 	if (pdata->hub_reset < 0)
 		return ERR_PTR(pdata->hub_reset);
@@ -399,18 +439,13 @@
 	}
 
 	gpio_direction_output(pdata->hub_reset, 0);
-	/* Hub reset should be asserted for minimum 2microsec
+	/*
+	 * Hub reset should be asserted for minimum 2microsec
 	 * before deasserting.
 	 */
 	udelay(5);
 	gpio_direction_output(pdata->hub_reset, 1);
 
-	ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add child node, ret=%d\n", ret);
-		goto uninit_gpio;
-	}
-
 	if (!IS_ERR(smsc_hub->hub_vbus_reg)) {
 		ret = regulator_enable(smsc_hub->hub_vbus_reg);
 		if (ret) {
@@ -436,14 +471,39 @@
 	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
 	strlcpy(i2c_info.type, "i2c_hsic_hub", I2C_NAME_SIZE);
 
+	/* 250ms delay is required for SMSC4604 HUB to get I2C up */
+	msleep(250);
+
+	/* Assign I2C slave address per SMSC model */
+	switch (pdata->model_id) {
+	case SMSC3503_ID:
+		normal_i2c[0] = SMSC3503_I2C_ADDR;
+		break;
+	case SMSC4604_ID:
+		normal_i2c[0] = SMSC4604_I2C_ADDR;
+		break;
+	default:
+		dev_err(&pdev->dev, "unsupported SMSC model-id\n");
+		i2c_put_adapter(i2c_adap);
+		i2c_del_driver(&hsic_hub_driver);
+		goto uninit_gpio;
+	}
+
 	smsc_hub->client = i2c_new_probed_device(i2c_adap, &i2c_info,
 						   normal_i2c, NULL);
 	i2c_put_adapter(i2c_adap);
-	if (!smsc_hub->client)
-		dev_err(&pdev->dev, "failed to connect to smsc_hub"
-			 "through I2C\n");
 
 i2c_add_fail:
+	ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add child node, ret=%d\n", ret);
+		goto uninit_gpio;
+	}
+
+	if (!smsc_hub->client)
+		dev_err(&pdev->dev,
+			"failed to connect to smsc_hub through I2C\n");
+
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
diff --git a/include/linux/smsc3503.h b/include/linux/smsc_hub.h
similarity index 90%
rename from include/linux/smsc3503.h
rename to include/linux/smsc_hub.h
index 1e28a58..9c0afc0 100644
--- a/include/linux/smsc3503.h
+++ b/include/linux/smsc_hub.h
@@ -14,6 +14,12 @@
 #ifndef __LINUX_SMSC3503_H__
 #define __LINUX_SMSC3503_H__
 
+#define SMSC3503_ID	3503
+#define SMSC4604_ID	4604
+#define SMSC3503_I2C_ADDR	0x08
+#define SMSC4604_I2C_ADDR	0x2d
+#define SMSC_GSBI_I2C_BUS_ID	0
+
 /*Serial interface Registers*/
 #define SMSC3503_VENDORID	0x00 /*u16 read*/
 #define SMSC3503_PRODUCTID	0x02 /*u16 read*/
@@ -42,6 +48,7 @@
 #define OCSPINSEL	(1<<5)
 
 struct smsc_hub_platform_data {
+	u32 model_id;
 	int hub_reset;
 	int refclk_gpio;
 	int int_gpio;