Merge "defconfig:msm8610 Enable camera front sensor (sp1628) for 8x10"
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index fbe2d25..e3a6721 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -135,6 +135,21 @@
qcom,usb2-power-budget = <500>;
};
+MSM HSUSB controller
+
+Required properties :
+- compatible : should be "qcom,ci13xxx_msm"
+
+Optional properties :
+- qcom,itc-level: value of 2^itc-level will be used for as the interrupt threshold
+ (ITC), when itc-level is between 0 to 6.
+
+Example MSM HSUSB controller device node :
+ msm_hsusb: qcom,ci13xxx_msm {
+ compatible = "qcom,ci13xxx_msm";
+ qcom,itc-level = <4>;
+};
+
ANDROID USB:
Required properties:
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 1877f40..0e446e2 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -22,6 +22,11 @@
#address-cells = <1>;
#size-cells = <1>;
+ qcom,revid@100 {
+ compatible = "qcom,qpnp-revid";
+ reg = <0x100 0x100>;
+ };
+
qcom,power-on@800 {
compatible = "qcom,qpnp-power-on";
reg = <0x800 0x100>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index d429f72..2008e1e 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -22,6 +22,11 @@
#address-cells = <1>;
#size-cells = <1>;
+ qcom,revid@100 {
+ compatible = "qcom,qpnp-revid";
+ reg = <0x100 0x100>;
+ };
+
qcom,power-on@800 {
compatible = "qcom,qpnp-power-on";
reg = <0x800 0x100>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index bbdc2b8..6891b90 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -51,7 +51,7 @@
/* Object 6, Instance = 0 */
00 00 00 00 00 00
/* Object 38, Instance = 0 */
- 1D 01 00 0C 04 0D 00 00
+ 1D 02 00 0A 06 0D 00 00
/* Object 7, Instance = 0 */
20 08 32
/* Object 8, Instance = 0 */
@@ -59,7 +59,7 @@
/* Object 9, Instance = 0 */
83 00 00 13 0B 00 20 32 01 03
00 32 05 30 0A 05 0A 00 70 03
- FC 01 00 36 2F 2C 00 00 40 00
+ FC 01 00 36 2F D8 00 00 40 00
00 0A 00 00 02
/* Object 18, Instance = 0 */
00 00
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 9406a09..ddbe3a0 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -51,7 +51,7 @@
/* Object 6, Instance = 0 */
00 00 00 00 00 00
/* Object 38, Instance = 0 */
- 1D 01 00 0C 04 0D 00 00
+ 1D 02 00 0A 06 0D 00 00
/* Object 7, Instance = 0 */
20 08 32
/* Object 8, Instance = 0 */
@@ -59,7 +59,7 @@
/* Object 9, Instance = 0 */
83 00 00 13 0B 00 20 32 01 03
00 32 05 30 0A 05 0A 00 70 03
- FC 01 00 36 2F 2C 00 00 40 00
+ FC 01 00 36 2F D8 00 00 40 00
00 0A 00 00 02
/* Object 18, Instance = 0 */
00 00
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dts
index 5f9365a..42367b3 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dts
@@ -157,6 +157,7 @@
qcom,id = <6>;
qcom,source-sel = <1>;
qcom,mode-ctrl = <0x61>;
+ qcom,mode = "manual";
};
};
@@ -171,6 +172,7 @@
qcom,id = <6>;
qcom,source-sel = <1>;
qcom,mode-ctrl = <0x10>;
+ qcom,mode = "manual";
};
};
};
@@ -265,3 +267,33 @@
status = "ok";
};
};
+
+&pm8110_gpios {
+ gpio@c000 { /* GPIO 1 */
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ };
+};
+
+&pm8110_mpps {
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ status = "disabled";
+ };
+
+ mpp@a200 { /* MPP 3 */
+ status = "disabled";
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index d617c27..f184a00 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -175,6 +175,11 @@
<87 512 40000 640000>;
};
+ msm_hsusb: qcom,ci13xxx_msm {
+ compatible = "qcom,ci13xxx_msm";
+ qcom,itc-level = <4>;
+ };
+
hsic_host: hsic@f9a15000 {
compatible = "qcom,hsic-host";
reg = <0xf9a15000 0x400>;
diff --git a/arch/arm/boot/dts/msmkrypton-sim.dts b/arch/arm/boot/dts/msmkrypton-sim.dts
index 1872a36..29f0df4 100644
--- a/arch/arm/boot/dts/msmkrypton-sim.dts
+++ b/arch/arm/boot/dts/msmkrypton-sim.dts
@@ -23,3 +23,13 @@
&uartdm3{
status = "ok";
};
+
+&spi_6 {
+ ethernet-switch@0 {
+ compatible = "simtec,ks8851";
+ reg = <0>;
+ interrupt-parent = <&msmgpio>;
+ spi-max-frequency = <19200000>;
+ interrupts = <75 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index 4b032d8..7bbd528 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -117,4 +117,19 @@
interrupts = <0 109 0>;
status = "disabled";
};
+
+ spi_6: spi@f9928000 { /* BLSP1 QUP6 */
+ cell-index = <0>;
+ compatible = "qcom,spi-qup-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xf9928000 0x1000>;
+ interrupts = <0 100 0>;
+ spi-max-frequency = <19200000>;
+
+ gpios = <&msmgpio 23 0>, /* CLK */
+ <&msmgpio 21 0>, /* MISO */
+ <&msmgpio 20 0>; /* MOSI */
+ cs-gpios = <&msmgpio 22 0>;
+ };
};
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 7420092..71249c9 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -205,6 +205,15 @@
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_QSEECOM=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
@@ -359,6 +368,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_VIBRATOR=y
+CONFIG_QPNP_REVID=y
CONFIG_MSM_IOMMU_V1=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 3798987..6c604ff 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -205,6 +205,15 @@
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_QSEECOM=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
@@ -384,6 +393,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_VIBRATOR=y
+CONFIG_QPNP_REVID=y
CONFIG_MSM_IOMMU_V1=y
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_TMC=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index acd6adc..d5e230d 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -349,6 +349,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_VIBRATOR=y
+CONFIG_QPNP_REVID=y
CONFIG_MSM_IOMMU_V0=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 4870575..b435924 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -368,6 +368,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_VIBRATOR=y
+CONFIG_QPNP_REVID=y
CONFIG_MSM_IOMMU_V0=y
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_TMC=y
diff --git a/arch/arm/configs/msmkrypton_defconfig b/arch/arm/configs/msmkrypton_defconfig
index 69bc36e..f073d2b 100644
--- a/arch/arm/configs/msmkrypton_defconfig
+++ b/arch/arm/configs/msmkrypton_defconfig
@@ -65,9 +65,28 @@
CONFIG_MTD_BLOCK=y
# CONFIG_MTD_MSM_NAND is not set
CONFIG_MTD_MSM_QPIC_NAND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IPV6=y
+# CONFIG_WIRELESS is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
# CONFIG_ANDROID_PMEM is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+CONFIG_KS8851=y
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_MSM_RMNET is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_WLAN is not set
# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_KEYBOARD is not set
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index cf10056..a70b300 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -573,6 +573,8 @@
local_fiq_disable();
local_irq_disable();
+ flush_cache_all();
+
while (1)
cpu_relax();
}
diff --git a/arch/arm/mach-msm/include/mach/qseecomi.h b/arch/arm/mach-msm/include/mach/qseecomi.h
index 3a997be..a4021d4 100644
--- a/arch/arm/mach-msm/include/mach/qseecomi.h
+++ b/arch/arm/mach-msm/include/mach/qseecomi.h
@@ -18,13 +18,13 @@
#define QSEECOM_KEY_ID_SIZE 32
-#define QSEOS_RESULT_FAIL_LOAD_KS -48
-#define QSEOS_RESULT_FAIL_SAVE_KS -49
-#define QSEOS_RESULT_FAIL_MAX_KEYS -50
-#define QSEOS_RESULT_FAIL_KEY_ID_EXISTS -51
-#define QSEOS_RESULT_FAIL_KEY_ID_DNE -52
-#define QSEOS_RESULT_FAIL_KS_OP -53
-#define QSEOS_RESULT_FAIL_CE_PIPE_INVALID -54
+#define QSEOS_RESULT_FAIL_LOAD_KS -57
+#define QSEOS_RESULT_FAIL_SAVE_KS -58
+#define QSEOS_RESULT_FAIL_MAX_KEYS -59
+#define QSEOS_RESULT_FAIL_KEY_ID_EXISTS -60
+#define QSEOS_RESULT_FAIL_KEY_ID_DNE -61
+#define QSEOS_RESULT_FAIL_KS_OP -62
+#define QSEOS_RESULT_FAIL_CE_PIPE_INVALID -63
enum qseecom_command_scm_resp_type {
QSEOS_APP_ID = 0xEE01,
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index a5e04cd..7b1a4c3 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -952,8 +952,8 @@
static irqreturn_t subsys_err_ready_intr_handler(int irq, void *subsys)
{
struct subsys_device *subsys_dev = subsys;
- pr_info("Error ready interrupt occured for %s\n",
- subsys_dev->desc->name);
+ dev_info(subsys_dev->desc->dev,
+ "Subsystem error monitoring/handling services are up\n");
if (subsys_dev->desc->is_not_loadable)
return IRQ_HANDLED;
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index efcace6..8dbac64 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -18,6 +18,7 @@
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -168,7 +169,15 @@
#define FT_REG_CAL 0x00
#define FT_CAL_MASK 0x70
-#define FT_DEBUG_DIR_NAME "ft_debug"
+#define FT_INFO_MAX_LEN 200
+
+#define FT_STORE_TS_INFO(buf, id, fw_ver) \
+ snprintf(buf, FT_INFO_MAX_LEN, \
+ "controller\t= focaltech\n" \
+ "model\t\t= 0x%x\n" \
+ "fw_ver\t\t= 0x%x\n", id, fw_ver)
+
+#define FT_DEBUG_DIR_NAME "ts_debug"
struct ts_event {
u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
@@ -202,6 +211,7 @@
struct dentry *dir;
u16 addr;
bool suspended;
+ char *ts_info;
#if defined(CONFIG_FB)
struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
@@ -298,17 +308,22 @@
event->pressure = 0;
}
- input_report_abs(data->input_dev, ABS_MT_POSITION_X,
- event->x[i]);
- input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
- event->y[i]);
- input_report_abs(data->input_dev, ABS_MT_PRESSURE,
- event->pressure);
- input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
- event->finger_id[i]);
- input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
- event->pressure);
- input_mt_sync(data->input_dev);
+ input_mt_slot(data->input_dev, i);
+ input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
+ !!event->pressure);
+
+ if (event->pressure == FT_PRESS) {
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+ event->x[i]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+ event->y[i]);
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+ event->pressure);
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
+ event->finger_id[i]);
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+ event->pressure);
+ }
}
input_report_key(data->input_dev, BTN_TOUCH, !!fingerdown);
@@ -809,6 +824,7 @@
rc = -EIO;
}
+ FT_STORE_TS_INFO(data->ts_info, data->family_id, FT_FW_FILE_VER(fw));
rel_fw:
release_firmware(fw);
return rc;
@@ -1015,6 +1031,27 @@
DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5x06_debug_suspend_get,
ft5x06_debug_suspend_set, "%lld\n");
+static int ft5x06_debug_dump_info(struct seq_file *m, void *v)
+{
+ struct ft5x06_ts_data *data = m->private;
+
+ seq_printf(m, "%s\n", data->ts_info);
+
+ return 0;
+}
+
+static int debugfs_dump_info_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ft5x06_debug_dump_info, inode->i_private);
+}
+
+static const struct file_operations debug_dump_info_fops = {
+ .owner = THIS_MODULE,
+ .open = debugfs_dump_info_open,
+ .read = seq_read,
+ .release = single_release,
+};
+
#ifdef CONFIG_OF
static int ft5x06_get_dt_coords(struct device *dev, char *name,
struct ft5x06_ts_platform_data *pdata)
@@ -1130,7 +1167,7 @@
struct ft5x06_ts_platform_data *pdata;
struct ft5x06_ts_data *data;
struct input_dev *input_dev;
- struct dentry *dir, *temp;
+ struct dentry *temp;
u8 reg_value;
u8 reg_addr;
int err;
@@ -1188,12 +1225,11 @@
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+ input_mt_init_slots(input_dev, CFG_MAX_TOUCH_POINTS);
input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
pdata->x_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
pdata->y_max, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
- CFG_MAX_TOUCH_POINTS, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, FT_PRESS, 0, 0);
input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);
@@ -1282,28 +1318,6 @@
data->family_id = reg_value;
- /*get some register information */
- reg_addr = FT_REG_FW_VER;
- err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
- if (err < 0)
- dev_err(&client->dev, "version read failed");
-
- dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
-
- reg_addr = FT_REG_POINT_RATE;
- ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
- if (err < 0)
- dev_err(&client->dev, "report rate read failed");
-
- dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
-
- reg_addr = FT_REG_THGROUP;
- err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
- if (err < 0)
- dev_err(&client->dev, "threshold read failed");
-
- dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
-
err = request_threaded_irq(client->irq, NULL,
ft5x06_ts_interrupt, pdata->irqflags,
client->dev.driver->name, data);
@@ -1330,14 +1344,14 @@
goto free_update_fw_sys;
}
- dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
- if (dir == NULL || IS_ERR(dir)) {
- pr_err("debugfs_create_dir failed: rc=%ld\n", PTR_ERR(dir));
- err = PTR_ERR(dir);
+ data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
+ if (data->dir == NULL || IS_ERR(data->dir)) {
+ pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir));
+ err = PTR_ERR(data->dir);
goto free_force_update_fw_sys;
}
- temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, dir, data,
+ temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, data->dir, data,
&debug_addr_fops);
if (temp == NULL || IS_ERR(temp)) {
pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
@@ -1345,7 +1359,7 @@
goto free_debug_dir;
}
- temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, dir, data,
+ temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, data->dir, data,
&debug_data_fops);
if (temp == NULL || IS_ERR(temp)) {
pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
@@ -1353,14 +1367,52 @@
goto free_debug_dir;
}
- temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, dir, data,
- &debug_suspend_fops);
+ temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, data->dir,
+ data, &debug_suspend_fops);
if (temp == NULL || IS_ERR(temp)) {
pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
err = PTR_ERR(temp);
goto free_debug_dir;
}
+ temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, data->dir,
+ data, &debug_dump_info_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+ err = PTR_ERR(temp);
+ goto free_debug_dir;
+ }
+
+ data->ts_info = kzalloc(FT_INFO_MAX_LEN, GFP_KERNEL);
+ if (!data->ts_info) {
+ dev_err(&client->dev, "Not enough memory\n");
+ goto free_debug_dir;
+ }
+
+ /*get some register information */
+ reg_addr = FT_REG_POINT_RATE;
+ ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
+ if (err < 0)
+ dev_err(&client->dev, "report rate read failed");
+
+ dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
+
+ reg_addr = FT_REG_THGROUP;
+ err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
+ if (err < 0)
+ dev_err(&client->dev, "threshold read failed");
+
+ dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
+
+ reg_addr = FT_REG_FW_VER;
+ err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
+ if (err < 0)
+ dev_err(&client->dev, "version read failed");
+
+ dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
+
+ FT_STORE_TS_INFO(data->ts_info, data->family_id, reg_value);
+
#if defined(CONFIG_FB)
data->fb_notif.notifier_call = fb_notifier_callback;
@@ -1449,6 +1501,7 @@
ft5x06_power_init(data, false);
input_unregister_device(data->input_dev);
+ kfree(data->ts_info);
kfree(data);
return 0;
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index ac2ecbb..a990f43 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -128,6 +128,16 @@
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = mmc_dev_to_card(dev);
+ if (!drv) {
+ pr_debug("%s: %s: drv is NULL\n", dev_name(dev), __func__);
+ return;
+ }
+
+ if (!card) {
+ pr_debug("%s: %s: card is NULL\n", dev_name(dev), __func__);
+ return;
+ }
+
if (drv->shutdown)
drv->shutdown(card);
}
diff --git a/drivers/platform/msm/ipa/a2_service.c b/drivers/platform/msm/ipa/a2_service.c
index 0d77741..8e79185 100644
--- a/drivers/platform/msm/ipa/a2_service.c
+++ b/drivers/platform/msm/ipa/a2_service.c
@@ -278,7 +278,8 @@
A2_MUX_COMPLETION_TIMEOUT);
a2_mux_ctx->wait_for_ack = 0;
if (unlikely(ret == 0)) {
- IPADBG("%s timeout previous ack\n", __func__);
+ IPAERR("%s previous ack from modem timed out\n",
+ __func__);
goto bail;
}
}
@@ -288,7 +289,7 @@
ret = wait_for_completion_timeout(&a2_mux_ctx->ul_wakeup_ack_completion,
A2_MUX_COMPLETION_TIMEOUT);
if (unlikely(ret == 0)) {
- IPADBG("%s timeout wakeup ack\n", __func__);
+ IPAERR("%s wakup ack from modem timed out\n", __func__);
goto bail;
}
INIT_COMPLETION(a2_mux_ctx->bam_connection_completion);
@@ -297,7 +298,7 @@
&a2_mux_ctx->bam_connection_completion,
A2_MUX_COMPLETION_TIMEOUT);
if (unlikely(ret == 0)) {
- IPADBG("%s timeout power on\n", __func__);
+ IPAERR("%s modem power on timed out\n", __func__);
goto bail;
}
}
@@ -450,7 +451,8 @@
&a2_mux_ctx->dl_wakeup_completion,
A2_MUX_COMPLETION_TIMEOUT);
if (unlikely(ret == 0)) {
- IPAERR("%s timeout A2 PROD\n", __func__);
+ IPAERR("%s timeout waiting for A2 PROD granted\n",
+ __func__);
BUG();
return;
}
@@ -475,8 +477,8 @@
&a2_mux_ctx->request_resource_completion,
A2_MUX_COMPLETION_TIMEOUT);
if (unlikely(ret == 0)) {
- IPADBG("%s timeout request A2 PROD resource\n",
- __func__);
+ IPAERR("%s timeout waiting for A2 PROD granted\n",
+ __func__);
BUG();
return;
}
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index f4ad172..1cbd514 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -50,7 +50,6 @@
#define IPA_AGGR_STR_IN_BYTES(str) \
(strnlen((str), IPA_AGGR_MAX_STR_LENGTH - 1) + 1)
-
static struct ipa_plat_drv_res ipa_res = {0, };
static struct of_device_id ipa_plat_drv_match[] = {
{
@@ -1735,6 +1734,22 @@
result = -ENOMEM;
goto fail_rt_tbl_cache;
}
+ ipa_ctx->tx_pkt_wrapper_cache =
+ kmem_cache_create("IPA TX PKT WRAPPER",
+ sizeof(struct ipa_tx_pkt_wrapper), 0, 0, NULL);
+ if (!ipa_ctx->tx_pkt_wrapper_cache) {
+ IPAERR(":ipa tx pkt wrapper cache create failed\n");
+ result = -ENOMEM;
+ goto fail_tx_pkt_wrapper_cache;
+ }
+ ipa_ctx->rx_pkt_wrapper_cache =
+ kmem_cache_create("IPA RX PKT WRAPPER",
+ sizeof(struct ipa_rx_pkt_wrapper), 0, 0, NULL);
+ if (!ipa_ctx->rx_pkt_wrapper_cache) {
+ IPAERR(":ipa rx pkt wrapper cache create failed\n");
+ result = -ENOMEM;
+ goto fail_rx_pkt_wrapper_cache;
+ }
ipa_ctx->tree_node_cache =
kmem_cache_create("IPA TREE", sizeof(struct ipa_tree_node), 0, 0,
NULL);
@@ -1803,8 +1818,6 @@
mutex_init(&ipa_ctx->lock);
mutex_init(&ipa_ctx->nat_mem.lock);
- skb_queue_head_init(&ipa_ctx->rx_list);
-
for (i = 0; i < IPA_A5_SYS_MAX; i++) {
INIT_LIST_HEAD(&ipa_ctx->sys[i].head_desc_list);
spin_lock_init(&ipa_ctx->sys[i].spinlock);
@@ -1818,15 +1831,15 @@
atomic_set(&ipa_ctx->sys[i].curr_polling_state, 0);
}
- ipa_ctx->rx_wq = alloc_workqueue("ipa rx wq", WQ_MEM_RECLAIM |
- WQ_CPU_INTENSIVE, 1);
+ ipa_ctx->rx_wq = create_singlethread_workqueue("ipa rx wq");
if (!ipa_ctx->rx_wq) {
IPAERR(":fail to create rx wq\n");
result = -ENOMEM;
goto fail_rx_wq;
}
- ipa_ctx->tx_wq = create_singlethread_workqueue("ipa tx wq");
+ ipa_ctx->tx_wq = alloc_workqueue("ipa tx wq", WQ_MEM_RECLAIM |
+ WQ_CPU_INTENSIVE, 2);
if (!ipa_ctx->tx_wq) {
IPAERR(":fail to create tx wq\n");
result = -ENOMEM;
@@ -1979,6 +1992,10 @@
fail_dma_pool:
kmem_cache_destroy(ipa_ctx->tree_node_cache);
fail_tree_node_cache:
+ kmem_cache_destroy(ipa_ctx->rx_pkt_wrapper_cache);
+fail_rx_pkt_wrapper_cache:
+ kmem_cache_destroy(ipa_ctx->tx_pkt_wrapper_cache);
+fail_tx_pkt_wrapper_cache:
kmem_cache_destroy(ipa_ctx->rt_tbl_cache);
fail_rt_tbl_cache:
kmem_cache_destroy(ipa_ctx->hdr_offset_cache);
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index ae59f37..5c343e8 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -9,7 +9,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-
#include <linux/delay.h>
#include "ipa_i.h"
@@ -251,26 +250,6 @@
memset(&ipa_ctx->ep[ipa_ep_idx], 0, sizeof(struct ipa_ep_context));
- if (IPA_CLIENT_IS_CONS(in->client)) {
- ep->cmd = kzalloc(sizeof(struct ipa_ip_packet_init),
- GFP_KERNEL);
- if (!ep->cmd) {
- IPAERR("failed to alloc immediate command object\n");
- result = -ENOMEM;
- goto fail;
- }
- ep->cmd->destination_pipe_index = ipa_ep_idx;
- ep->dma_addr = dma_map_single(NULL, ep->cmd,
- sizeof(struct ipa_ip_packet_init),
- DMA_TO_DEVICE);
- if (ep->dma_addr == 0 || ep->dma_addr == ~0) {
- IPAERR("failed to DMA MAP pkt_init\n");
- result = -ENOMEM;
- kfree(ep->cmd);
- goto fail;
- }
- }
-
ep->valid = 1;
ep->client = in->client;
ep->client_notify = in->notify;
@@ -447,13 +426,6 @@
return -EPERM;
}
- if (IPA_CLIENT_IS_CONS(ep->client)) {
- dma_unmap_single(NULL, ep->dma_addr,
- sizeof(struct ipa_ip_packet_init),
- DMA_TO_DEVICE);
- kfree(ep->cmd);
- }
-
ipa_enable_data_path(clnt_hdl);
memset(&ipa_ctx->ep[clnt_hdl], 0, sizeof(struct ipa_ep_context));
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index c564922..38a1a9c 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -17,23 +17,21 @@
#include <linux/netdevice.h>
#include "ipa_i.h"
+
#define list_next_entry(pos, member) \
list_entry(pos->member.next, typeof(*pos), member)
+#define IPA_LAST_DESC_CNT 0xFFFF
#define POLLING_INACTIVITY_RX 40
-#define POLLING_MIN_SLEEP_RX 2350
-#define POLLING_MAX_SLEEP_RX 2450
-#define POLLING_INACTIVITY_TX 10
-#define POLLING_MIN_SLEEP_TX 100
-#define POLLING_MAX_SLEEP_TX 200
-#define RX_MAX_IND 40
+#define POLLING_MIN_SLEEP_RX 950
+#define POLLING_MAX_SLEEP_RX 1050
+#define POLLING_INACTIVITY_TX 40
+#define POLLING_MIN_SLEEP_TX 400
+#define POLLING_MAX_SLEEP_TX 500
static void replenish_rx_work_func(struct work_struct *work);
static struct delayed_work replenish_rx_work;
static void ipa_wq_handle_rx(struct work_struct *work);
static DECLARE_WORK(rx_work, ipa_wq_handle_rx);
-static void ipa_wq_handle_tx(struct work_struct *work);
-static DECLARE_WORK(tx_work, ipa_wq_handle_tx);
-
/**
* ipa_write_done() - this function will be (eventually) called when a Tx
* operation is complete
@@ -83,7 +81,7 @@
if (tx_pkt->callback)
tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
- kfree(tx_pkt);
+ kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
}
int ipa_handle_tx_core(struct ipa_sys_context *sys, bool process_all,
@@ -121,13 +119,23 @@
IPADBG("--curr_cnt=%d\n", sys->len);
- if (tx_pkt->callback) {
+ if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
+ dma_pool_free(ipa_ctx->dma_pool,
+ tx_pkt->bounce,
+ tx_pkt->mem.phys_base);
+ else
dma_unmap_single(NULL, tx_pkt->mem.phys_base,
- tx_pkt->mem.size, DMA_TO_DEVICE);
- tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
- }
+ tx_pkt->mem.size,
+ DMA_TO_DEVICE);
- kfree(tx_pkt);
+ if (tx_pkt->callback)
+ tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
+
+ if (tx_pkt->cnt > 1 && tx_pkt->cnt != IPA_LAST_DESC_CNT)
+ dma_pool_free(ipa_ctx->dma_pool, tx_pkt->mult.base,
+ tx_pkt->mult.phys_base);
+
+ kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
cnt++;
};
@@ -146,6 +154,11 @@
goto fail;
}
+ ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect);
+ if (ret) {
+ IPAERR("sps_get_config() failed %d\n", ret);
+ goto fail;
+ }
sys->event.options = SPS_O_EOT;
ret = sps_register_event(sys->ep->ep_hdl, &sys->event);
if (ret) {
@@ -192,7 +205,9 @@
static void ipa_wq_handle_tx(struct work_struct *work)
{
- ipa_handle_tx(&ipa_ctx->sys[IPA_A5_LAN_WAN_OUT]);
+ struct ipa_tx_pkt_wrapper *tx_pkt;
+ tx_pkt = container_of(work, struct ipa_tx_pkt_wrapper, work);
+ ipa_handle_tx(tx_pkt->sys);
}
/**
@@ -225,7 +240,7 @@
if (unlikely(!in_atomic))
mem_flag = GFP_KERNEL;
- tx_pkt = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), mem_flag);
+ tx_pkt = kmem_cache_zalloc(ipa_ctx->tx_pkt_wrapper_cache, mem_flag);
if (!tx_pkt) {
IPAERR("failed to alloc tx wrapper\n");
goto fail_mem_alloc;
@@ -281,11 +296,14 @@
IPADBG("sending cmd=%d pyld_len=%d sps_flags=%x\n",
desc->opcode, desc->len, sps_flags);
IPA_DUMP_BUFF(desc->pyld, dma_address, desc->len);
+ INIT_WORK(&tx_pkt->work, ipa_wq_write_done);
} else {
len = desc->len;
+ INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
}
- INIT_WORK(&tx_pkt->work, ipa_wq_write_done);
+ if (unlikely(ipa_ctx->polling_mode))
+ INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
spin_lock_irqsave(&sys->spinlock, irq_flags);
list_add_tail(&tx_pkt->link, &sys->head_desc_list);
@@ -309,12 +327,192 @@
else
dma_unmap_single(NULL, dma_address, desc->len, DMA_TO_DEVICE);
fail_dma_map:
- kfree(tx_pkt);
+ kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
fail_mem_alloc:
return -EFAULT;
}
/**
+ * ipa_send() - Send multiple descriptors in one HW transaction
+ * @sys: system pipe context
+ * @num_desc: number of packets
+ * @desc: packets to send (may be immediate command or data)
+ * @in_atomic: whether caller is in atomic context
+ *
+ * This function is used for system-to-bam connection.
+ * - SPS driver expect struct sps_transfer which will contain all the data
+ * for a transaction
+ * - The sps_transfer struct will be pointing to bounce buffers for
+ * its DMA command (immediate command and data)
+ * - ipa_tx_pkt_wrapper will be used for each ipa
+ * descriptor (allocated from wrappers cache)
+ * - The wrapper struct will be configured for each ipa-desc payload and will
+ * contain information which will be later used by the user callbacks
+ * - each transfer will be made by calling to sps_transfer()
+ * - Each packet (command or data) that will be sent will also be saved in
+ * ipa_sys_context for later check that all data was sent
+ *
+ * Return codes: 0: success, -EFAULT: failure
+ */
+int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
+ bool in_atomic)
+{
+ struct ipa_tx_pkt_wrapper *tx_pkt;
+ struct ipa_tx_pkt_wrapper *next_pkt;
+ struct sps_transfer transfer = { 0 };
+ struct sps_iovec *iovec;
+ unsigned long irq_flags;
+ dma_addr_t dma_addr;
+ int i = 0;
+ int j;
+ int result;
+ int fail_dma_wrap = 0;
+ uint size = num_desc * sizeof(struct sps_iovec);
+ u32 mem_flag = GFP_ATOMIC;
+
+ if (unlikely(!in_atomic))
+ mem_flag = GFP_KERNEL;
+
+ transfer.iovec = dma_pool_alloc(ipa_ctx->dma_pool, mem_flag, &dma_addr);
+ transfer.iovec_phys = dma_addr;
+ transfer.iovec_count = num_desc;
+ spin_lock_irqsave(&sys->spinlock, irq_flags);
+ if (!transfer.iovec) {
+ IPAERR("fail to alloc DMA mem for sps xfr buff\n");
+ goto failure_coherent;
+ }
+
+ for (i = 0; i < num_desc; i++) {
+ fail_dma_wrap = 0;
+ tx_pkt = kmem_cache_zalloc(ipa_ctx->tx_pkt_wrapper_cache,
+ mem_flag);
+ if (!tx_pkt) {
+ IPAERR("failed to alloc tx wrapper\n");
+ goto failure;
+ }
+ /*
+ * first desc of set is "special" as it holds the count and
+ * other info
+ */
+ if (i == 0) {
+ transfer.user = tx_pkt;
+ tx_pkt->mult.phys_base = dma_addr;
+ tx_pkt->mult.base = transfer.iovec;
+ tx_pkt->mult.size = size;
+ tx_pkt->cnt = num_desc;
+ }
+ INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
+
+ iovec = &transfer.iovec[i];
+ iovec->flags = 0;
+
+ INIT_LIST_HEAD(&tx_pkt->link);
+ tx_pkt->type = desc[i].type;
+
+ tx_pkt->mem.base = desc[i].pyld;
+ tx_pkt->mem.size = desc[i].len;
+
+ if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0)) {
+ WARN_ON(tx_pkt->mem.size > 512);
+
+ /*
+ * Due to a HW limitation, we need to make sure that the
+ * packet does not cross a 1KB boundary
+ */
+ tx_pkt->bounce =
+ dma_pool_alloc(ipa_ctx->dma_pool,
+ mem_flag,
+ &tx_pkt->mem.phys_base);
+ if (!tx_pkt->bounce) {
+ tx_pkt->mem.phys_base = 0;
+ } else {
+ WARN_ON(!ipa_straddle_boundary(
+ (u32)tx_pkt->mem.phys_base,
+ (u32)tx_pkt->mem.phys_base +
+ tx_pkt->mem.size - 1, 1024));
+ memcpy(tx_pkt->bounce, tx_pkt->mem.base,
+ tx_pkt->mem.size);
+ }
+ } else {
+ tx_pkt->mem.phys_base =
+ dma_map_single(NULL, tx_pkt->mem.base,
+ tx_pkt->mem.size,
+ DMA_TO_DEVICE);
+ }
+ if (!tx_pkt->mem.phys_base) {
+ IPAERR("failed to alloc tx wrapper\n");
+ fail_dma_wrap = 1;
+ goto failure;
+ }
+
+ tx_pkt->sys = sys;
+ tx_pkt->callback = desc[i].callback;
+ tx_pkt->user1 = desc[i].user1;
+ tx_pkt->user2 = desc[i].user2;
+
+ /*
+ * Point the iovec to the bounce buffer and
+ * add this packet to system pipe context.
+ */
+ iovec->addr = tx_pkt->mem.phys_base;
+ list_add_tail(&tx_pkt->link, &sys->head_desc_list);
+
+ /*
+ * Special treatment for immediate commands, where the structure
+ * of the descriptor is different
+ */
+ if (desc[i].type == IPA_IMM_CMD_DESC) {
+ iovec->size = desc[i].opcode;
+ iovec->flags |= SPS_IOVEC_FLAG_IMME;
+ } else {
+ iovec->size = desc[i].len;
+ }
+
+ if (i == (num_desc - 1)) {
+ iovec->flags |= SPS_IOVEC_FLAG_EOT;
+ /* "mark" the last desc */
+ tx_pkt->cnt = IPA_LAST_DESC_CNT;
+ }
+ }
+
+ result = sps_transfer(sys->ep->ep_hdl, &transfer);
+ if (result) {
+ IPAERR("sps_transfer failed rc=%d\n", result);
+ goto failure;
+ }
+
+ spin_unlock_irqrestore(&sys->spinlock, irq_flags);
+ return 0;
+
+failure:
+ tx_pkt = transfer.user;
+ for (j = 0; j < i; j++) {
+ next_pkt = list_next_entry(tx_pkt, link);
+ list_del(&tx_pkt->link);
+ if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
+ dma_pool_free(ipa_ctx->dma_pool,
+ tx_pkt->bounce,
+ tx_pkt->mem.phys_base);
+ else
+ dma_unmap_single(NULL, tx_pkt->mem.phys_base,
+ tx_pkt->mem.size,
+ DMA_TO_DEVICE);
+ kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
+ tx_pkt = next_pkt;
+ }
+ if (i < num_desc)
+ /* last desc failed */
+ if (fail_dma_wrap)
+ kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
+ if (transfer.iovec_phys)
+ dma_pool_free(ipa_ctx->dma_pool, transfer.iovec,
+ transfer.iovec_phys);
+failure_coherent:
+ spin_unlock_irqrestore(&sys->spinlock, irq_flags);
+ return -EFAULT;
+}
+
+/**
* ipa_sps_irq_cmd_ack - callback function which will be called by SPS driver after an
* immediate command is complete.
* @user1: pointer to the descriptor of the transfer
@@ -345,6 +543,7 @@
*/
int ipa_send_cmd(u16 num_desc, struct ipa_desc *descr)
{
+ struct ipa_desc *desc;
int result = 0;
ipa_inc_client_enable_clks();
@@ -364,10 +563,22 @@
}
wait_for_completion(&descr->xfer_done);
} else {
- IPAERR("unsupported chaining multiple IC\n");
+ desc = &descr[num_desc - 1];
+ init_completion(&desc->xfer_done);
+
+ if (desc->callback || desc->user1)
+ WARN_ON(1);
+
+ desc->callback = ipa_sps_irq_cmd_ack;
+ desc->user1 = desc;
+ if (ipa_send(&ipa_ctx->sys[IPA_A5_CMD], num_desc,
+ descr, false)) {
+ IPAERR("fail to send multiple immediate command set\n");
result = -EFAULT;
goto bail;
}
+ wait_for_completion(&desc->xfer_done);
+ }
IPA_STATS_INC_IC_CNT(num_desc, descr, ipa_ctx->stats.imm_cmds);
bail:
@@ -386,13 +597,21 @@
static void ipa_sps_irq_tx_notify(struct sps_event_notify *notify)
{
struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_OUT];
+ struct ipa_tx_pkt_wrapper *tx_pkt;
int ret;
IPADBG("event %d notified\n", notify->event_id);
switch (notify->event_id) {
case SPS_EVENT_EOT:
+ tx_pkt = notify->data.transfer.user;
if (!atomic_read(&sys->curr_polling_state)) {
+ ret = sps_get_config(sys->ep->ep_hdl,
+ &sys->ep->connect);
+ if (ret) {
+ IPAERR("sps_get_config() failed %d\n", ret);
+ break;
+ }
sys->ep->connect.options = SPS_O_AUTO_ENABLE |
SPS_O_ACK_TRANSFERS | SPS_O_POLL;
ret = sps_set_config(sys->ep->ep_hdl,
@@ -402,7 +621,7 @@
break;
}
atomic_set(&sys->curr_polling_state, 1);
- queue_work(ipa_ctx->tx_wq, &tx_work);
+ queue_work(ipa_ctx->tx_wq, &tx_pkt->work);
}
break;
default:
@@ -435,47 +654,6 @@
}
}
-static void ipa_handle_tag_rsp(struct ipa_a5_mux_hdr *mux_hdr)
-{
- struct completion *compl;
- struct ipa_tree_node *node;
-
- /* retrieve the compl object from tag value */
- mux_hdr++;
- compl = (struct completion *) ntohl(*((u32 *)mux_hdr));
- IPADBG("%x %x %p\n", *(u32 *)mux_hdr, *((u32 *)mux_hdr + 1), compl);
-
- mutex_lock(&ipa_ctx->lock);
- node = ipa_search(&ipa_ctx->tag_tree, (u32)compl);
- if (node) {
- complete_all(compl);
- rb_erase(&node->node, &ipa_ctx->tag_tree);
- kmem_cache_free(ipa_ctx->tree_node_cache, node);
- } else {
- WARN_ON(1);
- }
- mutex_unlock(&ipa_ctx->lock);
-}
-
-static void ipa_dejitter(bool limit)
-{
- struct sk_buff *skb;
- int len = skb_queue_len(&ipa_ctx->rx_list);
- int i;
- void *cookie;
- ipa_notify_cb cb;
-
- if (limit && len >= RX_MAX_IND)
- len = RX_MAX_IND;
-
- for (i = len; i > 0; i--) {
- skb = __skb_dequeue(&ipa_ctx->rx_list);
- cb = (ipa_notify_cb)*(u32 *)&(skb->cb[0]);
- cookie = (void *)*(u32 *)&(skb->cb[4]);
- cb(cookie, IPA_RECEIVE, (unsigned long)skb);
- }
-}
-
/**
* ipa_handle_rx_core() - The core functionality of packet reception. This
* function is read from multiple code paths.
@@ -497,9 +675,13 @@
struct ipa_rx_pkt_wrapper *rx_pkt;
struct sk_buff *rx_skb;
struct sps_iovec iov;
+ unsigned int pull_len;
+ unsigned int padding;
int ret;
struct ipa_ep_context *ep;
int cnt = 0;
+ struct completion *compl;
+ struct ipa_tree_node *node;
unsigned int src_pipe;
while ((in_poll_state ? atomic_read(&sys->curr_polling_state) :
@@ -539,7 +721,7 @@
rx_skb->tail = rx_skb->data + rx_pkt->len;
rx_skb->len = rx_pkt->len;
rx_skb->truesize = rx_pkt->len + sizeof(struct sk_buff);
- kfree(rx_pkt);
+ kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
mux_hdr = (struct ipa_a5_mux_hdr *)rx_skb->data;
@@ -554,9 +736,29 @@
IPA_STATS_INC_CNT(ipa_ctx->stats.rx_pkts);
IPA_STATS_EXCP_CNT(mux_hdr->flags, ipa_ctx->stats.rx_excp_pkts);
- if (mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG) {
- if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL)
- ipa_handle_tag_rsp(mux_hdr);
+ if (unlikely(mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG)) {
+ if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL) {
+ /* retrieve the compl object from tag value */
+ mux_hdr++;
+ compl = (struct completion *)
+ ntohl(*((u32 *)mux_hdr));
+ IPADBG("%x %x %p\n", *(u32 *)mux_hdr,
+ *((u32 *)mux_hdr + 1), compl);
+
+ mutex_lock(&ipa_ctx->lock);
+ node = ipa_search(&ipa_ctx->tag_tree,
+ (u32)compl);
+ if (node) {
+ complete_all(compl);
+ rb_erase(&node->node,
+ &ipa_ctx->tag_tree);
+ kmem_cache_free(
+ ipa_ctx->tree_node_cache, node);
+ } else {
+ WARN_ON(1);
+ }
+ mutex_unlock(&ipa_ctx->lock);
+ }
dev_kfree_skb(rx_skb);
ipa_replenish_rx_cache();
++cnt;
@@ -567,22 +769,38 @@
* Any packets arriving over AMPDU_TX should be dispatched
* to the regular WLAN RX data-path.
*/
- if (src_pipe == WLAN_AMPDU_TX_EP)
+ if (unlikely(src_pipe == WLAN_AMPDU_TX_EP))
src_pipe = WLAN_PROD_TX_EP;
- WARN_ON(src_pipe >= IPA_NUM_PIPES);
+ if (unlikely(src_pipe >= IPA_NUM_PIPES ||
+ !ipa_ctx->ep[src_pipe].valid ||
+ !ipa_ctx->ep[src_pipe].client_notify)) {
+ IPAERR("drop pipe=%d ep_valid=%d client_notify=%p\n",
+ src_pipe, ipa_ctx->ep[src_pipe].valid,
+ ipa_ctx->ep[src_pipe].client_notify);
+ dev_kfree_skb(rx_skb);
+ ipa_replenish_rx_cache();
+ ++cnt;
+ continue;
+ }
ep = &ipa_ctx->ep[src_pipe];
- IPADBG("pulling %d bytes from skb\n", ep->pull_len);
- skb_pull(rx_skb, ep->pull_len);
+ pull_len = sizeof(struct ipa_a5_mux_hdr);
+
+ /*
+ * IP packet starts on word boundary
+ * remove the MUX header and any padding and pass the frame to
+ * the client which registered a rx callback on the "src pipe"
+ */
+ padding = ep->cfg.hdr.hdr_len & 0x3;
+ if (padding)
+ pull_len += 4 - padding;
+
+ IPADBG("pulling %d bytes from skb\n", pull_len);
+ skb_pull(rx_skb, pull_len);
ipa_replenish_rx_cache();
- if (ep->client_notify) {
- __skb_queue_tail(&ipa_ctx->rx_list, rx_skb);
- *(u32 *)&(rx_skb->cb[0]) = (u32)ep->client_notify;
- *(u32 *)&(rx_skb->cb[4]) = (u32)ep->priv;
- } else {
- dev_kfree_skb(rx_skb);
- }
+ ep->client_notify(ep->priv, IPA_RECEIVE,
+ (unsigned long)(rx_skb));
cnt++;
};
@@ -601,6 +819,11 @@
goto fail;
}
+ ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect);
+ if (ret) {
+ IPAERR("sps_get_config() failed %d\n", ret);
+ goto fail;
+ }
sys->event.options = SPS_O_EOT;
ret = sps_register_event(sys->ep->ep_hdl, &sys->event);
if (ret) {
@@ -647,6 +870,12 @@
switch (notify->event_id) {
case SPS_EVENT_EOT:
if (!atomic_read(&sys->curr_polling_state)) {
+ ret = sps_get_config(sys->ep->ep_hdl,
+ &sys->ep->connect);
+ if (ret) {
+ IPAERR("sps_get_config() failed %d\n", ret);
+ break;
+ }
sys->ep->connect.options = SPS_O_AUTO_ENABLE |
SPS_O_ACK_TRANSFERS | SPS_O_POLL;
ret = sps_set_config(sys->ep->ep_hdl,
@@ -696,10 +925,8 @@
} else {
inactive_cycles = 0;
}
- ipa_dejitter(true);
} while (inactive_cycles <= POLLING_INACTIVITY_RX);
- ipa_dejitter(false);
ipa_rx_switch_to_intr_mode(sys);
ipa_dec_client_disable_clks();
}
@@ -835,7 +1062,6 @@
break;
case 2:
sys_idx = ipa_ep_idx;
- ipa_ctx->sys[sys_idx].max_len = sys_in->desc_fifo_sz / 8 - 2;
INIT_DELAYED_WORK(&ipa_ctx->sys[sys_idx].switch_to_intr_work,
switch_to_intr_tx_work_func);
break;
@@ -950,87 +1176,9 @@
dev_kfree_skb(skb);
}
-static int ipa_send_two(struct sk_buff *skb, struct ipa_sys_context *sys,
- int dst_ep_idx)
+static void ipa_tx_cmd_comp(void *user1, void *user2)
{
- struct ipa_tx_pkt_wrapper *tx_pktc;
- struct ipa_tx_pkt_wrapper *tx_pktd;
- struct ipa_ep_context *ep = &ipa_ctx->ep[dst_ep_idx];
- unsigned long irq_flags;
- dma_addr_t dma_addrd;
- int rc = -ENOMEM;
-
- tx_pktc = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), GFP_ATOMIC);
- if (!tx_pktc) {
- IPAERR("failed to alloc tx wrapper C\n");
- goto fail_mem_alloc_c;
- }
-
- tx_pktd = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), GFP_ATOMIC);
- if (!tx_pktd) {
- IPAERR("failed to alloc tx wrapper D\n");
- goto fail_mem_alloc_d;
- }
-
- dma_addrd = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
- if (!dma_addrd) {
- IPAERR("failed to DMA wrap\n");
- goto fail_dma_map_d;
- }
-
- INIT_LIST_HEAD(&tx_pktc->link);
- tx_pktc->callback = NULL;
-
- INIT_LIST_HEAD(&tx_pktd->link);
- tx_pktd->mem.phys_base = dma_addrd;
- tx_pktd->mem.base = skb->data;
- tx_pktd->mem.size = skb->len;
- tx_pktd->callback = ipa_tx_comp_usr_notify_release;
- tx_pktd->user1 = skb;
- tx_pktd->user2 = (void *)dst_ep_idx;
-
- spin_lock_irqsave(&sys->spinlock, irq_flags);
- if (sys->len >= sys->max_len)
- goto fail_oom;
- list_add_tail(&tx_pktc->link, &sys->head_desc_list);
- if (sps_transfer_one(sys->ep->ep_hdl, ep->dma_addr, IPA_IP_PACKET_INIT,
- tx_pktc, SPS_IOVEC_FLAG_IMME |
- SPS_IOVEC_FLAG_NO_SUBMIT))
- IPAERR("sps_transfer_one 0 failed\n");
- list_add_tail(&tx_pktd->link, &sys->head_desc_list);
- if (sps_transfer_one(sys->ep->ep_hdl, dma_addrd, skb->len, tx_pktd,
- SPS_IOVEC_FLAG_EOT | SPS_IOVEC_FLAG_INT))
- IPAERR("sps_transfer_one 1 failed\n");
- sys->len += 2;
- spin_unlock_irqrestore(&sys->spinlock, irq_flags);
- return 0;
-
-fail_oom:
- dma_unmap_single(NULL, dma_addrd, skb->len, DMA_TO_DEVICE);
-fail_dma_map_d:
- kfree(tx_pktd);
-fail_mem_alloc_d:
- kfree(tx_pktc);
-fail_mem_alloc_c:
- return rc;
-}
-
-static int ipa_send_data_hw_path(struct sk_buff *skb,
- struct ipa_sys_context *sys, int dst_ep_idx)
-{
- struct ipa_desc desc;
-
- desc.pyld = skb->data;
- desc.len = skb->len;
- desc.type = IPA_DATA_DESC_SKB;
- desc.callback = ipa_tx_comp_usr_notify_release;
- desc.user1 = skb;
- desc.user2 = (void *)dst_ep_idx;
-
- if (ipa_send_one(sys, &desc, true))
- return -EFAULT;
-
- return 0;
+ kfree(user1);
}
/**
@@ -1063,42 +1211,76 @@
int ipa_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
struct ipa_tx_meta *meta)
{
+ struct ipa_desc desc[2];
int ipa_ep_idx;
+ struct ipa_ip_packet_init *cmd;
+
+ memset(&desc, 0, 2 * sizeof(struct ipa_desc));
ipa_ep_idx = ipa_get_ep_mapping(ipa_ctx->mode, dst);
if (unlikely(ipa_ep_idx == -1)) {
IPAERR("dest EP does not exist.\n");
- goto fail;
+ goto fail_gen;
}
if (unlikely(ipa_ctx->ep[ipa_ep_idx].valid == 0)) {
IPAERR("dest EP not valid.\n");
- goto fail;
+ goto fail_gen;
}
if (IPA_CLIENT_IS_CONS(dst)) {
- if (ipa_send_two(skb, &ipa_ctx->sys[IPA_A5_LAN_WAN_OUT],
- ipa_ep_idx)) {
- IPAERR("fail to send pkt_init+skb dst=%d skb=%p\n",
- dst, skb);
- goto fail;
+ cmd = kzalloc(sizeof(struct ipa_ip_packet_init), GFP_ATOMIC);
+ if (!cmd) {
+ IPAERR("failed to alloc immediate command object\n");
+ goto fail_mem_alloc;
+ }
+
+ cmd->destination_pipe_index = ipa_ep_idx;
+ if (meta && meta->mbim_stream_id_valid)
+ cmd->metadata = meta->mbim_stream_id;
+ desc[0].opcode = IPA_IP_PACKET_INIT;
+ desc[0].pyld = cmd;
+ desc[0].len = sizeof(struct ipa_ip_packet_init);
+ desc[0].type = IPA_IMM_CMD_DESC;
+ desc[0].callback = ipa_tx_cmd_comp;
+ desc[0].user1 = cmd;
+ desc[1].pyld = skb->data;
+ desc[1].len = skb->len;
+ desc[1].type = IPA_DATA_DESC_SKB;
+ desc[1].callback = ipa_tx_comp_usr_notify_release;
+ desc[1].user1 = skb;
+ desc[1].user2 = (void *)ipa_ep_idx;
+
+ if (ipa_send(&ipa_ctx->sys[IPA_A5_LAN_WAN_OUT], 2, desc,
+ true)) {
+ IPAERR("fail to send immediate command\n");
+ goto fail_send;
}
IPA_STATS_INC_CNT(ipa_ctx->stats.imm_cmds[IPA_IP_PACKET_INIT]);
} else if (dst == IPA_CLIENT_A5_WLAN_AMPDU_PROD) {
- if (ipa_send_data_hw_path(skb,
- &ipa_ctx->sys[IPA_A5_WLAN_AMPDU_OUT],
- ipa_ep_idx)) {
- IPAERR("fail to send skb dst=%d skb=%p\n", dst, skb);
- goto fail;
+ desc[0].pyld = skb->data;
+ desc[0].len = skb->len;
+ desc[0].type = IPA_DATA_DESC_SKB;
+ desc[0].callback = ipa_tx_comp_usr_notify_release;
+ desc[0].user1 = skb;
+ desc[0].user2 = (void *)ipa_ep_idx;
+
+ if (ipa_send_one(&ipa_ctx->sys[IPA_A5_WLAN_AMPDU_OUT],
+ &desc[0], true)) {
+ IPAERR("fail to send skb\n");
+ goto fail_gen;
}
} else {
IPAERR("%d PROD is not supported.\n", dst);
- goto fail;
+ goto fail_gen;
}
return 0;
-fail:
+fail_send:
+ kfree(cmd);
+fail_mem_alloc:
+fail_gen:
return -EFAULT;
}
EXPORT_SYMBOL(ipa_tx_dp);
@@ -1134,7 +1316,8 @@
rx_len_cached = sys->len;
while (rx_len_cached < IPA_RX_POOL_CEIL) {
- rx_pkt = kmalloc(sizeof(struct ipa_rx_pkt_wrapper), flag);
+ rx_pkt = kmem_cache_zalloc(ipa_ctx->rx_pkt_wrapper_cache,
+ flag);
if (!rx_pkt) {
IPAERR("failed to alloc rx wrapper\n");
goto fail_kmem_cache_alloc;
@@ -1182,7 +1365,7 @@
fail_dma_mapping:
dev_kfree_skb(rx_pkt->skb);
fail_skb_alloc:
- kfree(rx_pkt);
+ kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
fail_kmem_cache_alloc:
if (rx_len_cached == 0) {
IPA_STATS_INC_CNT(ipa_ctx->stats.rx_repl_repost);
@@ -1214,7 +1397,7 @@
dma_unmap_single(NULL, rx_pkt->dma_address, IPA_RX_SKB_SIZE,
DMA_FROM_DEVICE);
dev_kfree_skb(rx_pkt->skb);
- kfree(rx_pkt);
+ kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
}
}
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index 790898a..8ad0b5a 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -119,7 +119,6 @@
#define IPA_DFLT_HDR_NAME "ipa_excp_hdr"
#define IPA_INVALID_L4_PROTOCOL 0xFF
-
#define IPA_CLIENT_IS_PROD(x) (x >= IPA_CLIENT_PROD && x < IPA_CLIENT_CONS)
#define IPA_CLIENT_IS_CONS(x) (x >= IPA_CLIENT_CONS && x < IPA_CLIENT_MAX)
#define IPA_SETFIELD(val, shift, mask) (((val) << (shift)) & (mask))
@@ -364,9 +363,6 @@
bool desc_fifo_client_allocated;
bool data_fifo_client_allocated;
bool suspended;
- unsigned int pull_len;
- struct ipa_ip_packet_init *cmd;
- dma_addr_t dma_addr;
};
/**
@@ -382,7 +378,6 @@
struct ipa_sys_context {
struct list_head head_desc_list;
u32 len;
- u32 max_len;
spinlock_t spinlock;
struct sps_register_event event;
struct ipa_ep_context *ep;
@@ -641,6 +636,8 @@
struct kmem_cache *hdr_cache;
struct kmem_cache *hdr_offset_cache;
struct kmem_cache *rt_tbl_cache;
+ struct kmem_cache *tx_pkt_wrapper_cache;
+ struct kmem_cache *rx_pkt_wrapper_cache;
struct kmem_cache *tree_node_cache;
unsigned long rt_idx_bitmap[IPA_IP_MAX];
struct mutex lock;
@@ -687,7 +684,6 @@
/* featurize if memory footprint becomes a concern */
struct ipa_stats stats;
void *smem_pipe_mem;
- struct sk_buff_head rx_list;
};
/**
@@ -776,6 +772,8 @@
u32 *consumer_handle);
int ipa_send_one(struct ipa_sys_context *sys, struct ipa_desc *desc,
bool in_atomic);
+int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
+ bool in_atomic);
int ipa_get_ep_mapping(enum ipa_operating_mode mode,
enum ipa_client_type client);
int ipa_get_client_mapping(enum ipa_operating_mode mode, int pipe_idx);
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index 912d93c..23de300 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -32,24 +32,6 @@
{ 19, -1, -1, -1, -1, 11, 15, 8, 6, 2, 1, 5, 14, 16, 17, 18, -1, 10, 9, 7, 3, 4 },
};
-static unsigned int ipa_calc_pull_len(u32 hdr_len)
-{
- unsigned int pull_len, padding;
-
- pull_len = sizeof(struct ipa_a5_mux_hdr);
-
- /*
- * IP packet starts on word boundary
- * remove the MUX header and any padding and pass the frame to
- * the client which registered a rx callback on the "src pipe"
- */
- padding = hdr_len & 0x3;
- if (padding)
- pull_len += 4 - padding;
-
- return pull_len;
-}
-
/**
* ipa_cfg_route() - configure IPA route
* @route: IPA route
@@ -769,9 +751,6 @@
ipa_write_reg(ipa_ctx->mmio,
IPA_ENDP_INIT_HDR_n_OFST_v2(clnt_hdl), val);
- if (IPA_CLIENT_IS_PROD(ep->client))
- ep->pull_len = ipa_calc_pull_len(ipa_ep_cfg->hdr_len);
-
return 0;
}
EXPORT_SYMBOL(ipa_cfg_ep_hdr);
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index e91e5d6..53aa475 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -14,6 +14,7 @@
* SPI driver for Qualcomm MSM platforms
*
*/
+
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -2604,11 +2605,12 @@
}
/**
- * msm_spi_dt_to_pdata: copy device-tree data to platfrom data struct
+ * msm_spi_dt_to_pdata: create pdata and read gpio config from device tree
*/
-struct msm_spi_platform_data *
-__init msm_spi_dt_to_pdata(struct platform_device *pdev)
+struct msm_spi_platform_data * __init msm_spi_dt_to_pdata(
+ struct platform_device *pdev, struct msm_spi *dd)
{
+ int i;
struct msm_spi_platform_data *pdata;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
@@ -2618,22 +2620,36 @@
} else {
struct msm_spi_dt_to_pdata_map map[] = {
{"spi-max-frequency",
- &pdata->max_clock_speed, DT_SGST, DT_U32, 0},
+ &pdata->max_clock_speed, DT_SGST, DT_U32, 0},
{"qcom,infinite-mode",
- &pdata->infinite_mode, DT_OPT, DT_U32, 0},
+ &pdata->infinite_mode, DT_OPT, DT_U32, 0},
{"qcom,active-only",
- &pdata->active_only, DT_OPT, DT_BOOL, 0},
+ &pdata->active_only, DT_OPT, DT_BOOL, 0},
{"qcom,master-id",
- &pdata->master_id, DT_SGST, DT_U32, 0},
+ &pdata->master_id, DT_SGST, DT_U32, 0},
{"qcom,ver-reg-exists",
- &pdata->ver_reg_exists, DT_OPT, DT_BOOL, 0},
+ &pdata->ver_reg_exists, DT_OPT, DT_BOOL, 0},
{"qcom,use-bam",
- &pdata->use_bam, DT_OPT, DT_BOOL, 0},
+ &pdata->use_bam, DT_OPT, DT_BOOL, 0},
{"qcom,bam-consumer-pipe-index",
- &pdata->bam_consumer_pipe_index, DT_OPT, DT_U32, 0},
+ &pdata->bam_consumer_pipe_index, DT_OPT, DT_U32, 0},
{"qcom,bam-producer-pipe-index",
- &pdata->bam_producer_pipe_index, DT_OPT, DT_U32, 0},
- {NULL, NULL, 0, 0, 0},
+ &pdata->bam_producer_pipe_index, DT_OPT, DT_U32, 0},
+ {"qcom,gpio-clk",
+ &dd->spi_gpios[0], DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-miso",
+ &dd->spi_gpios[1], DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-mosi",
+ &dd->spi_gpios[2], DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-cs0",
+ &dd->cs_gpios[0].gpio_num, DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-cs1",
+ &dd->cs_gpios[1].gpio_num, DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-cs2",
+ &dd->cs_gpios[2].gpio_num, DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-cs3",
+ &dd->cs_gpios[3].gpio_num, DT_OPT, DT_GPIO, -1},
+ {NULL, NULL, 0, 0, 0},
};
if (msm_spi_dt_to_pdata_populate(pdev, pdata, map)) {
@@ -2655,6 +2671,10 @@
pdata->use_bam = false;
}
}
+
+ for (i = 0; i < ARRAY_SIZE(spi_cs_rsrcs); ++i)
+ dd->cs_gpios[i].valid = (dd->cs_gpios[i].gpio_num >= 0);
+
return pdata;
}
@@ -2714,7 +2734,6 @@
int clk_enabled = 0;
int pclk_enabled = 0;
struct msm_spi_platform_data *pdata;
- enum of_gpio_flags flags;
master = spi_alloc_master(&pdev->dev, sizeof(struct msm_spi));
if (!master) {
@@ -2734,7 +2753,7 @@
if (pdev->dev.of_node) {
dd->qup_ver = SPI_QUP_VERSION_BFAM;
master->dev.of_node = pdev->dev.of_node;
- pdata = msm_spi_dt_to_pdata(pdev);
+ pdata = msm_spi_dt_to_pdata(pdev, dd);
if (!pdata) {
rc = -ENOMEM;
goto err_probe_exit;
@@ -2746,18 +2765,6 @@
"using default bus_num %d\n", pdev->id);
else
master->bus_num = pdev->id = rc;
-
- for (i = 0; i < ARRAY_SIZE(spi_rsrcs); ++i) {
- dd->spi_gpios[i] = of_get_gpio_flags(pdev->dev.of_node,
- i, &flags);
- }
-
- for (i = 0; i < ARRAY_SIZE(spi_cs_rsrcs); ++i) {
- dd->cs_gpios[i].gpio_num = of_get_named_gpio_flags(
- pdev->dev.of_node, "cs-gpios",
- i, &flags);
- dd->cs_gpios[i].valid = 0;
- }
} else {
pdata = pdev->dev.platform_data;
dd->qup_ver = SPI_QUP_VERSION_NONE;
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index bb0b2fb..0cfd515 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -393,6 +393,7 @@
u32 recip;
u32 wValue;
u32 wIndex;
+ u32 reg;
int ret;
wValue = le16_to_cpu(ctrl->wValue);
@@ -413,6 +414,13 @@
return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ if (set)
+ reg |= DWC3_DCTL_INITU1ENA;
+ else
+ reg &= ~DWC3_DCTL_INITU1ENA;
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
break;
case USB_DEVICE_U2_ENABLE:
@@ -420,6 +428,13 @@
return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ if (set)
+ reg |= DWC3_DCTL_INITU2ENA;
+ else
+ reg &= ~DWC3_DCTL_INITU2ENA;
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
break;
case USB_DEVICE_LTM_ENABLE:
@@ -524,6 +539,7 @@
{
u32 cfg;
int ret;
+ u32 reg;
dwc->start_config_issued = false;
cfg = le16_to_cpu(ctrl->wValue);
@@ -538,6 +554,14 @@
/* if the cfg matches and the cfg is non zero */
if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
dwc->dev_state = DWC3_CONFIGURED_STATE;
+ /*
+ * Enable transition to U1/U2 state when
+ * nothing is pending from application.
+ */
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA);
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
dwc->resize_fifos = true;
dev_dbg(dwc->dev, "resize fifos flag SET\n");
}
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 3cad3ce..8d8c30e 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -16,6 +16,8 @@
#define MSM_USB_BASE (udc->regs)
+#define CI13XXX_MSM_MAX_ITC_LEVEL 6
+
struct ci13xxx_udc_context {
int irq;
void __iomem *regs;
@@ -177,7 +179,7 @@
CI13XXX_ZERO_ITC |
CI13XXX_DISABLE_STREAMING |
CI13XXX_IS_OTG,
-
+ .nz_itc = 0,
.notify_event = ci13xxx_msm_notify_event,
};
@@ -230,10 +232,21 @@
static int ci13xxx_msm_probe(struct platform_device *pdev)
{
struct resource *res;
- int ret;
+ int ret, rc;
+ int itc_level = 0;
dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
+ if (pdev->dev.of_node) {
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,itc-level",
+ &itc_level);
+ /* Acceptable values for nz_itc are: 0,1,2,4,8,16,32,64 */
+ if (itc_level > CI13XXX_MSM_MAX_ITC_LEVEL || rc)
+ ci13xxx_msm_udc_driver.nz_itc = 0;
+ else
+ ci13xxx_msm_udc_driver.nz_itc = 1 << itc_level;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "failed to get platform resource mem\n");
@@ -313,9 +326,18 @@
writel_relaxed(val, USB_GENCONFIG);
}
+static const struct of_device_id ci13xx_msm_dt_match[] = {
+ { .compatible = "qcom,ci13xxx_msm",
+ },
+ {}
+};
+
static struct platform_driver ci13xxx_msm_driver = {
.probe = ci13xxx_msm_probe,
- .driver = { .name = "msm_hsusb", },
+ .driver = {
+ .name = "msm_hsusb",
+ .of_match_table = ci13xx_msm_dt_match,
+ },
.remove = ci13xxx_msm_remove,
};
MODULE_ALIAS("platform:msm_hsusb");
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 939eb6d..e7074a2 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -367,7 +367,10 @@
* 8 micro frames. If CPU can handle interrupts at faster rate, ITC
* can be set to lesser value to gain performance.
*/
- if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
+ if (udc->udc_driver->nz_itc)
+ hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK,
+ USBCMD_ITC(udc->udc_driver->nz_itc));
+ else if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 4c5b38d..09404c8 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -129,6 +129,7 @@
struct ci13xxx_udc_driver {
const char *name;
unsigned long flags;
+ unsigned int nz_itc;
#define CI13XXX_REGS_SHARED BIT(0)
#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1)
#define CI13XXX_PULLUP_ON_VBUS BIT(2)
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 9dd9978..edcafcc 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -848,6 +848,7 @@
d->rx_req->context = port;
d->rx_req->complete = gbam_endless_rx_complete;
d->rx_req->length = 0;
+ d->rx_req->no_interrupt = 1;
sps_params = (MSM_SPS_MODE | d->src_pipe_idx |
MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER;
d->rx_req->udc_priv = sps_params;
@@ -863,6 +864,7 @@
d->tx_req->context = port;
d->tx_req->complete = gbam_endless_tx_complete;
d->tx_req->length = 0;
+ d->tx_req->no_interrupt = 1;
sps_params = (MSM_SPS_MODE | d->dst_pipe_idx |
MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER;
d->tx_req->udc_priv = sps_params;
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 5c7e52f..d470edf 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -296,6 +296,7 @@
d->rx_req->context = port;
d->rx_req->complete = bam_data_endless_rx_complete;
d->rx_req->length = 0;
+ d->rx_req->no_interrupt = 1;
sps_params = (SPS_PARAMS_SPS_MODE | d->src_pipe_idx |
MSM_VENDOR_ID) & ~SPS_PARAMS_TBE;
d->rx_req->udc_priv = sps_params;
@@ -306,6 +307,7 @@
d->tx_req->context = port;
d->tx_req->complete = bam_data_endless_tx_complete;
d->tx_req->length = 0;
+ d->tx_req->no_interrupt = 1;
sps_params = (SPS_PARAMS_SPS_MODE | d->dst_pipe_idx |
MSM_VENDOR_ID) & ~SPS_PARAMS_TBE;
d->tx_req->udc_priv = sps_params;
diff --git a/drivers/video/msm/mdss/dsi_io_v2.c b/drivers/video/msm/mdss/dsi_io_v2.c
index cbdd241..273fb54 100644
--- a/drivers/video/msm/mdss/dsi_io_v2.c
+++ b/drivers/video/msm/mdss/dsi_io_v2.c
@@ -437,5 +437,9 @@
void msm_dsi_phy_off(unsigned char *ctrl_base)
{
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_PLL_CTRL_5, 0x05f);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_0, 0x02);
MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_0, 0x00);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_1, 0x7f);
+ MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0);
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 52140b2..963d3fb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -2549,7 +2549,7 @@
hist_info = &mdss_pp_res->dspp_hist[dspp_num];
mutex_lock(&hist_info->hist_mutex);
for (j = 0; j < HIST_V_SIZE; j++)
- hist_concat[i] += hist_info->data[i];
+ hist_concat[j] += hist_info->data[j];
mutex_unlock(&hist_info->hist_mutex);
}
hist_data_addr = hist_concat;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 4fd90f9..97803b3 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -2249,6 +2249,9 @@
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
};
static const struct snd_kcontrol_new sec_auxpcm_rx_port_mixer_controls[] = {
@@ -2258,6 +2261,9 @@
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
};
static const struct snd_kcontrol_new sbus_1_rx_port_mixer_controls[] = {
@@ -3384,8 +3390,10 @@
{"AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"AUXPCM_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
{"AUX_PCM_RX", NULL, "AUXPCM_RX Port Mixer"},
+ {"SEC_AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"SEC_AUXPCM_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
{"SEC_AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"SEC_AUX_PCM_RX", NULL, "SEC_AUXPCM_RX Port Mixer"},