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;