Merge "defconfig: Enable CPUFreq for msm-copper" into msm-3.0
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 5b55f99..1cf5df3 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -303,7 +303,6 @@
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
-CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
CONFIG_MMC_MSM_SDC3_SUPPORT=y
CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 7f9c54d..8d31ee6 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -304,7 +304,6 @@
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
-CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
CONFIG_MMC_MSM_SDC3_SUPPORT=y
CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 3ee4132..736f2bb 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -334,7 +334,6 @@
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
-CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
# CONFIG_MMC_MSM_SDC1_SUPPORT is not set
CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index 1e037ea..bc464b4 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -333,7 +333,6 @@
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
-CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
# CONFIG_MMC_MSM_SDC1_SUPPORT is not set
CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index 8c2e3a6..e7f1a67 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -388,7 +388,6 @@
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
-CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 0e83888..c8dfd7a 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -389,7 +389,6 @@
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
-CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 70cba0f..601f235 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -245,7 +245,6 @@
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
-CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
CONFIG_MMC_MSM_SPS_SUPPORT=y
CONFIG_NEW_LEDS=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 2609aca..b465da5 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -258,6 +258,11 @@
obj-$(CONFIG_PM8921_BMS) += bms-batterydata.o bms-batterydata-desay.o
obj-$(CONFIG_MACH_APQ8064_SIM) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_MACH_APQ8064_RUMI3) += board-8064-all.o board-8064-regulator.o
+obj-$(CONFIG_MACH_APQ8064_CDP) += board-8064-all.o board-8064-regulator.o
+obj-$(CONFIG_MACH_APQ8064_MTP) += board-8064-all.o board-8064-regulator.o
+obj-$(CONFIG_MACH_APQ8064_LIQUID) += board-8064-all.o board-8064-regulator.o
+obj-$(CONFIG_MACH_MPQ8064_HRD) += board-8064-all.o board-8064-regulator.o
+obj-$(CONFIG_MACH_MPQ8064_DTV) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o
obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.o
diff --git a/arch/arm/mach-msm/acpuclock-7201.c b/arch/arm/mach-msm/acpuclock-7201.c
index 35e8eba..b6c0b26 100644
--- a/arch/arm/mach-msm/acpuclock-7201.c
+++ b/arch/arm/mach-msm/acpuclock-7201.c
@@ -171,7 +171,7 @@
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 0, 400000, ACPU_PLL_4, 6, 1, 50000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
- { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
@@ -186,7 +186,7 @@
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 120000 },
{ 0, 400000, ACPU_PLL_4, 6, 1, 50000, 3, 4, 120000 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 120000 },
- { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
@@ -200,8 +200,8 @@
{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
- { 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
- { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
+ { 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 160000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
@@ -215,8 +215,8 @@
{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
- { 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
- { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
+ { 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 160000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
@@ -229,8 +229,8 @@
{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 3, 61440 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
- { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
- { 0, 604800, ACPU_PLL_4, 6, 1, 75600, 3, 6, 200000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
+ { 0, 604800, ACPU_PLL_4, 6, 1, 75600, 3, 6, 160000 },
{ 1, 1209600, ACPU_PLL_4, 6, 0, 151200, 3, 7, 200000},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
@@ -243,8 +243,8 @@
{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 3, 98304 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
- { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
- { 0, 604800, ACPU_PLL_4, 6, 1, 75600, 3, 6, 200000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
+ { 0, 604800, ACPU_PLL_4, 6, 1, 75600, 3, 6, 160000 },
{ 1, 1209600, ACPU_PLL_4, 6, 0, 151200, 3, 7, 200000},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
@@ -273,7 +273,7 @@
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 0, 400000, ACPU_PLL_4, 6, 1, 50000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
- { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
@@ -288,7 +288,7 @@
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 120000 },
{ 0, 400000, ACPU_PLL_4, 6, 1, 50000, 3, 4, 120000 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 120000 },
- { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
@@ -302,8 +302,8 @@
{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
- { 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
- { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
+ { 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 160000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
@@ -317,8 +317,8 @@
{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
- { 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
- { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
+ { 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 160000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
@@ -468,6 +468,10 @@
reg_clksel ^= 1;
writel_relaxed(reg_clksel, A11S_CLK_SEL_ADDR);
+ /* Wait for the clock switch to complete */
+ mb();
+ udelay(50);
+
/*
* If the new clock divider is lower than the previous, then
* program the divider after switching the clock
@@ -619,8 +623,6 @@
/* Adjust the global one */
loops_per_jiffy = cur_s->lpj;
- mb();
- udelay(50);
}
/* Nothing else to do for SWFI. */
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 89d7fc9..6361d6d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -982,11 +982,13 @@
int msm_bam_dmux_is_ch_low(uint32_t id)
{
+ unsigned long flags;
int ret;
if (id >= BAM_DMUX_NUM_CHANNELS)
return -EINVAL;
+ spin_lock_irqsave(&bam_ch[id].lock, flags);
bam_ch[id].use_wm = 1;
ret = bam_ch[id].num_tx_pkts <= LOW_WATERMARK;
DBG("%s: ch %d num tx pkts=%d, LWM=%d\n", __func__,
@@ -995,6 +997,7 @@
ret = -ENODEV;
pr_err("%s: port not open: %d\n", __func__, bam_ch[id].status);
}
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
return ret;
}
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 9080e60..c7b3af5 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -499,6 +499,41 @@
.sensor_type = BAYER_SENSOR,
};
+static struct camera_vreg_t apq_8064_s5k3l1yx_vreg[] = {
+ {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+ {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+ {"cam_vio", REG_VS, 0, 0, 0},
+ {"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
+};
+
+static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
+ .flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_csi_lane_params s5k3l1yx_csi_lane_params = {
+ .csi_lane_assign = 0xE4,
+ .csi_lane_mask = 0xF,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
+ .mount_angle = 90,
+ .cam_vreg = apq_8064_s5k3l1yx_vreg,
+ .num_vreg = ARRAY_SIZE(apq_8064_s5k3l1yx_vreg),
+ .gpio_conf = &apq8064_back_cam_gpio_conf,
+ .i2c_conf = &apq8064_back_cam_i2c_conf,
+ .csi_lane_params = &s5k3l1yx_csi_lane_params,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_s5k3l1yx_data = {
+ .sensor_name = "s5k3l1yx",
+ .pdata = &msm_camera_csi_device_data[0],
+ .flash_data = &flash_s5k3l1yx,
+ .sensor_platform_info = &sensor_board_info_s5k3l1yx,
+ .csi_if = 1,
+ .camera_type = BACK_CAMERA_2D,
+ .sensor_type = BAYER_SENSOR,
+};
+
static struct camera_vreg_t apq_8064_mt9m114_vreg[] = {
{"cam_vio", REG_VS, 0, 0, 0},
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
@@ -603,6 +638,10 @@
I2C_BOARD_INFO("imx091", 0x34),
.platform_data = &msm_camera_sensor_imx091_data,
},
+ {
+ I2C_BOARD_INFO("s5k3l1yx", 0x20),
+ .platform_data = &msm_camera_sensor_s5k3l1yx_data,
+ },
};
struct msm_camera_board_info apq8064_camera_board_info = {
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 24df393..ae2de20 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -62,6 +62,7 @@
REGULATOR_SUPPLY("cam_vana", "4-0048"),
REGULATOR_SUPPLY("cam_vana", "4-006c"),
REGULATOR_SUPPLY("cam_vana", "4-0034"),
+ REGULATOR_SUPPLY("cam_vana", "4-0020"),
};
VREG_CONSUMERS(L9) = {
REGULATOR_SUPPLY("8921_l9", NULL),
@@ -80,6 +81,7 @@
REGULATOR_SUPPLY("cam_vdig", "4-0048"),
REGULATOR_SUPPLY("cam_vdig", "4-006c"),
REGULATOR_SUPPLY("cam_vdig", "4-0034"),
+ REGULATOR_SUPPLY("cam_vdig", "4-0020"),
REGULATOR_SUPPLY("8921_l12", NULL),
};
VREG_CONSUMERS(L14) = {
@@ -94,6 +96,7 @@
REGULATOR_SUPPLY("cam_vaf", "4-0048"),
REGULATOR_SUPPLY("cam_vaf", "4-006c"),
REGULATOR_SUPPLY("cam_vaf", "4-0034"),
+ REGULATOR_SUPPLY("cam_vaf", "4-0020"),
};
VREG_CONSUMERS(L17) = {
REGULATOR_SUPPLY("8921_l17", NULL),
@@ -197,6 +200,7 @@
REGULATOR_SUPPLY("cam_vio", "4-0048"),
REGULATOR_SUPPLY("cam_vio", "4-006c"),
REGULATOR_SUPPLY("cam_vio", "4-0034"),
+ REGULATOR_SUPPLY("cam_vio", "4-0020"),
};
VREG_CONSUMERS(LVS6) = {
REGULATOR_SUPPLY("8921_lvs6", NULL),
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index d06b5bd..3f4266f 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -588,6 +588,12 @@
.name = "usb",
};
+static int phy_init_seq[] = {
+ 0x38, 0x81, /* update DC voltage level */
+ 0x24, 0x82, /* set pre-emphasis and rise/fall time */
+ -1
+};
+
static struct msm_otg_platform_data msm_otg_pdata = {
.mode = USB_OTG,
.otg_control = OTG_PMIC_CONTROL,
@@ -595,6 +601,7 @@
.pmic_id_irq = PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
.power_budget = 750,
.bus_scale_table = &usb_bus_scale_pdata,
+ .phy_init_seq = phy_init_seq,
};
static struct msm_usb_host_platform_data msm_ehci_host_pdata3 = {
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 5b632bd..bfb8be3 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -55,7 +55,7 @@
.pull = GPIOMUX_PULL_NONE,
};
-static struct gpiomux_setting gsbi5 = {
+static struct gpiomux_setting gsbi_uart = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_8MA,
.pull = GPIOMUX_PULL_NONE,
@@ -327,30 +327,6 @@
},
},
{
- .gpio = 22, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
- .gpio = 23, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
- .gpio = 24, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
- .gpio = 25, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
.gpio = 44, /* GSBI12 I2C QUP SDA */
.settings = {
[GPIOMUX_SUSPENDED] = &gsbi12,
@@ -376,6 +352,60 @@
},
};
+static struct msm_gpiomux_config msm8960_gsbi5_uart_configs[] __initdata = {
+ {
+ .gpio = 22, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 23, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 24, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 25, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_gsbi8_uart_configs[] __initdata = {
+ {
+ .gpio = 34, /* GSBI8 UART3 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 35, /* GSBI8 UART3 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 36, /* GSBI8 UART3 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 37, /* GSBI8 UART3 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+};
+
static struct msm_gpiomux_config msm8960_slimbus_config[] __initdata = {
{
.gpio = 60, /* slimbus data */
@@ -686,5 +716,12 @@
msm_gpiomux_install(msm8960_mdp_vsync_configs,
ARRAY_SIZE(msm8960_mdp_vsync_configs));
+ if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+ msm_gpiomux_install(msm8960_gsbi8_uart_configs,
+ ARRAY_SIZE(msm8960_gsbi8_uart_configs));
+ else
+ msm_gpiomux_install(msm8960_gsbi5_uart_configs,
+ ARRAY_SIZE(msm8960_gsbi5_uart_configs));
+
return 0;
}
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 257b27f..f462c7a 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2192,7 +2192,6 @@
static struct platform_device *common_devices[] __initdata = {
&msm8960_device_dmov,
&msm_device_smd,
- &msm8960_device_uart_gsbi5,
&msm_device_uart_dm6,
&msm_device_saw_core0,
&msm_device_saw_core1,
@@ -2275,6 +2274,7 @@
};
static struct platform_device *sim_devices[] __initdata = {
+ &msm8960_device_uart_gsbi5,
&msm8960_device_otg,
&msm8960_device_gadget_peripheral,
&msm_device_hsusb_host,
@@ -2320,6 +2320,7 @@
};
static struct platform_device *rumi3_devices[] __initdata = {
+ &msm8960_device_uart_gsbi5,
&msm_kgsl_3d0,
&msm_kgsl_2d0,
&msm_kgsl_2d1,
@@ -2900,6 +2901,12 @@
platform_device_register(&msm8960_device_ext_3p3v_vreg);
if (machine_is_msm8960_cdp())
platform_device_register(&msm8960_device_ext_l2_vreg);
+
+ if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+ platform_device_register(&msm8960_device_uart_gsbi8);
+ else
+ platform_device_register(&msm8960_device_uart_gsbi5);
+
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm8960_pm8921_gpio_mpp_init();
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
diff --git a/arch/arm/mach-msm/board-9615-storage.c b/arch/arm/mach-msm/board-9615-storage.c
index 5a795c0..c73e5a9 100644
--- a/arch/arm/mach-msm/board-9615-storage.c
+++ b/arch/arm/mach-msm/board-9615-storage.c
@@ -202,9 +202,7 @@
.sup_clk_cnt = ARRAY_SIZE(sdc2_sup_clk_rates),
.pclk_src_dfab = 1,
.pin_data = &mmc_slot_pin_data[SDCC2],
-#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
.sdiowakeup_irq = MSM_GPIO_TO_INT(GPIO_SDC2_DAT1_WAKEUP),
-#endif
};
static struct mmc_platform_data *msm9615_sdc2_pdata = &sdc2_data;
#else
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index e96284a..e2076f8 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -28,7 +28,7 @@
#include "board-msm7627a.h"
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_SIZE 0x261000
+#define MSM_FB_SIZE 0x2FD000
#define MSM7x25A_MSM_FB_SIZE 0xE1000
#else
#define MSM_FB_SIZE 0x196000
@@ -684,6 +684,18 @@
}
};
+static struct msm_panel_common_pdata mipi_NT35516_pdata = {
+ .pmic_backlight = NULL,
+};
+
+static struct platform_device mipi_dsi_NT35516_panel_device = {
+ .name = "mipi_truly_tft540960_1_e",
+ .id = 0,
+ .dev = {
+ .platform_data = &mipi_NT35516_pdata,
+ }
+};
+
static struct platform_device *msm_fb_devices[] __initdata = {
&msm_fb_device,
&lcdc_toshiba_panel_device,
@@ -708,6 +720,7 @@
static struct platform_device *evb_fb_devices[] __initdata = {
&msm_fb_device,
&mipi_dsi_NT35510_panel_device,
+ &mipi_dsi_NT35516_panel_device,
};
void __init msm_msm7627a_allocate_memory_regions(void)
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index 564c59d..11d9a21 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -293,9 +293,7 @@
.ocr_mask = MMC_VDD_28_29 | MMC_VDD_165_195,
.translate_vdd = msm_sdcc_setup_power,
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
-#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
.sdiowakeup_irq = MSM_GPIO_TO_INT(66),
-#endif
.msmsdcc_fmin = 144000,
.msmsdcc_fmid = 24576000,
.msmsdcc_fmax = 49152000,
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index 34ae4c8..f1ff49a 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -1518,9 +1518,7 @@
.ocr_mask = MMC_VDD_28_29,
.translate_vdd = msm_sdcc_setup_power,
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
-#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
.sdiowakeup_irq = MSM_GPIO_TO_INT(66),
-#endif
.msmsdcc_fmin = 144000,
.msmsdcc_fmid = 24576000,
.msmsdcc_fmax = 49152000,
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 972cb22..cf608ad 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -6103,9 +6103,7 @@
.ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
.translate_vdd = msm_sdcc_setup_power,
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
-#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
.sdiowakeup_irq = MSM_GPIO_TO_INT(118),
-#endif
.msmsdcc_fmin = 144000,
.msmsdcc_fmid = 24576000,
.msmsdcc_fmax = 49152000,
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index b9050cd..5db8de4 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2882,7 +2882,7 @@
.id = 2,
.dev = { .platform_data = &android_pmem_adsp_pdata },
};
-#endif
+
static struct android_pmem_platform_data android_pmem_audio_pdata = {
.name = "pmem_audio",
.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
@@ -2895,7 +2895,7 @@
.id = 4,
.dev = { .platform_data = &android_pmem_audio_pdata },
};
-
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
#define PMEM_BUS_WIDTH(_bw) \
{ \
.vectors = &(struct msm_bus_vectors){ \
@@ -2954,8 +2954,8 @@
.id = 7,
.dev = { .platform_data = &android_pmem_smipool_pdata },
};
-#endif
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
#define GPIO_DONGLE_PWR_EN 258
static void setup_display_power(void);
@@ -4264,9 +4264,9 @@
&android_pmem_device,
&android_pmem_adsp_device,
&android_pmem_smipool_device,
-#endif
&android_pmem_audio_device,
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
#ifdef CONFIG_MSM_ROTATOR
&msm_rotator_device,
#endif
@@ -5195,9 +5195,9 @@
&android_pmem_device,
&android_pmem_adsp_device,
&android_pmem_smipool_device,
-#endif
&android_pmem_audio_device,
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
#ifdef CONFIG_MSM_ROTATOR
&msm_rotator_device,
#endif
@@ -5491,15 +5491,19 @@
if (hdmi_is_primary)
pmem_sf_size = MSM_HDMI_PRIM_PMEM_SF_SIZE;
android_pmem_pdata.size = pmem_sf_size;
-#endif
android_pmem_audio_pdata.size = MSM_PMEM_AUDIO_SIZE;
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
}
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
static void __init reserve_memory_for(struct android_pmem_platform_data *p)
{
msm8x60_reserve_table[p->memory_type].size += p->size;
}
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
static void __init reserve_pmem_memory(void)
{
@@ -5508,10 +5512,10 @@
reserve_memory_for(&android_pmem_adsp_pdata);
reserve_memory_for(&android_pmem_smipool_pdata);
reserve_memory_for(&android_pmem_pdata);
-#endif
reserve_memory_for(&android_pmem_audio_pdata);
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
msm8x60_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-#endif
+#endif /*CONFIG_ANDROID_PMEM*/
}
static void __init reserve_mdp_memory(void);
@@ -8496,10 +8500,8 @@
if (machine_is_msm8x60_fusion())
msm8x60_sdc2_data.msmsdcc_fmax = 24000000;
if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
-#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
msm8x60_sdc2_data.sdiowakeup_irq = gpio_to_irq(144);
msm_sdcc_setup_gpio(2, 1);
-#endif
msm_add_sdcc(2, &msm8x60_sdc2_data);
}
#endif
@@ -8560,10 +8562,8 @@
if (machine_is_msm8x60_fusion())
msm8x60_sdc5_data.msmsdcc_fmax = 24000000;
if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
-#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
msm8x60_sdc5_data.sdiowakeup_irq = gpio_to_irq(99);
msm_sdcc_setup_gpio(5, 1);
-#endif
msm_add_sdcc(5, &msm8x60_sdc5_data);
}
#endif
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 60457cc..7b27c4e 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -797,9 +797,9 @@
ARRAY_SIZE(qrd7627a_devices));
}
- if (machine_is_msm7627a_qrd3())
+ if (machine_is_msm7627a_qrd3() || machine_is_msm7627a_evb())
platform_add_devices(qrd3_devices,
- ARRAY_SIZE(qrd3_devices));
+ ARRAY_SIZE(qrd3_devices));
platform_add_devices(common_devices,
ARRAY_SIZE(common_devices));
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index af8f0af..7d1bcf3 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5007,6 +5007,7 @@
CLK_LOOKUP("core_clk", amp_clk.c, ""),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-001a"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0034"),
+ CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0020"),
CLK_LOOKUP("cam_clk", cam1_clk.c, "4-0048"),
CLK_LOOKUP("cam_clk", cam1_clk.c, "4-006c"),
CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, "msm_csid.0"),
@@ -5231,7 +5232,7 @@
CLK_LOOKUP("core_clk", gsbi5_uart_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("core_clk", gsbi6_uart_clk.c, "msm_serial_hs.0"),
CLK_LOOKUP("core_clk", gsbi7_uart_clk.c, ""),
- CLK_LOOKUP("core_clk", gsbi8_uart_clk.c, ""),
+ CLK_LOOKUP("core_clk", gsbi8_uart_clk.c, "msm_serial_hsl.1"),
CLK_LOOKUP("core_clk", gsbi9_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi10_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi11_uart_clk.c, ""),
@@ -5284,7 +5285,7 @@
CLK_LOOKUP("iface_clk", gsbi5_p_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("iface_clk", gsbi6_p_clk.c, "msm_serial_hs.0"),
CLK_LOOKUP("iface_clk", gsbi7_p_clk.c, ""),
- CLK_LOOKUP("iface_clk", gsbi8_p_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gsbi8_p_clk.c, "msm_serial_hsl.1"),
CLK_LOOKUP("iface_clk", gsbi9_p_clk.c, ""),
CLK_LOOKUP("iface_clk", gsbi10_p_clk.c, "qup_i2c.10"),
CLK_LOOKUP("iface_clk", gsbi11_p_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index 9ad653d..8ff4878 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -29,7 +29,7 @@
list_for_each_entry(clk, &parent->children, siblings) {
struct clk_voter *v = to_clk_voter(clk);
if (v->enabled)
- rate = max(v->rate, rate);
+ rate = max(clk->rate, rate);
}
return rate;
}
@@ -54,10 +54,10 @@
list_for_each_entry(clkp, &parent->children, siblings) {
clkh = to_clk_voter(clkp);
if (clkh->enabled && clkh != v)
- other_rate = max(clkh->rate, other_rate);
+ other_rate = max(clkp->rate, other_rate);
}
- cur_rate = max(other_rate, v->rate);
+ cur_rate = max(other_rate, clk->rate);
new_rate = max(other_rate, rate);
if (new_rate != cur_rate) {
@@ -66,7 +66,7 @@
goto unlock;
}
}
- v->rate = rate;
+ clk->rate = rate;
unlock:
spin_unlock_irqrestore(&voter_clk_lock, flags);
@@ -89,8 +89,8 @@
* than the current rate.
*/
cur_rate = voter_clk_aggregate_rate(parent);
- if (v->rate > cur_rate) {
- ret = clk_set_rate(parent, v->rate);
+ if (clk->rate > cur_rate) {
+ ret = clk_set_rate(parent, clk->rate);
if (ret)
goto out;
}
@@ -116,7 +116,7 @@
*/
v->enabled = false;
new_rate = voter_clk_aggregate_rate(parent);
- cur_rate = max(new_rate, v->rate);
+ cur_rate = max(new_rate, clk->rate);
if (new_rate < cur_rate)
clk_set_rate(parent, new_rate);
@@ -124,18 +124,6 @@
spin_unlock_irqrestore(&voter_clk_lock, flags);
}
-static unsigned long voter_clk_get_rate(struct clk *clk)
-{
- unsigned long rate, flags;
- struct clk_voter *v = to_clk_voter(clk);
-
- spin_lock_irqsave(&voter_clk_lock, flags);
- rate = v->rate;
- spin_unlock_irqrestore(&voter_clk_lock, flags);
-
- return rate;
-}
-
static int voter_clk_is_enabled(struct clk *clk)
{
struct clk_voter *v = to_clk_voter(clk);
@@ -163,7 +151,6 @@
.enable = voter_clk_enable,
.disable = voter_clk_disable,
.set_rate = voter_clk_set_rate,
- .get_rate = voter_clk_get_rate,
.is_enabled = voter_clk_is_enabled,
.round_rate = voter_clk_round_rate,
.get_parent = voter_clk_get_parent,
diff --git a/arch/arm/mach-msm/clock-voter.h b/arch/arm/mach-msm/clock-voter.h
index 10353d4..de17894 100644
--- a/arch/arm/mach-msm/clock-voter.h
+++ b/arch/arm/mach-msm/clock-voter.h
@@ -19,7 +19,6 @@
struct clk_voter {
bool enabled;
- unsigned long rate;
struct clk *parent;
struct clk c;
};
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 029fc6f3..3255248 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -36,6 +36,7 @@
#include <sound/apr_audio.h>
#include <mach/msm_tsif.h>
#include <mach/qdss.h>
+#include <mach/msm_serial_hs_lite.h>
#include "clock.h"
#include "devices.h"
#include "devices-msm8x60.h"
@@ -72,6 +73,7 @@
#define MSM_UART2DM_PHYS (MSM_GSBI2_PHYS + 0x40000)
#define MSM_UART5DM_PHYS (MSM_GSBI5_PHYS + 0x40000)
#define MSM_UART6DM_PHYS (MSM_GSBI6_PHYS + 0x40000)
+#define MSM_UART8DM_PHYS (MSM_GSBI8_PHYS + 0x40000)
/* GSBI QUP devices */
#define MSM_GSBI1_QUP_PHYS (MSM_GSBI1_PHYS + 0x80000)
@@ -308,6 +310,39 @@
.num_resources = ARRAY_SIZE(resources_uart_gsbi5),
.resource = resources_uart_gsbi5,
};
+
+static struct msm_serial_hslite_platform_data uart_gsbi8_pdata = {
+ .line = 0,
+};
+
+static struct resource resources_uart_gsbi8[] = {
+ {
+ .start = GSBI8_UARTDM_IRQ,
+ .end = GSBI8_UARTDM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MSM_UART8DM_PHYS,
+ .end = MSM_UART8DM_PHYS + PAGE_SIZE - 1,
+ .name = "uartdm_resource",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM_GSBI8_PHYS,
+ .end = MSM_GSBI8_PHYS + PAGE_SIZE - 1,
+ .name = "gsbi_resource",
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device msm8960_device_uart_gsbi8 = {
+ .name = "msm_serial_hsl",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(resources_uart_gsbi8),
+ .resource = resources_uart_gsbi8,
+ .dev.platform_data = &uart_gsbi8_pdata,
+};
+
/* MSM Video core device */
#ifdef CONFIG_MSM_BUS_SCALING
static struct msm_bus_vectors vidc_init_vectors[] = {
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index 77314e7..5ec339e 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -855,6 +855,7 @@
.num_levels = 1,
.set_grp_async = NULL,
.idle_timeout = HZ,
+ .strtstp_sleepwake = true,
.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM,
};
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 4575166..70f1c2c 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -809,6 +809,7 @@
.num_levels = 3,
.set_grp_async = set_grp_xbar_async,
.idle_timeout = HZ,
+ .strtstp_sleepwake = true,
.nap_allowed = false,
.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM,
};
@@ -836,8 +837,10 @@
void __init msm8x25_kgsl_3d0_init(void)
{
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625()) {
kgsl_3d0_pdata.idle_timeout = HZ/5;
+ kgsl_3d0_pdata.strtstp_sleepwake = false;
+ }
}
static void __init msm_register_device(struct platform_device *pdev, void *data)
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 5758dc4..078e931 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -55,6 +55,7 @@
extern struct platform_device msm8960_device_uart_gsbi2;
extern struct platform_device msm8960_device_uart_gsbi5;
+extern struct platform_device msm8960_device_uart_gsbi8;
extern struct platform_device msm8960_device_ssbi_pmic;
extern struct platform_device msm8960_device_qup_i2c_gsbi3;
extern struct platform_device msm8960_device_qup_i2c_gsbi4;
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index 087227c..b055f4e 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -61,16 +61,17 @@
size_t sd_size;
struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT];
struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT];
- spinlock_t lock;
+ struct mutex lock;
+ spinlock_t list_lock;
unsigned int irq;
struct clk *clk;
struct clk *pclk;
struct clk *ebiclk;
unsigned int clk_ctl;
- struct timer_list timer;
+ struct delayed_work work;
};
-static void msm_dmov_clock_timer(unsigned long);
+static void msm_dmov_clock_work(struct work_struct *);
static int msm_dmov_clk_toggle(int, int);
#ifdef CONFIG_ARCH_MSM8X60
@@ -163,15 +164,19 @@
{
.crci_conf = adm0_crci_conf,
.chan_conf = adm0_chan_conf,
- .lock = __SPIN_LOCK_UNLOCKED(dmov_lock),
+ .lock = __MUTEX_INITIALIZER(dmov_conf[0].lock),
+ .list_lock = __SPIN_LOCK_UNLOCKED(dmov_list_lock),
.clk_ctl = CLK_DIS,
- .timer = TIMER_INITIALIZER(msm_dmov_clock_timer, 0, 0),
+ .work = __DELAYED_WORK_INITIALIZER(dmov_conf[0].work,
+ msm_dmov_clock_work),
}, {
.crci_conf = adm1_crci_conf,
.chan_conf = adm1_chan_conf,
- .lock = __SPIN_LOCK_UNLOCKED(dmov_lock),
+ .lock = __MUTEX_INITIALIZER(dmov_conf[1].lock),
+ .list_lock = __SPIN_LOCK_UNLOCKED(dmov_list_lock),
.clk_ctl = CLK_DIS,
- .timer = TIMER_INITIALIZER(msm_dmov_clock_timer, 0, 1),
+ .work = __DELAYED_WORK_INITIALIZER(dmov_conf[1].work,
+ msm_dmov_clock_work),
}
};
#else
@@ -179,9 +184,11 @@
{
.crci_conf = NULL,
.chan_conf = NULL,
- .lock = __SPIN_LOCK_UNLOCKED(dmov_lock),
+ .lock = __MUTEX_INITIALIZER(dmov_conf[0].lock),
+ .list_lock = __SPIN_LOCK_UNLOCKED(dmov_list_lock),
.clk_ctl = CLK_DIS,
- .timer = TIMER_INITIALIZER(msm_dmov_clock_timer, 0, 0),
+ .work = __DELAYED_WORK_INITIALIZER(dmov_conf[0].work,
+ msm_dmov_clock_work),
}
};
#endif
@@ -257,16 +264,18 @@
return ret;
}
-static void msm_dmov_clock_timer(unsigned long adm)
+static void msm_dmov_clock_work(struct work_struct *work)
{
- unsigned long irq_flags;
- spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
- if (dmov_conf[adm].clk_ctl == CLK_TO_BE_DIS) {
- BUG_ON(dmov_conf[adm].channel_active);
+ struct msm_dmov_conf *conf =
+ container_of(to_delayed_work(work), struct msm_dmov_conf, work);
+ int adm = DMOV_IRQ_TO_ADM(conf->irq);
+ mutex_lock(&conf->lock);
+ if (conf->clk_ctl == CLK_TO_BE_DIS) {
+ BUG_ON(conf->channel_active);
msm_dmov_clk_toggle(adm, 0);
- dmov_conf[adm].clk_ctl = CLK_DIS;
+ conf->clk_ctl = CLK_DIS;
}
- spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
+ mutex_unlock(&conf->lock);
}
void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful)
@@ -278,48 +287,83 @@
}
EXPORT_SYMBOL(msm_dmov_stop_cmd);
-void msm_dmov_enqueue_cmd_ext(unsigned id, struct msm_dmov_cmd *cmd)
+/* Caller must hold the list lock */
+static void start_ready_cmd(unsigned ch, int adm)
{
- unsigned long irq_flags;
- unsigned int status;
+ struct msm_dmov_cmd *cmd;
+
+ if (list_empty(&dmov_conf[adm].ready_commands[ch]))
+ return;
+
+ cmd = list_entry(dmov_conf[adm].ready_commands[ch].next, typeof(*cmd),
+ list);
+ list_del(&cmd->list);
+ if (cmd->exec_func)
+ cmd->exec_func(cmd);
+ list_add_tail(&cmd->list, &dmov_conf[adm].active_commands[ch]);
+ if (!dmov_conf[adm].channel_active)
+ enable_irq(dmov_conf[adm].irq);
+ dmov_conf[adm].channel_active |= BIT(ch);
+ PRINT_IO("msm dmov enqueue command %x\n", cmd->cmdptr);
+ writel_relaxed(cmd->cmdptr, DMOV_REG(DMOV_CMD_PTR(ch), adm));
+}
+
+static void msm_dmov_enqueue_cmd_ext_work(struct work_struct *work)
+{
+ struct msm_dmov_cmd *cmd =
+ container_of(work, struct msm_dmov_cmd, work);
+ unsigned id = cmd->id;
+ unsigned status;
+ unsigned long flags;
int adm = DMOV_ID_TO_ADM(id);
int ch = DMOV_ID_TO_CHAN(id);
- spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
+ mutex_lock(&dmov_conf[adm].lock);
if (dmov_conf[adm].clk_ctl == CLK_DIS) {
status = msm_dmov_clk_toggle(adm, 1);
if (status != 0)
goto error;
} else if (dmov_conf[adm].clk_ctl == CLK_TO_BE_DIS)
- del_timer(&dmov_conf[adm].timer);
+ cancel_delayed_work_sync(&dmov_conf[adm].work);
dmov_conf[adm].clk_ctl = CLK_EN;
+ spin_lock_irqsave(&dmov_conf[adm].list_lock, flags);
+
status = readl_relaxed(DMOV_REG(DMOV_STATUS(ch), adm));
if (status & DMOV_STATUS_CMD_PTR_RDY) {
PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n",
id, status);
- if (cmd->exec_func)
- cmd->exec_func(cmd);
- list_add_tail(&cmd->list, &dmov_conf[adm].active_commands[ch]);
- if (!dmov_conf[adm].channel_active)
- enable_irq(dmov_conf[adm].irq);
- dmov_conf[adm].channel_active |= 1U << ch;
- PRINT_IO("Writing %x exactly to register", cmd->cmdptr);
- writel_relaxed(cmd->cmdptr, DMOV_REG(DMOV_CMD_PTR(ch), adm));
+ start_ready_cmd(ch, adm);
} else {
- if (!dmov_conf[adm].channel_active) {
- dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS;
- mod_timer(&dmov_conf[adm].timer, jiffies + HZ);
- }
- if (list_empty(&dmov_conf[adm].active_commands[ch]))
+ if (list_empty(&dmov_conf[adm].active_commands[ch]) &&
+ !list_empty(&dmov_conf[adm].ready_commands[ch]))
PRINT_ERROR("msm_dmov_enqueue_cmd_ext(%d), stalled, "
"status %x\n", id, status);
PRINT_IO("msm_dmov_enqueue_cmd(%d), enqueue command, status "
"%x\n", id, status);
- list_add_tail(&cmd->list, &dmov_conf[adm].ready_commands[ch]);
}
+ if (!dmov_conf[adm].channel_active) {
+ dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS;
+ schedule_delayed_work(&dmov_conf[adm].work, HZ);
+ }
+ spin_unlock_irqrestore(&dmov_conf[adm].list_lock, flags);
error:
- spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
+ mutex_unlock(&dmov_conf[adm].lock);
+}
+
+void msm_dmov_enqueue_cmd_ext(unsigned id, struct msm_dmov_cmd *cmd)
+{
+ int adm = DMOV_ID_TO_ADM(id);
+ int ch = DMOV_ID_TO_CHAN(id);
+ unsigned long flags;
+ cmd->id = id;
+ INIT_WORK(&cmd->work, msm_dmov_enqueue_cmd_ext_work);
+
+ spin_lock_irqsave(&dmov_conf[adm].list_lock, flags);
+ list_add_tail(&cmd->list, &dmov_conf[adm].ready_commands[ch]);
+ spin_unlock_irqrestore(&dmov_conf[adm].list_lock, flags);
+
+ schedule_work(&cmd->work);
}
EXPORT_SYMBOL(msm_dmov_enqueue_cmd_ext);
@@ -337,14 +381,14 @@
unsigned long irq_flags;
int ch = DMOV_ID_TO_CHAN(id);
int adm = DMOV_ID_TO_ADM(id);
- spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
+ spin_lock_irqsave(&dmov_conf[adm].list_lock, irq_flags);
/* XXX not checking if flush cmd sent already */
if (!list_empty(&dmov_conf[adm].active_commands[ch])) {
PRINT_IO("msm_dmov_flush(%d), send flush cmd\n", id);
writel_relaxed(DMOV_FLUSH_TYPE, DMOV_REG(DMOV_FLUSH0(ch), adm));
}
/* spin_unlock_irqrestore has the necessary barrier */
- spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
+ spin_unlock_irqrestore(&dmov_conf[adm].list_lock, irq_flags);
}
EXPORT_SYMBOL(msm_dmov_flush);
@@ -406,7 +450,7 @@
errdata->flush[5] = readl_relaxed(DMOV_REG(DMOV_FLUSH5(ch), adm));
}
-static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
+static irqreturn_t msm_dmov_isr(int irq, void *dev_id)
{
unsigned int int_status;
unsigned int mask;
@@ -419,11 +463,12 @@
struct msm_dmov_cmd *cmd;
int adm = DMOV_IRQ_TO_ADM(irq);
- spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
+ mutex_lock(&dmov_conf[adm].lock);
/* read and clear isr */
int_status = readl_relaxed(DMOV_REG(DMOV_ISR, adm));
PRINT_FLOW("msm_datamover_irq_handler: DMOV_ISR %x\n", int_status);
+ spin_lock_irqsave(&dmov_conf[adm].list_lock, irq_flags);
while (int_status) {
mask = int_status & -int_status;
ch = fls(mask) - 1;
@@ -491,50 +536,40 @@
ch_status = readl_relaxed(DMOV_REG(DMOV_STATUS(ch),
adm));
PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
- if ((ch_status & DMOV_STATUS_CMD_PTR_RDY) &&
- !list_empty(&dmov_conf[adm].ready_commands[ch])) {
- cmd = list_entry(dmov_conf[adm].
- ready_commands[ch].next, typeof(*cmd),
- list);
- list_del(&cmd->list);
- if (cmd->exec_func)
- cmd->exec_func(cmd);
- list_add_tail(&cmd->list,
- &dmov_conf[adm].active_commands[ch]);
+ if (ch_status & DMOV_STATUS_CMD_PTR_RDY) {
+ start_ready_cmd(ch, adm);
PRINT_FLOW("msm_datamover_irq_handler id %d, start command\n", id);
- writel_relaxed(cmd->cmdptr,
- DMOV_REG(DMOV_CMD_PTR(ch), adm));
}
} while (ch_status & DMOV_STATUS_RSLT_VALID);
if (list_empty(&dmov_conf[adm].active_commands[ch]) &&
- list_empty(&dmov_conf[adm].ready_commands[ch]))
+ list_empty(&dmov_conf[adm].ready_commands[ch]))
dmov_conf[adm].channel_active &= ~(1U << ch);
PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
}
+ spin_unlock_irqrestore(&dmov_conf[adm].list_lock, irq_flags);
if (!dmov_conf[adm].channel_active && valid) {
disable_irq_nosync(dmov_conf[adm].irq);
dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS;
- mod_timer(&dmov_conf[adm].timer, jiffies + HZ);
+ schedule_delayed_work(&dmov_conf[adm].work, HZ);
}
- spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
+ mutex_unlock(&dmov_conf[adm].lock);
return valid ? IRQ_HANDLED : IRQ_NONE;
}
static int msm_dmov_suspend_late(struct device *dev)
{
- unsigned long irq_flags;
struct platform_device *pdev = to_platform_device(dev);
int adm = (pdev->id >= 0) ? pdev->id : 0;
- spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
+ mutex_lock(&dmov_conf[adm].lock);
if (dmov_conf[adm].clk_ctl == CLK_TO_BE_DIS) {
BUG_ON(dmov_conf[adm].channel_active);
- del_timer(&dmov_conf[adm].timer);
+ cancel_delayed_work_sync(&dmov_conf[adm].work);
msm_dmov_clk_toggle(adm, 0);
dmov_conf[adm].clk_ctl = CLK_DIS;
}
- spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
+ mutex_unlock(&dmov_conf[adm].lock);
return 0;
}
@@ -649,8 +684,8 @@
if (!dmov_conf[adm].base)
return -ENOMEM;
- ret = request_irq(dmov_conf[adm].irq, msm_datamover_irq_handler,
- 0, "msmdatamover", NULL);
+ ret = request_threaded_irq(dmov_conf[adm].irq, NULL, msm_dmov_isr,
+ IRQF_ONESHOT, "msmdatamover", NULL);
if (ret) {
PRINT_ERROR("Requesting ADM%d irq %d failed\n", adm,
dmov_conf[adm].irq);
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index d170f5f..6e58ebe 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-msm/dma.h
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -35,6 +35,8 @@
unsigned int result,
struct msm_dmov_errdata *err);
void (*exec_func)(struct msm_dmov_cmd *cmd);
+ struct work_struct work;
+ unsigned id; /* For internal use */
void *user; /* Pointer for caller's reference */
};
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
index 57f2d37..af82fd9 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
@@ -57,8 +57,9 @@
#define FL_TYPE_TABLE (1 << 0)
#define FL_TYPE_SECT (2 << 0)
#define FL_SUPERSECTION (1 << 18)
-#define FL_AP_WRITE (1 << 10)
-#define FL_AP_READ (1 << 11)
+#define FL_AP0 (1 << 10)
+#define FL_AP1 (1 << 11)
+#define FL_AP2 (1 << 15)
#define FL_SHARED (1 << 16)
#define FL_BUFFERABLE (1 << 2)
#define FL_CACHEABLE (1 << 3)
@@ -73,6 +74,7 @@
#define SL_TYPE_SMALL (2 << 0)
#define SL_AP0 (1 << 4)
#define SL_AP1 (2 << 4)
+#define SL_AP2 (1 << 9)
#define SL_SHARED (1 << 10)
#define SL_BUFFERABLE (1 << 2)
#define SL_CACHEABLE (1 << 3)
diff --git a/arch/arm/mach-msm/include/mach/msm_rtb.h b/arch/arm/mach-msm/include/mach/msm_rtb.h
index 5eea63f..74ddfbd 100644
--- a/arch/arm/mach-msm/include/mach/msm_rtb.h
+++ b/arch/arm/mach-msm/include/mach/msm_rtb.h
@@ -15,7 +15,7 @@
/*
* These numbers are used from the kernel command line and sysfs
- * to control filtering. Remove items from here with extreme caution
+ * to control filtering. Remove items from here with extreme caution.
*/
enum logk_event_type {
LOGK_NONE = 0,
@@ -24,9 +24,11 @@
LOGK_LOGBUF = 3,
LOGK_HOTPLUG = 4,
LOGK_CTXID = 5,
- LOGK_OTHER = 31,
+ LOGK_TIMESTAMP = 6,
};
+#define LOGTYPE_NOPC 0x80
+
struct msm_rtb_platform_data {
unsigned int size;
};
diff --git a/arch/arm/mach-msm/include/mach/msm_smsm.h b/arch/arm/mach-msm/include/mach/msm_smsm.h
index 772c9f6..5c3307e 100644
--- a/arch/arm/mach-msm/include/mach/msm_smsm.h
+++ b/arch/arm/mach-msm/include/mach/msm_smsm.h
@@ -100,6 +100,21 @@
void *smem_get_entry(unsigned id, unsigned *size);
int smsm_change_state(uint32_t smsm_entry,
uint32_t clear_mask, uint32_t set_mask);
+
+/*
+ * Changes the global interrupt mask. The set and clear masks are re-applied
+ * every time the global interrupt mask is updated for callback registration
+ * and de-registration.
+ *
+ * The clear mask is applied first, so if a bit is set to 1 in both the clear
+ * mask and the set mask, the result will be that the interrupt is set.
+ *
+ * @smsm_entry SMSM entry to change
+ * @clear_mask 1 = clear bit, 0 = no-op
+ * @set_mask 1 = set bit, 0 = no-op
+ *
+ * @returns 0 for success, < 0 for error
+ */
int smsm_change_intr_mask(uint32_t smsm_entry,
uint32_t clear_mask, uint32_t set_mask);
int smsm_get_intr_mask(uint32_t smsm_entry, uint32_t *intr_mask);
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
index dd5ddd8..bd303b2 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
@@ -135,6 +135,8 @@
uint16_t event_types;
/* Input event source */
enum us_input_event_src_type event_src;
+ /* Bitmap of types of events from devs, conflicting with USF */
+ uint16_t conflicting_event_types;
};
struct us_tx_info_type {
@@ -208,6 +210,8 @@
/* Time (sec) to wait for data or special values: */
/* USF_NO_WAIT_TIMEOUT, USF_INFINITIVE_TIMEOUT, USF_DEFAULT_TIMEOUT */
uint32_t timeout;
+/* Events (from conflicting devs) to be disabled/enabled */
+ uint16_t event_filters;
/* Input transparent data: */
/* Parameters size */
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 99bf212..aee562e 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -44,6 +44,8 @@
#define machine_is_copper_sim() 0
#endif
+#define PLATFORM_SUBTYPE_SGLTE 6
+
enum msm_cpu {
MSM_CPU_UNKNOWN = 0,
MSM_CPU_7X01,
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index d495c1b..19e1684 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -421,6 +421,16 @@
unsigned int pgprot;
int tex;
+ if (!(prot & (IOMMU_READ | IOMMU_WRITE))) {
+ prot |= IOMMU_READ | IOMMU_WRITE;
+ WARN_ONCE(1, "No attributes in iommu mapping; assuming RW\n");
+ }
+
+ if ((prot & IOMMU_WRITE) && !(prot & IOMMU_READ)) {
+ prot |= IOMMU_READ;
+ WARN_ONCE(1, "Write-only iommu mappings unsupported; falling back to RW\n");
+ }
+
if (prot & IOMMU_CACHE)
tex = (pgprot_kernel >> 2) & 0x07;
else
@@ -434,11 +444,15 @@
pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
pgprot |= tex & 0x04 ? FL_TEX0 : 0;
+ pgprot |= FL_AP0 | FL_AP1;
+ pgprot |= prot & IOMMU_WRITE ? 0 : FL_AP2;
} else {
pgprot = SL_SHARED;
pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
pgprot |= tex & 0x04 ? SL_TEX0 : 0;
+ pgprot |= SL_AP0 | SL_AP1;
+ pgprot |= prot & IOMMU_WRITE ? 0 : SL_AP2;
}
return pgprot;
@@ -501,9 +515,8 @@
}
for (i = 0; i < 16; i++)
- *(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
- FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
- FL_SHARED | FL_NG | pgprot;
+ *(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION
+ | FL_TYPE_SECT | FL_SHARED | FL_NG | pgprot;
if (!priv->redirect)
clean_pte(fl_pte, fl_pte + 16);
}
@@ -514,8 +527,8 @@
goto fail;
}
- *fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | FL_NG |
- FL_TYPE_SECT | FL_SHARED | pgprot;
+ *fl_pte = (pa & 0xFFF00000) | FL_NG | FL_TYPE_SECT | FL_SHARED
+ | pgprot;
if (!priv->redirect)
clean_pte(fl_pte, fl_pte + 1);
}
@@ -558,8 +571,8 @@
goto fail;
}
- *sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG |
- SL_SHARED | SL_TYPE_SMALL | pgprot;
+ *sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_NG | SL_SHARED
+ | SL_TYPE_SMALL | pgprot;
if (!priv->redirect)
clean_pte(sl_pte, sl_pte + 1);
}
@@ -574,8 +587,8 @@
}
for (i = 0; i < 16; i++)
- *(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
- SL_NG | SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
+ *(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_NG
+ | SL_SHARED | SL_TYPE_LARGE | pgprot;
if (!priv->redirect)
clean_pte(sl_pte, sl_pte + 16);
@@ -776,8 +789,7 @@
while (offset < len && sl_offset < NUM_SL_PTE) {
pa = chunk_pa + chunk_offset;
sl_table[sl_offset] = (pa & SL_BASE_MASK_SMALL) |
- pgprot | SL_AP0 | SL_AP1 | SL_NG |
- SL_SHARED | SL_TYPE_SMALL;
+ pgprot | SL_NG | SL_SHARED | SL_TYPE_SMALL;
sl_offset++;
offset += SZ_4K;
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index 3f56d1a..403c13d 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -20,6 +20,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <asm-generic/sizes.h>
#include <mach/memory.h>
@@ -76,7 +77,7 @@
int msm_rtb_event_should_log(enum logk_event_type log_type)
{
return msm_rtb.initialized && msm_rtb.enabled &&
- ((1 << log_type) & msm_rtb.filter);
+ ((1 << (log_type & ~LOGTYPE_NOPC)) & msm_rtb.filter);
}
EXPORT_SYMBOL(msm_rtb_event_should_log);
@@ -109,10 +110,39 @@
start->data = data;
}
+static void uncached_logk_pc_idx(enum logk_event_type log_type, void *caller,
+ void *data, int idx)
+{
+ struct msm_rtb_layout *start;
+
+ start = &msm_rtb.rtb[idx & (msm_rtb.nentries - 1)];
+
+ msm_rtb_emit_sentinel(start);
+ msm_rtb_write_type(log_type, start);
+ msm_rtb_write_caller(caller, start);
+ msm_rtb_write_idx(idx, start);
+ msm_rtb_write_data(data, start);
+ mb();
+
+ return;
+}
+
+static void uncached_logk_timestamp(int idx)
+{
+ unsigned long long timestamp;
+ void *timestamp_upper, *timestamp_lower;
+ timestamp = sched_clock();
+ timestamp_lower = (void *)lower_32_bits(timestamp);
+ timestamp_upper = (void *)upper_32_bits(timestamp);
+
+ uncached_logk_pc_idx(LOGK_TIMESTAMP|LOGTYPE_NOPC, timestamp_lower,
+ timestamp_upper, idx);
+}
+
#if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
static int msm_rtb_get_idx(void)
{
- int cpu, i;
+ int cpu, i, offset;
atomic_t *index;
/*
@@ -126,16 +156,34 @@
i = atomic_add_return(msm_rtb.step_size, index);
i -= msm_rtb.step_size;
+ /* Check if index has wrapped around */
+ offset = (i & (msm_rtb.nentries - 1)) -
+ ((i - msm_rtb.step_size) & (msm_rtb.nentries - 1));
+ if (offset < 0) {
+ uncached_logk_timestamp(i);
+ i = atomic_add_return(msm_rtb.step_size, index);
+ i -= msm_rtb.step_size;
+ }
+
return i;
}
#else
static int msm_rtb_get_idx(void)
{
- int i;
+ int i, offset;
i = atomic_inc_return(&msm_rtb_idx);
i--;
+ /* Check if index has wrapped around */
+ offset = (i & (msm_rtb.nentries - 1)) -
+ ((i - 1) & (msm_rtb.nentries - 1));
+ if (offset < 0) {
+ uncached_logk_timestamp(i);
+ i = atomic_inc_return(&msm_rtb_idx);
+ i--;
+ }
+
return i;
}
#endif
@@ -144,21 +192,13 @@
void *data)
{
int i;
- struct msm_rtb_layout *start;
if (!msm_rtb_event_should_log(log_type))
return 0;
i = msm_rtb_get_idx();
- start = &msm_rtb.rtb[i & (msm_rtb.nentries - 1)];
-
- msm_rtb_emit_sentinel(start);
- msm_rtb_write_type(log_type, start);
- msm_rtb_write_caller(caller, start);
- msm_rtb_write_idx(i, start);
- msm_rtb_write_data(data, start);
- mb();
+ uncached_logk_pc_idx(log_type, caller, data, i);
return 1;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index b5f071f..2403c02 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -371,14 +371,11 @@
mutex_lock(&q6.lock);
if (q6.state == APR_Q6_NOIMG) {
q6.pil = pil_get("q6");
- if (!q6.pil) {
- pr_err("APR: Unable to load q6 image\n");
+ if (IS_ERR(q6.pil)) {
+ rc = PTR_ERR(q6.pil);
+ pr_err("APR: Unable to load q6 image, error:%d\n", rc);
mutex_unlock(&q6.lock);
- /* Return failure if not intended for simulator */
- if (!machine_is_apq8064_sim()) {
- pr_debug("APR: Not apq8064 sim\n");
- return svc;
- }
+ return svc;
}
q6.state = APR_Q6_LOADED;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/Makefile b/arch/arm/mach-msm/qdsp6v2/ultrasound/Makefile
index 540119b..0be1303 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/Makefile
@@ -1,2 +1,2 @@
-obj-y += q6usm.o usf.o
+obj-y += q6usm.o usf.o usfcdev.o
EXTRA_CFLAGS += -I$(src)/..
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
index 64f70c5..b4a0a7f 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
@@ -24,9 +24,10 @@
#include <sound/apr_audio.h>
#include <mach/qdsp6v2/usf.h>
#include "q6usm.h"
+#include "usfcdev.h"
/* The driver version*/
-#define DRV_VERSION "1.2"
+#define DRV_VERSION "1.3"
/* Standard timeout in the asynchronous ops */
#define USF_TIMEOUT_JIFFIES (3*HZ) /* 3 sec */
@@ -111,6 +112,10 @@
struct input_dev *input_if;
/* The event source */
int event_src;
+ /* Bitmap of types of events, conflicting to USF's ones */
+ uint16_t conflicting_event_types;
+ /* Bitmap of types of events from devs, conflicting with USF */
+ uint16_t conflicting_event_filters;
};
/* The MAX number of the supported devices */
@@ -126,6 +131,9 @@
/* The opened devices container */
static int s_opened_devs[MAX_DEVS_NUMBER];
+#define USF_NAME_PREFIX "USF_"
+#define USF_NAME_PREFIX_SIZE 4
+
static void usf_rx_cb(uint32_t opcode, uint32_t token,
uint32_t *payload, void *priv)
{
@@ -316,11 +324,70 @@
return rc;
}
+static bool usf_match(uint16_t event_type_ind, struct input_dev *dev)
+{
+ bool rc = false;
+
+ rc = (event_type_ind < MAX_EVENT_TYPE_NUM) &&
+ ((dev->name == NULL) ||
+ strncmp(dev->name, USF_NAME_PREFIX, USF_NAME_PREFIX_SIZE));
+ pr_debug("%s: name=[%s]; rc=%d\n",
+ __func__, dev->name, rc);
+
+ return rc;
+}
+
+static bool usf_register_conflicting_events(uint16_t event_types)
+{
+ bool rc = true;
+ uint16_t ind = 0;
+ uint16_t mask = 1;
+
+ for (ind = 0; ind < MAX_EVENT_TYPE_NUM; ++ind) {
+ if (event_types & mask) {
+ rc = usfcdev_register(ind, usf_match);
+ if (!rc)
+ break;
+ }
+ mask = mask << 1;
+ }
+
+ return rc;
+}
+
+static void usf_unregister_conflicting_events(uint16_t event_types)
+{
+ uint16_t ind = 0;
+ uint16_t mask = 1;
+
+ for (ind = 0; ind < MAX_EVENT_TYPE_NUM; ++ind) {
+ if (event_types & mask)
+ usfcdev_unregister(ind);
+ mask = mask << 1;
+ }
+}
+
+static void usf_set_event_filters(struct usf_type *usf, uint16_t event_filters)
+{
+ uint16_t ind = 0;
+ uint16_t mask = 1;
+
+ if (usf->conflicting_event_filters != event_filters) {
+ for (ind = 0; ind < MAX_EVENT_TYPE_NUM; ++ind) {
+ if (usf->conflicting_event_types & mask)
+ usfcdev_set_filter(ind, event_filters&mask);
+ mask = mask << 1;
+ }
+ usf->conflicting_event_filters = event_filters;
+ }
+}
+
static int register_input_device(struct usf_type *usf_info,
struct us_input_info_type *input_info)
{
int rc = 0;
struct input_dev *input_dev = NULL;
+ bool ret = true;
if ((usf_info == NULL) ||
(input_info == NULL) ||
@@ -417,6 +484,11 @@
usf_info->event_types = input_info->event_types;
pr_debug("%s: input device[%s] was registered\n",
__func__, input_dev->name);
+ ret = usf_register_conflicting_events(
+ input_info->conflicting_event_types);
+ if (ret)
+ usf_info->conflicting_event_types =
+ input_info->conflicting_event_types;
}
return rc;
@@ -826,6 +898,7 @@
}
if (!usf_xx->user_upd_info_na) {
+ usf_set_event_filters(usf, upd_tx_info.event_filters);
handle_input_event(usf,
upd_tx_info.event_counter,
upd_tx_info.event);
@@ -963,16 +1036,23 @@
return rc;
} /* usf_set_rx_update */
+static void usf_release_input(struct usf_type *usf)
+{
+ if (usf->input_if != NULL) {
+ usf_unregister_conflicting_events(
+ usf->conflicting_event_types);
+ usf->conflicting_event_types = 0;
+ input_unregister_device(usf->input_if);
+ usf->input_if = NULL;
+ pr_debug("%s input_unregister_device\n", __func__);
+ }
+} /* usf_release_input */
+
static int usf_stop_tx(struct usf_type *usf)
{
struct usf_xx_type *usf_xx = &usf->usf_tx;
- if (usf->input_if != NULL) {
- input_unregister_device(usf->input_if);
- usf->input_if = NULL;
- pr_debug("%s input_unregister_device",
- __func__);
- }
+ usf_release_input(usf);
usf_disable(usf_xx);
return 0;
@@ -1225,18 +1305,13 @@
return 0;
}
-
static int usf_release(struct inode *inode, struct file *file)
{
struct usf_type *usf = file->private_data;
pr_debug("%s: release entry\n", __func__);
- if (usf->input_if != NULL) {
- input_unregister_device(usf->input_if);
- usf->input_if = NULL;
- pr_debug("%s input_unregister_device\n", __func__);
- }
+ usf_release_input(usf);
usf_disable(&usf->usf_tx);
usf_disable(&usf->usf_rx);
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usfcdev.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usfcdev.c
new file mode 100644
index 0000000..b99a9b0
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usfcdev.c
@@ -0,0 +1,236 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include "usfcdev.h"
+
+struct usfcdev_event {
+ bool (*match_cb)(uint16_t, struct input_dev *dev);
+ bool registered_event;
+ bool filter;
+};
+static struct usfcdev_event s_usfcdev_events[MAX_EVENT_TYPE_NUM];
+
+static bool usfcdev_filter(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value);
+static bool usfcdev_match(struct input_handler *handler,
+ struct input_dev *dev);
+static int usfcdev_connect(struct input_handler *handler,
+ struct input_dev *dev,
+ const struct input_device_id *id);
+static void usfcdev_disconnect(struct input_handle *handle);
+
+static const struct input_device_id usfc_tsc_ids[] = {
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_KEYBIT |
+ INPUT_DEVICE_ID_MATCH_ABSBIT,
+ .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
+ .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
+ .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
+ },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, usfc_tsc_ids);
+
+static struct input_handler s_usfc_handlers[MAX_EVENT_TYPE_NUM] = {
+ { /* TSC handler */
+ .filter = usfcdev_filter,
+ .match = usfcdev_match,
+ .connect = usfcdev_connect,
+ .disconnect = usfcdev_disconnect,
+ /* .minor can be used as index in the container, */
+ /* because .fops isn't supported */
+ .minor = TSC_EVENT_TYPE_IND,
+ .name = "usfc_tsc_handler",
+ .id_table = usfc_tsc_ids,
+ },
+};
+
+/* For each event type, one conflicting device (and handle) is supported */
+static struct input_handle s_usfc_handles[MAX_EVENT_TYPE_NUM] = {
+ { /* TSC handle */
+ .handler = &s_usfc_handlers[TSC_EVENT_TYPE_IND],
+ .name = "usfc_tsc_handle",
+ },
+};
+
+static bool usfcdev_match(struct input_handler *handler, struct input_dev *dev)
+{
+ bool rc = false;
+ int ind = handler->minor;
+
+ pr_debug("%s: name=[%s]; ind=%d\n", __func__, dev->name, ind);
+ if (s_usfcdev_events[ind].registered_event &&
+ s_usfcdev_events[ind].match_cb) {
+ rc = (*s_usfcdev_events[ind].match_cb)((uint16_t)ind, dev);
+ pr_debug("%s: [%s]; rc=%d\n", __func__, dev->name, rc);
+ }
+
+ return rc;
+}
+
+static int usfcdev_connect(struct input_handler *handler, struct input_dev *dev,
+ const struct input_device_id *id)
+{
+ int ret = 0;
+ uint16_t ind = handler->minor;
+
+ s_usfc_handles[ind].dev = dev;
+ ret = input_register_handle(&s_usfc_handles[ind]);
+ if (ret) {
+ pr_err("%s: input_register_handle[%d] failed: ret=%d\n",
+ __func__,
+ ind,
+ ret);
+ } else {
+ ret = input_open_device(&s_usfc_handles[ind]);
+ if (ret) {
+ pr_err("%s: input_open_device[%d] failed: ret=%d\n",
+ __func__,
+ ind,
+ ret);
+ input_unregister_handle(&s_usfc_handles[ind]);
+ } else
+ pr_debug("%s: device[%d] is opened\n",
+ __func__,
+ ind);
+ }
+
+ return ret;
+}
+
+static void usfcdev_disconnect(struct input_handle *handle)
+{
+ input_unregister_handle(handle);
+ pr_debug("%s: handle[%d] is disconnect\n",
+ __func__,
+ handle->handler->minor);
+}
+
+static bool usfcdev_filter(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
+{
+ uint16_t ind = (uint16_t)handle->handler->minor;
+
+ pr_debug("%s: event_type=%d; filter=%d\n",
+ __func__,
+ ind,
+ s_usfcdev_events[ind].filter);
+
+ return s_usfcdev_events[ind].filter;
+}
+
+bool usfcdev_register(
+ uint16_t event_type_ind,
+ bool (*match_cb)(uint16_t, struct input_dev *dev))
+{
+ int ret = 0;
+ bool rc = false;
+
+ if ((event_type_ind >= MAX_EVENT_TYPE_NUM) || !match_cb) {
+ pr_err("%s: wrong input: event_type_ind=%d; match_cb=0x%p\n",
+ __func__,
+ event_type_ind,
+ match_cb);
+ return false;
+ }
+
+ if (s_usfcdev_events[event_type_ind].registered_event) {
+ pr_info("%s: handler[%d] was already registered\n",
+ __func__,
+ event_type_ind);
+ return true;
+ }
+
+ s_usfcdev_events[event_type_ind].registered_event = true;
+ s_usfcdev_events[event_type_ind].match_cb = match_cb;
+ s_usfcdev_events[event_type_ind].filter = false;
+ ret = input_register_handler(&s_usfc_handlers[event_type_ind]);
+ if (!ret) {
+ rc = true;
+ pr_debug("%s: handler[%d] was registered\n",
+ __func__,
+ event_type_ind);
+ } else {
+ s_usfcdev_events[event_type_ind].registered_event = false;
+ s_usfcdev_events[event_type_ind].match_cb = NULL;
+ pr_err("%s: handler[%d] registration failed: ret=%d\n",
+ __func__,
+ event_type_ind,
+ ret);
+ }
+
+ return rc;
+}
+
+void usfcdev_unregister(uint16_t event_type_ind)
+{
+ if (event_type_ind >= MAX_EVENT_TYPE_NUM) {
+ pr_err("%s: wrong input: event_type_ind=%d\n",
+ __func__,
+ event_type_ind);
+ return;
+ }
+ if (s_usfcdev_events[event_type_ind].registered_event) {
+ input_unregister_handler(&s_usfc_handlers[event_type_ind]);
+ pr_debug("%s: handler[%d] was unregistered\n",
+ __func__,
+ event_type_ind);
+ s_usfcdev_events[event_type_ind].registered_event = false;
+ s_usfcdev_events[event_type_ind].match_cb = NULL;
+ s_usfcdev_events[event_type_ind].filter = false;
+ }
+}
+
+bool usfcdev_set_filter(uint16_t event_type_ind, bool filter)
+{
+ bool rc = true;
+
+ if (event_type_ind >= MAX_EVENT_TYPE_NUM) {
+ pr_err("%s: wrong input: event_type_ind=%d\n",
+ __func__,
+ event_type_ind);
+ return false;
+ }
+
+ if (s_usfcdev_events[event_type_ind].registered_event) {
+ s_usfcdev_events[event_type_ind].filter = filter;
+ pr_debug("%s: event_type[%d]; filter=%d\n",
+ __func__,
+ event_type_ind,
+ filter
+ );
+ } else {
+ pr_err("%s: event_type[%d] isn't registered\n",
+ __func__,
+ event_type_ind);
+ rc = false;
+ }
+
+ return rc;
+}
+
+static int __init usfcdev_init(void)
+{
+ return 0;
+}
+
+device_initcall(usfcdev_init);
+
+MODULE_DESCRIPTION("Handle of events from devices, conflicting with USF");
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usfcdev.h b/arch/arm/mach-msm/qdsp6v2/ultrasound/usfcdev.h
new file mode 100644
index 0000000..042b293
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usfcdev.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __USFCDEV_H__
+#define __USFCDEV_H__
+
+#include <linux/input.h>
+
+/* TSC event type index in the containers of the handlers & handles */
+#define TSC_EVENT_TYPE_IND 0
+/* Number of supported event types to be filtered */
+#define MAX_EVENT_TYPE_NUM 1
+
+bool usfcdev_register(
+ uint16_t event_type_ind,
+ bool (*match_cb)(uint16_t, struct input_dev *dev));
+void usfcdev_unregister(uint16_t event_type_ind);
+bool usfcdev_set_filter(uint16_t event_type_ind, bool filter);
+#endif /* __USFCDEV_H__ */
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index d00dd1a..839f932 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -71,6 +71,10 @@
uint32_t SMSM_NUM_ENTRIES = 8;
uint32_t SMSM_NUM_HOSTS = 3;
+/* Legacy SMSM interrupt notifications */
+#define LEGACY_MODEM_SMSM_MASK (SMSM_RESET | SMSM_INIT | SMSM_SMDINIT \
+ | SMSM_RUN | SMSM_SYSTEM_DOWNLOAD)
+
enum {
MSM_SMD_DEBUG = 1U << 0,
MSM_SMSM_DEBUG = 1U << 1,
@@ -108,6 +112,8 @@
struct smsm_state_info {
struct list_head callbacks;
uint32_t last_value;
+ uint32_t intr_mask_set;
+ uint32_t intr_mask_clear;
};
struct interrupt_config_item {
@@ -2246,6 +2252,8 @@
for (n = 0; n < SMSM_NUM_ENTRIES; n++) {
state_info = &smsm_states[n];
state_info->last_value = __raw_readl(SMSM_STATE_ADDR(n));
+ state_info->intr_mask_set = 0x0;
+ state_info->intr_mask_clear = 0x0;
INIT_LIST_HEAD(&state_info->callbacks);
}
mutex_unlock(&smsm_lock);
@@ -2302,10 +2310,16 @@
SMSM_NUM_HOSTS *
sizeof(uint32_t));
- if (smsm_info.intr_mask)
+ if (smsm_info.intr_mask) {
for (i = 0; i < SMSM_NUM_ENTRIES; i++)
- __raw_writel(0xffffffff,
- SMSM_INTR_MASK_ADDR(i, SMSM_APPS));
+ __raw_writel(0x0,
+ SMSM_INTR_MASK_ADDR(i, SMSM_APPS));
+
+ /* Configure legacy modem bits */
+ __raw_writel(LEGACY_MODEM_SMSM_MASK,
+ SMSM_INTR_MASK_ADDR(SMSM_MODEM_STATE,
+ SMSM_APPS));
+ }
}
if (!smsm_info.intr_mux)
@@ -2539,6 +2553,20 @@
return smsm_irq_handler(irq, data);
}
+/*
+ * Changes the global interrupt mask. The set and clear masks are re-applied
+ * every time the global interrupt mask is updated for callback registration
+ * and de-registration.
+ *
+ * The clear mask is applied first, so if a bit is set to 1 in both the clear
+ * mask and the set mask, the result will be that the interrupt is set.
+ *
+ * @smsm_entry SMSM entry to change
+ * @clear_mask 1 = clear bit, 0 = no-op
+ * @set_mask 1 = set bit, 0 = no-op
+ *
+ * @returns 0 for success, < 0 for error
+ */
int smsm_change_intr_mask(uint32_t smsm_entry,
uint32_t clear_mask, uint32_t set_mask)
{
@@ -2557,6 +2585,8 @@
}
spin_lock_irqsave(&smem_lock, flags);
+ smsm_states[smsm_entry].intr_mask_clear = clear_mask;
+ smsm_states[smsm_entry].intr_mask_set = set_mask;
old_mask = __raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_APPS));
new_mask = (old_mask & ~clear_mask) | set_mask;
@@ -2733,8 +2763,10 @@
int smsm_state_cb_register(uint32_t smsm_entry, uint32_t mask,
void (*notify)(void *, uint32_t, uint32_t), void *data)
{
+ struct smsm_state_info *state;
struct smsm_state_cb_info *cb_info;
struct smsm_state_cb_info *cb_found = 0;
+ uint32_t new_mask = 0;
int ret = 0;
if (smsm_entry >= SMSM_NUM_ENTRIES)
@@ -2748,15 +2780,16 @@
goto cleanup;
}
+ state = &smsm_states[smsm_entry];
list_for_each_entry(cb_info,
- &smsm_states[smsm_entry].callbacks, cb_list) {
- if ((cb_info->notify == notify) &&
+ &state->callbacks, cb_list) {
+ if (!ret && (cb_info->notify == notify) &&
(cb_info->data == data)) {
cb_info->mask |= mask;
cb_found = cb_info;
ret = 1;
- break;
}
+ new_mask |= cb_info->mask;
}
if (!cb_found) {
@@ -2772,7 +2805,24 @@
cb_info->data = data;
INIT_LIST_HEAD(&cb_info->cb_list);
list_add_tail(&cb_info->cb_list,
- &smsm_states[smsm_entry].callbacks);
+ &state->callbacks);
+ new_mask |= mask;
+ }
+
+ /* update interrupt notification mask */
+ if (smsm_entry == SMSM_MODEM_STATE)
+ new_mask |= LEGACY_MODEM_SMSM_MASK;
+
+ if (smsm_info.intr_mask) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&smem_lock, flags);
+ new_mask = (new_mask & ~state->intr_mask_clear)
+ | state->intr_mask_set;
+ __raw_writel(new_mask,
+ SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_APPS));
+ wmb();
+ spin_unlock_irqrestore(&smem_lock, flags);
}
cleanup:
@@ -2800,6 +2850,9 @@
void (*notify)(void *, uint32_t, uint32_t), void *data)
{
struct smsm_state_cb_info *cb_info;
+ struct smsm_state_cb_info *cb_tmp;
+ struct smsm_state_info *state;
+ uint32_t new_mask = 0;
int ret = 0;
if (smsm_entry >= SMSM_NUM_ENTRIES)
@@ -2813,9 +2866,10 @@
return -ENODEV;
}
- list_for_each_entry(cb_info,
- &smsm_states[smsm_entry].callbacks, cb_list) {
- if ((cb_info->notify == notify) &&
+ state = &smsm_states[smsm_entry];
+ list_for_each_entry_safe(cb_info, cb_tmp,
+ &state->callbacks, cb_list) {
+ if (!ret && (cb_info->notify == notify) &&
(cb_info->data == data)) {
cb_info->mask &= ~mask;
ret = 1;
@@ -2824,9 +2878,26 @@
list_del(&cb_info->cb_list);
kfree(cb_info);
ret = 2;
+ continue;
}
- break;
}
+ new_mask |= cb_info->mask;
+ }
+
+ /* update interrupt notification mask */
+ if (smsm_entry == SMSM_MODEM_STATE)
+ new_mask |= LEGACY_MODEM_SMSM_MASK;
+
+ if (smsm_info.intr_mask) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&smem_lock, flags);
+ new_mask = (new_mask & ~state->intr_mask_clear)
+ | state->intr_mask_set;
+ __raw_writel(new_mask,
+ SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_APPS));
+ wmb();
+ spin_unlock_irqrestore(&smem_lock, flags);
}
mutex_unlock(&smsm_lock);
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 28850d0..68e0f41 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -83,6 +83,8 @@
{2, "APPS_RIVA_BT_ACL", NULL, SMD_APPS_WCNSS},
{3, "APPS_RIVA_BT_CMD", NULL, SMD_APPS_WCNSS},
{4, "MBALBRIDGE", NULL, SMD_APPS_MODEM},
+ {5, "APPS_RIVA_ANT_CMD", NULL, SMD_APPS_WCNSS},
+ {6, "APPS_RIVA_ANT_DATA", NULL, SMD_APPS_WCNSS},
{7, "DATA1", NULL, SMD_APPS_MODEM},
{11, "DATA11", NULL, SMD_APPS_MODEM},
{21, "DATA21", NULL, SMD_APPS_MODEM},
diff --git a/drivers/base/base.h b/drivers/base/base.h
index a34dca0..9641309 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -105,6 +105,7 @@
extern void driver_detach(struct device_driver *drv);
extern int driver_probe_device(struct device_driver *drv, struct device *dev);
+extern void driver_deferred_probe_del(struct device *dev);
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 78445f4..14cdf13 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -589,6 +589,7 @@
{
dev->kobj.kset = devices_kset;
kobject_init(&dev->kobj, &device_ktype);
+ INIT_LIST_HEAD(&dev->deferred_probe);
INIT_LIST_HEAD(&dev->dma_pools);
mutex_init(&dev->mutex);
lockdep_set_novalidate_class(&dev->mutex);
@@ -1120,6 +1121,7 @@
device_remove_file(dev, &uevent_attr);
device_remove_attrs(dev);
bus_remove_device(dev);
+ driver_deferred_probe_del(dev);
/*
* Some platform devices are driven without driver attached
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 6658da7..455b502 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -28,6 +28,133 @@
#include "base.h"
#include "power/power.h"
+/*
+ * Deferred Probe infrastructure.
+ *
+ * Sometimes driver probe order matters, but the kernel doesn't always have
+ * dependency information which means some drivers will get probed before a
+ * resource it depends on is available. For example, an SDHCI driver may
+ * first need a GPIO line from an i2c GPIO controller before it can be
+ * initialized. If a required resource is not available yet, a driver can
+ * request probing to be deferred by returning -EPROBE_DEFER from its probe hook
+ *
+ * Deferred probe maintains two lists of devices, a pending list and an active
+ * list. A driver returning -EPROBE_DEFER causes the device to be added to the
+ * pending list. A successful driver probe will trigger moving all devices
+ * from the pending to the active list so that the workqueue will eventually
+ * retry them.
+ *
+ * The deferred_probe_mutex must be held any time the deferred_probe_*_list
+ * of the (struct device*)->deferred_probe pointers are manipulated
+ */
+static DEFINE_MUTEX(deferred_probe_mutex);
+static LIST_HEAD(deferred_probe_pending_list);
+static LIST_HEAD(deferred_probe_active_list);
+static struct workqueue_struct *deferred_wq;
+
+/**
+ * deferred_probe_work_func() - Retry probing devices in the active list.
+ */
+static void deferred_probe_work_func(struct work_struct *work)
+{
+ struct device *dev;
+ /*
+ * This block processes every device in the deferred 'active' list.
+ * Each device is removed from the active list and passed to
+ * bus_probe_device() to re-attempt the probe. The loop continues
+ * until every device in the active list is removed and retried.
+ *
+ * Note: Once the device is removed from the list and the mutex is
+ * released, it is possible for the device get freed by another thread
+ * and cause a illegal pointer dereference. This code uses
+ * get/put_device() to ensure the device structure cannot disappear
+ * from under our feet.
+ */
+ mutex_lock(&deferred_probe_mutex);
+ while (!list_empty(&deferred_probe_active_list)) {
+ dev = list_first_entry(&deferred_probe_active_list,
+ typeof(*dev), deferred_probe);
+ list_del_init(&dev->deferred_probe);
+
+ get_device(dev);
+
+ /* Drop the mutex while probing each device; the probe path
+ * may manipulate the deferred list */
+ mutex_unlock(&deferred_probe_mutex);
+ dev_dbg(dev, "Retrying from deferred list\n");
+ bus_probe_device(dev);
+ mutex_lock(&deferred_probe_mutex);
+
+ put_device(dev);
+ }
+ mutex_unlock(&deferred_probe_mutex);
+}
+static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func);
+
+static void driver_deferred_probe_add(struct device *dev)
+{
+ mutex_lock(&deferred_probe_mutex);
+ if (list_empty(&dev->deferred_probe)) {
+ dev_dbg(dev, "Added to deferred list\n");
+ list_add(&dev->deferred_probe, &deferred_probe_pending_list);
+ }
+ mutex_unlock(&deferred_probe_mutex);
+}
+
+void driver_deferred_probe_del(struct device *dev)
+{
+ mutex_lock(&deferred_probe_mutex);
+ if (!list_empty(&dev->deferred_probe)) {
+ dev_dbg(dev, "Removed from deferred list\n");
+ list_del_init(&dev->deferred_probe);
+ }
+ mutex_unlock(&deferred_probe_mutex);
+}
+
+static bool driver_deferred_probe_enable = false;
+/**
+ * driver_deferred_probe_trigger() - Kick off re-probing deferred devices
+ *
+ * This functions moves all devices from the pending list to the active
+ * list and schedules the deferred probe workqueue to process them. It
+ * should be called anytime a driver is successfully bound to a device.
+ */
+static void driver_deferred_probe_trigger(void)
+{
+ if (!driver_deferred_probe_enable)
+ return;
+
+ /* A successful probe means that all the devices in the pending list
+ * should be triggered to be reprobed. Move all the deferred devices
+ * into the active list so they can be retried by the workqueue */
+ mutex_lock(&deferred_probe_mutex);
+ list_splice_tail_init(&deferred_probe_pending_list,
+ &deferred_probe_active_list);
+ mutex_unlock(&deferred_probe_mutex);
+
+ /* Kick the re-probe thread. It may already be scheduled, but
+ * it is safe to kick it again. */
+ queue_work(deferred_wq, &deferred_probe_work);
+}
+
+/**
+ * deferred_probe_initcall() - Enable probing of deferred devices
+ *
+ * We don't want to get in the way when the bulk of drivers are getting probed.
+ * Instead, this initcall makes sure that deferred probing is delayed until
+ * late_initcall time.
+ */
+static int deferred_probe_initcall(void)
+{
+ deferred_wq = create_singlethread_workqueue("deferwq");
+ if (WARN_ON(!deferred_wq))
+ return -ENOMEM;
+
+ driver_deferred_probe_enable = true;
+ driver_deferred_probe_trigger();
+ return 0;
+}
+late_initcall(deferred_probe_initcall);
static void driver_bound(struct device *dev)
{
@@ -42,6 +169,11 @@
klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
+ /* Make sure the device is no longer in one of the deferred lists
+ * and kick off retrying all pending devices */
+ driver_deferred_probe_del(dev);
+ driver_deferred_probe_trigger();
+
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_BOUND_DRIVER, dev);
@@ -142,7 +274,11 @@
driver_sysfs_remove(dev);
dev->driver = NULL;
- if (ret != -ENODEV && ret != -ENXIO) {
+ if (ret == -EPROBE_DEFER) {
+ /* Driver requested deferred probing */
+ dev_info(dev, "Driver %s requests probe deferral\n", drv->name);
+ driver_deferred_probe_add(dev);
+ } else if (ret != -ENODEV && ret != -ENXIO) {
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 4f5c783..fdf7304 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -46,6 +46,7 @@
#define A3XX_RBBM_HW_VERSION 0x000
#define A3XX_RBBM_HW_RELEASE 0x001
#define A3XX_RBBM_HW_CONFIGURATION 0x002
+#define A3XX_RBBM_SP_HYST_CNT 0x012
#define A3XX_RBBM_SW_RESET_CMD 0x018
#define A3XX_RBBM_AHB_CTL0 0x020
#define A3XX_RBBM_AHB_CTL1 0x021
@@ -54,6 +55,7 @@
#define A3XX_RBBM_GPR0_CTL 0x02E
/* This the same register as on A2XX, just in a different place */
#define A3XX_RBBM_STATUS 0x030
+#define A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL 0x33
#define A3XX_RBBM_INTERFACE_HANG_INT_CTL 0x50
#define A3XX_RBBM_INTERFACE_HANG_MASK_CTL0 0x51
#define A3XX_RBBM_INTERFACE_HANG_MASK_CTL1 0x54
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index c01e676..2761b60 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2576,6 +2576,10 @@
/* Make all blocks contribute to the GPU BUSY perf counter */
adreno_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF);
+ /* Tune the hystersis counters for SP and CP idle detection */
+ adreno_regwrite(device, A3XX_RBBM_SP_HYST_CNT, 0x10);
+ adreno_regwrite(device, A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
+
/* Enable the RBBM error reporting bits. This lets us get
useful information on failure */
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 6f575ec..d960eaf 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -509,6 +509,7 @@
pwr->nap_allowed = pdata->nap_allowed;
pwr->idle_needed = pdata->idle_needed;
pwr->interval_timeout = pdata->idle_timeout;
+ pwr->strtstp_sleepwake = pdata->strtstp_sleepwake;
pwr->ebi1_clk = clk_get(&pdev->dev, "bus_clk");
if (IS_ERR(pwr->ebi1_clk))
pwr->ebi1_clk = NULL;
@@ -629,7 +630,8 @@
KGSL_PWR_INFO(device, "idle timer expired device %d\n", device->id);
if (device->requested_state != KGSL_STATE_SUSPEND) {
- if (device->pwrctrl.restore_slumber)
+ if (device->pwrctrl.restore_slumber ||
+ device->pwrctrl.strtstp_sleepwake)
kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
else
kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
@@ -770,7 +772,9 @@
case KGSL_STATE_NAP:
case KGSL_STATE_SLEEP:
del_timer_sync(&device->idle_timer);
- kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_NOMINAL);
+ if (!device->pwrctrl.strtstp_sleepwake)
+ kgsl_pwrctrl_pwrlevel_change(device,
+ KGSL_PWRLEVEL_NOMINAL);
device->pwrctrl.restore_slumber = true;
device->ftbl->suspend_context(device);
device->ftbl->stop(device);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 2222cdf..7dd429f 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -48,6 +48,7 @@
int thermal_pwrlevel;
unsigned int num_pwrlevels;
unsigned int interval_timeout;
+ bool strtstp_sleepwake;
struct regulator *gpu_reg;
uint32_t pcl;
unsigned int nap_allowed;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 39c158d..bda7cb2 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -274,6 +274,10 @@
#define T7_DATA_SIZE 3
#define MXT_MAX_RW_TRIES 3
#define MXT_BLOCK_SIZE 256
+#define MXT_CFG_VERSION_LEN 3
+#define MXT_CFG_VERSION_EQUAL 0
+#define MXT_CFG_VERSION_LESS 1
+#define MXT_CFG_VERSION_GREATER 2
#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
#define MXT_DEBUGFS_FILE "object"
@@ -340,8 +344,10 @@
u8 t9_min_reportid;
u8 t15_max_reportid;
u8 t15_min_reportid;
- u8 curr_cfg_version;
+ u8 cfg_version[MXT_CFG_VERSION_LEN];
int cfg_version_idx;
+ int t38_start_addr;
+ bool update_cfg;
const char *fw_name;
};
@@ -1047,8 +1053,10 @@
/* Calculate index for config major version in config array.
* Major version is the first byte in object T38.
*/
- if (object->type == MXT_SPT_USERDATA_T38)
+ if (object->type == MXT_SPT_USERDATA_T38) {
+ data->t38_start_addr = object->start_address;
found_t38 = true;
+ }
if (!found_t38 && mxt_object_writable(object->type))
data->cfg_version_idx += object->size + 1;
}
@@ -1056,14 +1064,85 @@
return 0;
}
-static int mxt_search_config_array(struct mxt_data *data, bool version_match)
+static int compare_versions(const u8 *v1, const u8 *v2)
+{
+ int i;
+
+ if (!v1 || !v2)
+ return -EINVAL;
+
+ /* The major version number stays the same across different versions for
+ * a particular controller on a target. The minor and sub-minor version
+ * numbers indicate which version is newer.
+ */
+ if (v1[0] != v2[0])
+ return -EINVAL;
+
+ for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
+ if (v1[i] > v2[i])
+ return MXT_CFG_VERSION_LESS; /* v2 is older */
+
+ if (v1[i] < v2[i])
+ return MXT_CFG_VERSION_GREATER; /* v2 is newer */
+ }
+
+ return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
+}
+
+static void mxt_check_config_version(struct mxt_data *data,
+ const struct mxt_config_info *cfg_info,
+ bool match_major,
+ const u8 **cfg_version_found,
+ bool *found_cfg_major_match)
+{
+ const u8 *cfg_version;
+ int result = -EINVAL;
+
+ cfg_version = cfg_info->config + data->cfg_version_idx;
+
+ if (*cfg_version_found)
+ result = compare_versions(*cfg_version_found, cfg_version);
+
+ if (match_major) {
+ if (result >= MXT_CFG_VERSION_EQUAL)
+ *found_cfg_major_match = true;
+
+ if (result == MXT_CFG_VERSION_EQUAL ||
+ result == MXT_CFG_VERSION_GREATER) {
+ data->config_info = cfg_info;
+ data->fw_name = cfg_info->fw_name;
+ *cfg_version_found = cfg_version;
+ }
+
+ if (result == MXT_CFG_VERSION_GREATER)
+ data->update_cfg = true;
+ } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
+ data->config_info = cfg_info;
+ data->fw_name = cfg_info->fw_name;
+ data->update_cfg = true;
+ *cfg_version_found = cfg_version;
+ }
+}
+
+/* If the controller's config version has a non-zero major number, call this
+ * function with match_major = true to look for the latest config present in
+ * the pdata based on matching family id, variant id, f/w version, build, and
+ * config major number. If the controller is programmed with wrong config data
+ * previously, call this function with match_major = false to look for latest
+ * config based on based on matching family id, variant id, f/w version and
+ * build only.
+ */
+static int mxt_search_config_array(struct mxt_data *data, bool match_major)
{
const struct mxt_platform_data *pdata = data->pdata;
const struct mxt_config_info *cfg_info;
- struct mxt_info *info = &data->info;
+ const struct mxt_info *info = &data->info;
+ const u8 *cfg_version_found;
+ bool found_cfg_major_match = false;
int i;
- u8 cfg_version;
+
+ cfg_version_found = match_major ? data->cfg_version : NULL;
for (i = 0; i < pdata->config_array_size; i++) {
@@ -1077,22 +1156,17 @@
info->version == cfg_info->version &&
info->build == cfg_info->build) {
- cfg_version = cfg_info->config[data->cfg_version_idx];
- if (data->curr_cfg_version == cfg_version ||
- !version_match) {
- data->config_info = cfg_info;
- data->fw_name = pdata->config_array[i].fw_name;
- return 0;
- }
+ mxt_check_config_version(data, cfg_info, match_major,
+ &cfg_version_found, &found_cfg_major_match);
}
}
+ if (data->config_info || found_cfg_major_match)
+ return 0;
+
+ data->config_info = NULL;
data->fw_name = NULL;
- dev_info(&data->client->dev,
- "Config not found: F: %d, V: %d, FW: %d.%d.%d, CFG: %d\n",
- info->family_id, info->variant_id,
- info->version >> 4, info->version & 0xF, info->build,
- data->curr_cfg_version);
+
return -EINVAL;
}
@@ -1115,24 +1189,40 @@
return -EINVAL;
}
- error = mxt_read_reg(data->client, object->start_address,
- &data->curr_cfg_version);
+ error = __mxt_read_reg(data->client, object->start_address,
+ sizeof(data->cfg_version), data->cfg_version);
if (error) {
dev_err(dev, "Unable to read config version\n");
return error;
}
+ dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
+ data->cfg_version[0], data->cfg_version[1],
+ data->cfg_version[2]);
/* It is possible that the config data on the controller is not
* versioned and the version number returns 0. In this case,
* find a match without the config version checking.
*/
error = mxt_search_config_array(data,
- data->curr_cfg_version != 0 ? true : false);
- if (error)
- return error;
+ data->cfg_version[0] != 0 ? true : false);
+ if (error) {
+ /* If a match wasn't found for a non-zero config version,
+ * it means the controller has the wrong config data. Search
+ * for a best match based on controller and firmware version,
+ * but not config version.
+ */
+ if (data->cfg_version[0])
+ error = mxt_search_config_array(data, false);
+ if (error) {
+ dev_err(dev,
+ "Unable to find matching config in pdata\n");
+ return error;
+ }
+ }
return 0;
}
+
static void mxt_reset_delay(struct mxt_data *data)
{
struct mxt_info *info = &data->info;
@@ -1152,17 +1242,104 @@
}
}
+static int mxt_backup_nv(struct mxt_data *data)
+{
+ int error;
+ u8 command_register;
+ int timeout_counter = 0;
+
+ /* Backup to memory */
+ mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_BACKUPNV,
+ MXT_BACKUP_VALUE);
+ msleep(MXT_BACKUP_TIME);
+
+ do {
+ error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_BACKUPNV,
+ &command_register);
+ if (error)
+ return error;
+
+ usleep_range(1000, 2000);
+
+ } while ((command_register != 0) && (++timeout_counter <= 100));
+
+ if (timeout_counter > 100) {
+ dev_err(&data->client->dev, "No response after backup!\n");
+ return -EIO;
+ }
+
+ /* Soft reset */
+ mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
+
+ mxt_reset_delay(data);
+
+ return 0;
+}
+
+static int mxt_save_objects(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ struct mxt_object *t7_object;
+ struct mxt_object *t9_object;
+ struct mxt_object *t15_object;
+ int error;
+
+ /* Store T7 and T9 locally, used in suspend/resume operations */
+ t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
+ if (!t7_object) {
+ dev_err(&client->dev, "Failed to get T7 object\n");
+ return -EINVAL;
+ }
+
+ data->t7_start_addr = t7_object->start_address;
+ error = __mxt_read_reg(client, data->t7_start_addr,
+ T7_DATA_SIZE, data->t7_data);
+ if (error < 0) {
+ dev_err(&client->dev,
+ "Failed to save current power state\n");
+ return error;
+ }
+
+ error = mxt_read_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
+ &data->t9_ctrl);
+ if (error < 0) {
+ dev_err(&client->dev, "Failed to save current touch object\n");
+ return error;
+ }
+
+ /* Store T9, T15's min and max report ids */
+ t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
+ if (!t9_object) {
+ dev_err(&client->dev, "Failed to get T9 object\n");
+ return -EINVAL;
+ }
+ data->t9_max_reportid = t9_object->max_reportid;
+ data->t9_min_reportid = t9_object->max_reportid -
+ t9_object->num_report_ids + 1;
+
+ if (data->pdata->key_codes) {
+ t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
+ if (!t15_object)
+ dev_dbg(&client->dev, "T15 object is not available\n");
+ else {
+ data->t15_max_reportid = t15_object->max_reportid;
+ data->t15_min_reportid = t15_object->max_reportid -
+ t15_object->num_report_ids + 1;
+ }
+ }
+
+ return 0;
+}
+
static int mxt_initialize(struct mxt_data *data)
{
struct i2c_client *client = data->client;
struct mxt_info *info = &data->info;
int error;
- int timeout_counter = 0;
u8 val;
- u8 command_register;
- struct mxt_object *t7_object;
- struct mxt_object *t9_object;
- struct mxt_object *t15_object;
+ const u8 *cfg_ver;
error = mxt_get_info(data);
if (error) {
@@ -1209,81 +1386,40 @@
dev_dbg(&client->dev, "Config info not found.\n");
/* Check register init values */
- error = mxt_check_reg_init(data);
+ if (data->config_info && data->config_info->config) {
+ if (data->update_cfg) {
+ error = mxt_check_reg_init(data);
+ if (error) {
+ dev_err(&client->dev,
+ "Failed to check reg init value\n");
+ goto free_object_table;
+ }
+
+ error = mxt_backup_nv(data);
+ if (error) {
+ dev_err(&client->dev, "Failed to back up NV\n");
+ goto free_object_table;
+ }
+
+ cfg_ver = data->config_info->config +
+ data->cfg_version_idx;
+ dev_info(&client->dev,
+ "Config updated from %d.%d.%d to %d.%d.%d\n",
+ data->cfg_version[0], data->cfg_version[1],
+ data->cfg_version[2],
+ cfg_ver[0], cfg_ver[1], cfg_ver[2]);
+
+ memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
+ }
+ } else {
+ dev_info(&client->dev,
+ "No cfg data defined, skipping check reg init\n");
+ }
+
+ error = mxt_save_objects(data);
if (error)
goto free_object_table;
- /* Store T7 and T9 locally, used in suspend/resume operations */
- t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
- if (!t7_object) {
- dev_err(&client->dev, "Failed to get T7 object\n");
- error = -EINVAL;
- goto free_object_table;
- }
-
- data->t7_start_addr = t7_object->start_address;
- error = __mxt_read_reg(client, data->t7_start_addr,
- T7_DATA_SIZE, data->t7_data);
- if (error < 0) {
- dev_err(&client->dev,
- "Failed to save current power state\n");
- goto free_object_table;
- }
- error = mxt_read_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
- &data->t9_ctrl);
- if (error < 0) {
- dev_err(&client->dev, "Failed to save current touch object\n");
- goto free_object_table;
- }
-
- /* Store T9, T15's min and max report ids */
- t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
- if (!t9_object) {
- dev_err(&client->dev, "Failed to get T9 object\n");
- error = -EINVAL;
- goto free_object_table;
- }
- data->t9_max_reportid = t9_object->max_reportid;
- data->t9_min_reportid = t9_object->max_reportid -
- t9_object->num_report_ids + 1;
-
- if (data->pdata->key_codes) {
- t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
- if (!t15_object)
- dev_dbg(&client->dev, "T15 object is not available\n");
- else {
- data->t15_max_reportid = t15_object->max_reportid;
- data->t15_min_reportid = t15_object->max_reportid -
- t15_object->num_report_ids + 1;
- }
- }
-
- /* Backup to memory */
- mxt_write_object(data, MXT_GEN_COMMAND_T6,
- MXT_COMMAND_BACKUPNV,
- MXT_BACKUP_VALUE);
- msleep(MXT_BACKUP_TIME);
- do {
- error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
- MXT_COMMAND_BACKUPNV,
- &command_register);
- if (error)
- goto free_object_table;
- usleep_range(1000, 2000);
- } while ((command_register != 0) && (++timeout_counter <= 100));
- if (timeout_counter > 100) {
- dev_err(&client->dev, "No response after backup!\n");
- error = -EIO;
- goto free_object_table;
- }
-
-
- /* Soft reset */
- mxt_write_object(data, MXT_GEN_COMMAND_T6,
- MXT_COMMAND_RESET, 1);
-
- mxt_reset_delay(data);
-
/* Update matrix size at info struct */
error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
if (error)
@@ -1518,6 +1654,7 @@
int error;
const char *fw_name;
u8 bootldr_id;
+ u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
/* If fw_name is set, then the existing firmware has an upgrade */
if (!data->fw_name) {
@@ -1566,6 +1703,13 @@
kfree(data->object_table);
data->object_table = NULL;
data->cfg_version_idx = 0;
+ data->update_cfg = false;
+
+ error = __mxt_write_reg(data->client, data->t38_start_addr,
+ sizeof(cfg_version), cfg_version);
+ if (error)
+ dev_err(dev,
+ "Unable to zero out config version after fw upgrade\n");
mxt_initialize(data);
}
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index c8827ff..ba510a2 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -18,7 +18,6 @@
#include <linux/crypto.h>
#include <linux/workqueue.h>
#include <linux/backing-dev.h>
-#include <linux/percpu.h>
#include <asm/atomic.h>
#include <linux/scatterlist.h>
#include <asm/page.h>
@@ -44,7 +43,8 @@
unsigned int idx_in;
unsigned int idx_out;
sector_t sector;
- atomic_t pending;
+ atomic_t cc_pending;
+ struct ablkcipher_request *req;
};
/*
@@ -57,7 +57,7 @@
struct convert_context ctx;
- atomic_t pending;
+ atomic_t io_pending;
int error;
sector_t sector;
struct dm_crypt_io *base_io;
@@ -106,18 +106,7 @@
enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID };
/*
- * Duplicated per-CPU state for cipher.
- */
-struct crypt_cpu {
- struct ablkcipher_request *req;
- /* ESSIV: struct crypto_cipher *essiv_tfm */
- void *iv_private;
- struct crypto_ablkcipher *tfms[0];
-};
-
-/*
* The fields in here must be read only after initialization,
- * changing state should be in crypt_cpu.
*/
struct crypt_config {
struct dm_dev *dev;
@@ -147,11 +136,9 @@
sector_t iv_offset;
unsigned int iv_size;
- /*
- * Duplicated per cpu state. Access through
- * per_cpu_ptr() only.
- */
- struct crypt_cpu __percpu *cpu;
+ /* ESSIV: struct crypto_cipher *essiv_tfm */
+ void *iv_private;
+ struct crypto_ablkcipher **tfms;
unsigned tfms_count;
/*
@@ -185,17 +172,12 @@
static void kcryptd_queue_crypt(struct dm_crypt_io *io);
static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq);
-static struct crypt_cpu *this_crypt_config(struct crypt_config *cc)
-{
- return this_cpu_ptr(cc->cpu);
-}
-
/*
* Use this to access cipher attributes that are the same for each CPU.
*/
static struct crypto_ablkcipher *any_tfm(struct crypt_config *cc)
{
- return __this_cpu_ptr(cc->cpu)->tfms[0];
+ return cc->tfms[0];
}
/*
@@ -260,7 +242,7 @@
struct hash_desc desc;
struct scatterlist sg;
struct crypto_cipher *essiv_tfm;
- int err, cpu;
+ int err;
sg_init_one(&sg, cc->key, cc->key_size);
desc.tfm = essiv->hash_tfm;
@@ -270,14 +252,12 @@
if (err)
return err;
- for_each_possible_cpu(cpu) {
- essiv_tfm = per_cpu_ptr(cc->cpu, cpu)->iv_private,
+ essiv_tfm = cc->iv_private;
- err = crypto_cipher_setkey(essiv_tfm, essiv->salt,
- crypto_hash_digestsize(essiv->hash_tfm));
- if (err)
- return err;
- }
+ err = crypto_cipher_setkey(essiv_tfm, essiv->salt,
+ crypto_hash_digestsize(essiv->hash_tfm));
+ if (err)
+ return err;
return 0;
}
@@ -288,16 +268,14 @@
struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm);
struct crypto_cipher *essiv_tfm;
- int cpu, r, err = 0;
+ int r, err = 0;
memset(essiv->salt, 0, salt_size);
- for_each_possible_cpu(cpu) {
- essiv_tfm = per_cpu_ptr(cc->cpu, cpu)->iv_private;
- r = crypto_cipher_setkey(essiv_tfm, essiv->salt, salt_size);
- if (r)
- err = r;
- }
+ essiv_tfm = cc->iv_private;
+ r = crypto_cipher_setkey(essiv_tfm, essiv->salt, salt_size);
+ if (r)
+ err = r;
return err;
}
@@ -337,8 +315,6 @@
static void crypt_iv_essiv_dtr(struct crypt_config *cc)
{
- int cpu;
- struct crypt_cpu *cpu_cc;
struct crypto_cipher *essiv_tfm;
struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
@@ -348,15 +324,13 @@
kzfree(essiv->salt);
essiv->salt = NULL;
- for_each_possible_cpu(cpu) {
- cpu_cc = per_cpu_ptr(cc->cpu, cpu);
- essiv_tfm = cpu_cc->iv_private;
+ essiv_tfm = cc->iv_private;
- if (essiv_tfm)
- crypto_free_cipher(essiv_tfm);
+ if (essiv_tfm)
+ crypto_free_cipher(essiv_tfm);
- cpu_cc->iv_private = NULL;
- }
+ cc->iv_private = NULL;
+
}
static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
@@ -365,7 +339,7 @@
struct crypto_cipher *essiv_tfm = NULL;
struct crypto_hash *hash_tfm = NULL;
u8 *salt = NULL;
- int err, cpu;
+ int err;
if (!opts) {
ti->error = "Digest algorithm missing for ESSIV mode";
@@ -390,15 +364,13 @@
cc->iv_gen_private.essiv.salt = salt;
cc->iv_gen_private.essiv.hash_tfm = hash_tfm;
- for_each_possible_cpu(cpu) {
- essiv_tfm = setup_essiv_cpu(cc, ti, salt,
- crypto_hash_digestsize(hash_tfm));
- if (IS_ERR(essiv_tfm)) {
- crypt_iv_essiv_dtr(cc);
- return PTR_ERR(essiv_tfm);
- }
- per_cpu_ptr(cc->cpu, cpu)->iv_private = essiv_tfm;
+ essiv_tfm = setup_essiv_cpu(cc, ti, salt,
+ crypto_hash_digestsize(hash_tfm));
+ if (IS_ERR(essiv_tfm)) {
+ crypt_iv_essiv_dtr(cc);
+ return PTR_ERR(essiv_tfm);
}
+ cc->iv_private = essiv_tfm;
return 0;
@@ -412,7 +384,8 @@
static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv,
struct dm_crypt_request *dmreq)
{
- struct crypto_cipher *essiv_tfm = this_crypt_config(cc)->iv_private;
+
+ struct crypto_cipher *essiv_tfm = cc->iv_private;
memset(iv, 0, cc->iv_size);
*(u64 *)iv = cpu_to_le64(dmreq->iv_sector);
@@ -750,16 +723,15 @@
static void crypt_alloc_req(struct crypt_config *cc,
struct convert_context *ctx)
{
- struct crypt_cpu *this_cc = this_crypt_config(cc);
unsigned key_index = ctx->sector & (cc->tfms_count - 1);
- if (!this_cc->req)
- this_cc->req = mempool_alloc(cc->req_pool, GFP_NOIO);
+ if (!ctx->req)
+ ctx->req = mempool_alloc(cc->req_pool, GFP_NOIO);
- ablkcipher_request_set_tfm(this_cc->req, this_cc->tfms[key_index]);
- ablkcipher_request_set_callback(this_cc->req,
+ ablkcipher_request_set_tfm(ctx->req, cc->tfms[key_index]);
+ ablkcipher_request_set_callback(ctx->req,
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
- kcryptd_async_done, dmreq_of_req(cc, this_cc->req));
+ kcryptd_async_done, dmreq_of_req(cc, ctx->req));
}
/*
@@ -768,19 +740,18 @@
static int crypt_convert(struct crypt_config *cc,
struct convert_context *ctx)
{
- struct crypt_cpu *this_cc = this_crypt_config(cc);
int r;
- atomic_set(&ctx->pending, 1);
+ atomic_set(&ctx->cc_pending, 1);
while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
ctx->idx_out < ctx->bio_out->bi_vcnt) {
crypt_alloc_req(cc, ctx);
- atomic_inc(&ctx->pending);
+ atomic_inc(&ctx->cc_pending);
- r = crypt_convert_block(cc, ctx, this_cc->req);
+ r = crypt_convert_block(cc, ctx, ctx->req);
switch (r) {
/* async */
@@ -789,20 +760,20 @@
INIT_COMPLETION(ctx->restart);
/* fall through*/
case -EINPROGRESS:
- this_cc->req = NULL;
+ ctx->req = NULL;
ctx->sector++;
continue;
/* sync */
case 0:
- atomic_dec(&ctx->pending);
+ atomic_dec(&ctx->cc_pending);
ctx->sector++;
cond_resched();
continue;
/* error */
default:
- atomic_dec(&ctx->pending);
+ atomic_dec(&ctx->cc_pending);
return r;
}
}
@@ -853,8 +824,7 @@
* return a partially allocated bio, the caller will then try
* to allocate additional bios while submitting this partial bio
*/
- if (i == (MIN_BIO_PAGES - 1))
- gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
+ gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
len = (size > PAGE_SIZE) ? PAGE_SIZE : size;
@@ -899,14 +869,15 @@
io->sector = sector;
io->error = 0;
io->base_io = NULL;
- atomic_set(&io->pending, 0);
+ io->ctx.req = NULL;
+ atomic_set(&io->io_pending, 0);
return io;
}
static void crypt_inc_pending(struct dm_crypt_io *io)
{
- atomic_inc(&io->pending);
+ atomic_inc(&io->io_pending);
}
/*
@@ -921,9 +892,11 @@
struct dm_crypt_io *base_io = io->base_io;
int error = io->error;
- if (!atomic_dec_and_test(&io->pending))
+ if (!atomic_dec_and_test(&io->io_pending))
return;
+ if (io->ctx.req)
+ mempool_free(io->ctx.req, cc->req_pool);
mempool_free(io, cc->io_pool);
if (likely(!base_io))
@@ -1047,16 +1020,14 @@
queue_work(cc->io_queue, &io->work);
}
-static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
- int error, int async)
+static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
{
struct bio *clone = io->ctx.bio_out;
struct crypt_config *cc = io->target->private;
- if (unlikely(error < 0)) {
+ if (unlikely(io->error < 0)) {
crypt_free_buffer_pages(cc, clone);
bio_put(clone);
- io->error = -EIO;
crypt_dec_pending(io);
return;
}
@@ -1108,11 +1079,13 @@
crypt_inc_pending(io);
r = crypt_convert(cc, &io->ctx);
- crypt_finished = atomic_dec_and_test(&io->ctx.pending);
+ if (r < 0)
+ io->error = -EIO;
+ crypt_finished = atomic_dec_and_test(&io->ctx.cc_pending);
/* Encryption was already finished, submit io now */
if (crypt_finished) {
- kcryptd_crypt_write_io_submit(io, r, 0);
+ kcryptd_crypt_write_io_submit(io, 0);
/*
* If there was an error, do not try next fragments.
@@ -1163,11 +1136,8 @@
crypt_dec_pending(io);
}
-static void kcryptd_crypt_read_done(struct dm_crypt_io *io, int error)
+static void kcryptd_crypt_read_done(struct dm_crypt_io *io)
{
- if (unlikely(error < 0))
- io->error = -EIO;
-
crypt_dec_pending(io);
}
@@ -1183,8 +1153,11 @@
r = crypt_convert(cc, &io->ctx);
- if (atomic_dec_and_test(&io->ctx.pending))
- kcryptd_crypt_read_done(io, r);
+ if (r < 0)
+ io->error = -EIO;
+
+ if (atomic_dec_and_test(&io->ctx.cc_pending))
+ kcryptd_crypt_read_done(io);
crypt_dec_pending(io);
}
@@ -1205,15 +1178,18 @@
if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);
+ if (error < 0)
+ io->error = -EIO;
+
mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
- if (!atomic_dec_and_test(&ctx->pending))
+ if (!atomic_dec_and_test(&ctx->cc_pending))
return;
if (bio_data_dir(io->base_bio) == READ)
- kcryptd_crypt_read_done(io, error);
+ kcryptd_crypt_read_done(io);
else
- kcryptd_crypt_write_io_submit(io, error, 1);
+ kcryptd_crypt_write_io_submit(io, 1);
}
static void kcryptd_crypt(struct work_struct *work)
@@ -1275,29 +1251,35 @@
}
}
-static void crypt_free_tfms(struct crypt_config *cc, int cpu)
+static void crypt_free_tfms(struct crypt_config *cc)
{
- struct crypt_cpu *cpu_cc = per_cpu_ptr(cc->cpu, cpu);
unsigned i;
+ if (!cc->tfms)
+ return;
+
for (i = 0; i < cc->tfms_count; i++)
- if (cpu_cc->tfms[i] && !IS_ERR(cpu_cc->tfms[i])) {
- crypto_free_ablkcipher(cpu_cc->tfms[i]);
- cpu_cc->tfms[i] = NULL;
+ if (cc->tfms[i] && !IS_ERR(cc->tfms[i])) {
+ crypto_free_ablkcipher(cc->tfms[i]);
+ cc->tfms[i] = NULL;
}
}
-static int crypt_alloc_tfms(struct crypt_config *cc, int cpu, char *ciphermode)
+static int crypt_alloc_tfms(struct crypt_config *cc, char *ciphermode)
{
- struct crypt_cpu *cpu_cc = per_cpu_ptr(cc->cpu, cpu);
unsigned i;
int err;
+ cc->tfms = kmalloc(cc->tfms_count * sizeof(struct crypto_ablkcipher *),
+ GFP_KERNEL);
+ if (!cc->tfms)
+ return -ENOMEM;
+
for (i = 0; i < cc->tfms_count; i++) {
- cpu_cc->tfms[i] = crypto_alloc_ablkcipher(ciphermode, 0, 0);
- if (IS_ERR(cpu_cc->tfms[i])) {
- err = PTR_ERR(cpu_cc->tfms[i]);
- crypt_free_tfms(cc, cpu);
+ cc->tfms[i] = crypto_alloc_ablkcipher(ciphermode, 0, 0);
+ if (IS_ERR(cc->tfms[i])) {
+ err = PTR_ERR(cc->tfms[i]);
+ crypt_free_tfms(cc);
return err;
}
}
@@ -1308,15 +1290,14 @@
static int crypt_setkey_allcpus(struct crypt_config *cc)
{
unsigned subkey_size = cc->key_size >> ilog2(cc->tfms_count);
- int cpu, err = 0, i, r;
+ int err = 0, i, r;
- for_each_possible_cpu(cpu) {
- for (i = 0; i < cc->tfms_count; i++) {
- r = crypto_ablkcipher_setkey(per_cpu_ptr(cc->cpu, cpu)->tfms[i],
- cc->key + (i * subkey_size), subkey_size);
- if (r)
- err = r;
- }
+ for (i = 0; i < cc->tfms_count; i++) {
+ r = crypto_ablkcipher_setkey(cc->tfms[i],
+ cc->key + (i * subkey_size),
+ subkey_size);
+ if (r)
+ err = r;
}
return err;
@@ -1360,8 +1341,6 @@
static void crypt_dtr(struct dm_target *ti)
{
struct crypt_config *cc = ti->private;
- struct crypt_cpu *cpu_cc;
- int cpu;
ti->private = NULL;
@@ -1373,13 +1352,7 @@
if (cc->crypt_queue)
destroy_workqueue(cc->crypt_queue);
- if (cc->cpu)
- for_each_possible_cpu(cpu) {
- cpu_cc = per_cpu_ptr(cc->cpu, cpu);
- if (cpu_cc->req)
- mempool_free(cpu_cc->req, cc->req_pool);
- crypt_free_tfms(cc, cpu);
- }
+ crypt_free_tfms(cc);
if (cc->bs)
bioset_free(cc->bs);
@@ -1397,9 +1370,6 @@
if (cc->dev)
dm_put_device(ti, cc->dev);
- if (cc->cpu)
- free_percpu(cc->cpu);
-
kzfree(cc->cipher);
kzfree(cc->cipher_string);
@@ -1413,7 +1383,7 @@
struct crypt_config *cc = ti->private;
char *tmp, *cipher, *chainmode, *ivmode, *ivopts, *keycount;
char *cipher_api = NULL;
- int cpu, ret = -EINVAL;
+ int ret = -EINVAL;
/* Convert to crypto api definition? */
if (strchr(cipher_in, '(')) {
@@ -1453,14 +1423,6 @@
if (tmp)
DMWARN("Ignoring unexpected additional cipher options");
- cc->cpu = __alloc_percpu(sizeof(*(cc->cpu)) +
- cc->tfms_count * sizeof(*(cc->cpu->tfms)),
- __alignof__(struct crypt_cpu));
- if (!cc->cpu) {
- ti->error = "Cannot allocate per cpu state";
- goto bad_mem;
- }
-
/*
* For compatibility with the original dm-crypt mapping format, if
* only the cipher name is supplied, use cbc-plain.
@@ -1487,12 +1449,10 @@
}
/* Allocate cipher */
- for_each_possible_cpu(cpu) {
- ret = crypt_alloc_tfms(cc, cpu, cipher_api);
- if (ret < 0) {
- ti->error = "Error allocating crypto tfm";
- goto bad;
- }
+ ret = crypt_alloc_tfms(cc, cipher_api);
+ if (ret < 0) {
+ ti->error = "Error allocating crypto tfm";
+ goto bad;
}
/* Initialize and set key */
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index ab732b2..a276e84 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -99,6 +99,7 @@
struct hci_fm_ssbi_peek ssbi_peek_reg;
struct hci_fm_sig_threshold_rsp sig_th;
struct hci_fm_ch_det_threshold ch_det_threshold;
+ struct hci_fm_data_rd_rsp default_data;
};
static struct video_device *priv_videodev;
@@ -1769,23 +1770,15 @@
struct iris_device *radio = video_get_drvdata(video_get_dev());
__u8 status = *((__u8 *) skb->data);
__u8 len;
- char *data;
if (status)
return;
len = skb->data[1];
- data = kmalloc(len+2, GFP_ATOMIC);
- if (!data) {
- FMDERR("Memory allocation failed");
- return;
- }
- data[0] = status;
- data[1] = len;
- memcpy(&data[2], &skb->data[DEFAULT_DATA_OFFSET], len);
- iris_q_evt_data(radio, data, len+2, IRIS_BUF_RD_DEFAULT);
+ memset(&radio->default_data, 0 , sizeof(struct hci_fm_data_rd_rsp));
+ memcpy(&radio->default_data, &skb->data[0], len+2);
+ iris_q_evt_data(radio, &skb->data[0], len+2, IRIS_BUF_RD_DEFAULT);
radio_hci_req_complete(hdev, status);
- kfree(data);
}
static void hci_cc_ssbi_peek_rsp(struct radio_hci_dev *hdev,
@@ -2773,6 +2766,8 @@
unsigned long arg = 0;
struct hci_fm_tx_ps tx_ps = {0};
struct hci_fm_tx_rt tx_rt = {0};
+ struct hci_fm_def_data_rd_req rd_txgain;
+ struct hci_fm_def_data_wr_req wr_txgain;
switch (ctrl->id) {
case V4L2_CID_PRIVATE_IRIS_TX_TONE:
@@ -3055,6 +3050,32 @@
radio->ps_repeatcount = ctrl->value;
break;
case V4L2_CID_TUNE_POWER_LEVEL:
+ if (ctrl->value > FM_TX_PWR_LVL_MAX)
+ ctrl->value = FM_TX_PWR_LVL_MAX;
+ if (ctrl->value < FM_TX_PWR_LVL_0)
+ ctrl->value = FM_TX_PWR_LVL_0;
+ rd_txgain.mode = FM_TX_PHY_CFG_MODE;
+ rd_txgain.length = FM_TX_PHY_CFG_LEN;
+ rd_txgain.param_len = 0x00;
+ rd_txgain.param = 0x00;
+
+ retval = hci_def_data_read(&rd_txgain, radio->fm_hdev);
+ if (retval < 0) {
+ FMDERR("Default data read failed for PHY_CFG %d\n",
+ retval);
+ break;
+ }
+ memset(&wr_txgain, 0, sizeof(wr_txgain));
+ wr_txgain.mode = FM_TX_PHY_CFG_MODE;
+ wr_txgain.length = FM_TX_PHY_CFG_LEN;
+ memcpy(&wr_txgain.data, &radio->default_data.data,
+ radio->default_data.ret_data_len);
+ wr_txgain.data[FM_TX_PWR_GAIN_OFFSET] =
+ (ctrl->value) * FM_TX_PWR_LVL_STEP_SIZE;
+ retval = hci_def_data_write(&wr_txgain, radio->fm_hdev);
+ if (retval < 0)
+ FMDERR("Default write failed for PHY_TXGAIN %d\n",
+ retval);
break;
case V4L2_CID_PRIVATE_IRIS_SOFT_MUTE:
radio->mute_mode.soft_mute = ctrl->value;
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 8d59590..d12d65e 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -484,8 +484,11 @@
uint8_t ctrl_data[max_control_command_size];
WARN_ON(ctrl == NULL);
-
- if (ctrl && ctrl->id == MSM_V4L2_PID_CTRL_CMD)
+ if (ctrl == NULL) {
+ pr_err("%s Invalid control\n", __func__);
+ return -EINVAL;
+ }
+ if (ctrl->id == MSM_V4L2_PID_CTRL_CMD)
return msm_server_proc_ctrl_cmd(pcam, ctrl, 1);
memset(ctrl_data, 0, sizeof(ctrl_data));
@@ -512,7 +515,11 @@
uint8_t ctrl_data[max_control_command_size];
WARN_ON(ctrl == NULL);
- if (ctrl && ctrl->id == MSM_V4L2_PID_CTRL_CMD)
+ if (ctrl == NULL) {
+ pr_err("%s Invalid control\n", __func__);
+ return -EINVAL;
+ }
+ if (ctrl->id == MSM_V4L2_PID_CTRL_CMD)
return msm_server_proc_ctrl_cmd(pcam, ctrl, 0);
memset(ctrl_data, 0, sizeof(ctrl_data));
@@ -2322,7 +2329,7 @@
if (IS_ERR(device_config)) {
rc = PTR_ERR(device_config);
pr_err("%s: error creating device: %d\n", __func__, rc);
- return rc;
+ goto config_setup_fail;
}
cdev_init(&config_cam->config_cdev,
@@ -2333,7 +2340,7 @@
if (rc < 0) {
pr_err("%s: error adding cdev: %d\n", __func__, rc);
device_destroy(msm_class, devno);
- return rc;
+ goto config_setup_fail;
}
g_server_dev.config_info.config_dev_name[dev_num]
= dev_name(device_config);
@@ -2345,16 +2352,23 @@
config_cam->config_stat_event_queue.pvdev = video_device_alloc();
if (config_cam->config_stat_event_queue.pvdev == NULL) {
pr_err("%s: video_device_alloc failed\n", __func__);
- return -ENOMEM;
+ goto config_setup_fail;
}
rc = msm_setup_v4l2_event_queue(
&config_cam->config_stat_event_queue.eventHandle,
config_cam->config_stat_event_queue.pvdev);
- if (rc < 0)
+ if (rc < 0) {
pr_err("%s failed to initialize event queue\n", __func__);
+ goto config_setup_fail;
+ }
return rc;
+
+config_setup_fail:
+ kfree(config_cam);
+ return rc;
+
}
static int msm_setup_server_dev(int node, char *device_name)
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index 7c26947..deb35cc 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -159,11 +159,16 @@
} fmt;
};
-static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+struct v4l2_create_buffers32 {
+ __u32 index; /* output: buffers index...index + count - 1 have been created */
+ __u32 count;
+ enum v4l2_memory memory;
+ struct v4l2_format32 format; /* filled in by the user, plane sizes calculated by the driver */
+ __u32 reserved[8];
+};
+
+static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
- get_user(kp->type, &up->type))
- return -EFAULT;
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -192,11 +197,24 @@
}
}
-static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
- put_user(kp->type, &up->type))
- return -EFAULT;
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
+ get_user(kp->type, &up->type))
+ return -EFAULT;
+ return __get_v4l2_format32(kp, up);
+}
+
+static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
+ copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format.fmt)))
+ return -EFAULT;
+ return __get_v4l2_format32(&kp->format, &up->format);
+}
+
+static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -225,6 +243,22 @@
}
}
+static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+ put_user(kp->type, &up->type))
+ return -EFAULT;
+ return __put_v4l2_format32(kp, up);
+}
+
+static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
+ copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt)))
+ return -EFAULT;
+ return __put_v4l2_format32(&kp->format, &up->format);
+}
+
struct v4l2_standard32 {
__u32 index;
__u32 id[2]; /* __u64 would get the alignment wrong */
@@ -675,6 +709,8 @@
#define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
#define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
+#define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
+#define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
#define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
#define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
@@ -693,6 +729,7 @@
struct v4l2_input v2i;
struct v4l2_standard v2s;
struct v4l2_ext_controls v2ecs;
+ struct v4l2_create_buffers v2crt;
unsigned long vx;
int vi;
} karg;
@@ -722,6 +759,8 @@
case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
+ case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
+ case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
}
switch (cmd) {
@@ -746,6 +785,12 @@
compatible_arg = 0;
break;
+ case VIDIOC_CREATE_BUFS:
+ err = get_v4l2_create32(&karg.v2crt, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_PREPARE_BUF:
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
@@ -824,6 +869,10 @@
err = put_v4l2_format32(&karg.v2f, up);
break;
+ case VIDIOC_CREATE_BUFS:
+ err = put_v4l2_create32(&karg.v2crt, up);
+ break;
+
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
@@ -922,6 +971,8 @@
case VIDIOC_DQEVENT:
case VIDIOC_SUBSCRIBE_EVENT:
case VIDIOC_UNSUBSCRIBE_EVENT:
+ case VIDIOC_CREATE_BUFS32:
+ case VIDIOC_PREPARE_BUF32:
ret = do_video_ioctl(file, cmd, arg);
break;
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index bda252f..5e44c90 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -259,6 +259,8 @@
[_IOC_NR(VIDIOC_DQEVENT)] = "VIDIOC_DQEVENT",
[_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)] = "VIDIOC_SUBSCRIBE_EVENT",
[_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
+ [_IOC_NR(VIDIOC_CREATE_BUFS)] = "VIDIOC_CREATE_BUFS",
+ [_IOC_NR(VIDIOC_PREPARE_BUF)] = "VIDIOC_PREPARE_BUF",
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
@@ -2196,6 +2198,40 @@
dbgarg(cmd, "type=0x%8.8x", sub->type);
break;
}
+ case VIDIOC_CREATE_BUFS:
+ {
+ struct v4l2_create_buffers *create = arg;
+
+ if (!ops->vidioc_create_bufs)
+ break;
+ /*if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }*/
+ ret = check_fmt(ops, create->format.type);
+ if (ret)
+ break;
+
+ ret = ops->vidioc_create_bufs(file, fh, create);
+
+ dbgarg(cmd, "count=%d @ %d\n", create->count, create->index);
+ break;
+ }
+ case VIDIOC_PREPARE_BUF:
+ {
+ struct v4l2_buffer *b = arg;
+
+ if (!ops->vidioc_prepare_buf)
+ break;
+ ret = check_fmt(ops, b->type);
+ if (ret)
+ break;
+
+ ret = ops->vidioc_prepare_buf(file, fh, b);
+
+ dbgarg(cmd, "index=%d", b->index);
+ break;
+ }
default:
{
bool valid_prio = true;
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index ddb3881..14d8b75 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -449,12 +449,6 @@
This provides support for the SD/MMC cell found in the
MSM and QSD SOCs from Qualcomm.
-config MMC_MSM_SDIO_SUPPORT
- boolean "Qualcomm MSM SDIO support"
- depends on MMC_MSM
- help
- This enables SDIO support in the msm_sdcc driver.
-
config MMC_MSM_CARD_HW_DETECTION
boolean "Qualcomm MMC Hardware detection support"
depends on MMC_MSM
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index f03aeac..b4d2edc 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1666,13 +1666,11 @@
msmsdcc_print_status(host, "irq0-p", status);
#endif
-#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
if (status & MCI_SDIOINTROPE) {
if (host->sdcc_suspending)
wake_lock(&host->sdio_suspend_wlock);
mmc_signal_sdio_irq(host->mmc);
}
-#endif
data = host->curr.data;
if (host->dummy_52_sent) {
@@ -2741,7 +2739,6 @@
return status;
}
-#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
{
struct msmsdcc_host *host = mmc_priv(mmc);
@@ -2771,7 +2768,6 @@
}
}
}
-#endif /* CONFIG_MMC_MSM_SDIO_SUPPORT */
#ifdef CONFIG_PM_RUNTIME
static int msmsdcc_enable(struct mmc_host *mmc)
@@ -3421,9 +3417,7 @@
.request = msmsdcc_request,
.set_ios = msmsdcc_set_ios,
.get_ro = msmsdcc_get_ro,
-#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
.enable_sdio_irq = msmsdcc_enable_sdio_irq,
-#endif
.start_signal_voltage_switch = msmsdcc_start_signal_voltage_switch,
.execute_tuning = msmsdcc_execute_tuning
};
@@ -4550,9 +4544,7 @@
if (plat->nonremovable)
mmc->caps |= MMC_CAP_NONREMOVABLE;
-#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
mmc->caps |= MMC_CAP_SDIO_IRQ;
-#endif
if (plat->is_sdio_al_client)
mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index 401b63c..bbcf3c4 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.c
@@ -79,6 +79,7 @@
#endif
struct sk_buff *waiting_for_ul_skb;
spinlock_t lock;
+ spinlock_t tx_queue_lock;
struct tasklet_struct tsklt;
u32 operation_mode; /* IOCTL specified mode (protocol, QoS header) */
uint8_t device_up;
@@ -321,6 +322,7 @@
{
struct rmnet_private *p = netdev_priv(dev);
u32 opmode = p->operation_mode;
+ unsigned long flags;
DBG1("%s: write complete\n", __func__);
if (RMNET_IS_MODE_IP(opmode) ||
@@ -335,12 +337,15 @@
((struct net_device *)(dev))->name, p->stats.tx_packets,
skb->len, skb->mark);
dev_kfree_skb_any(skb);
+
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
if (netif_queue_stopped(dev) &&
msm_bam_dmux_is_ch_low(p->ch_id)) {
DBG0("%s: Low WM hit, waking queue=%p\n",
__func__, skb);
netif_wake_queue(dev);
}
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
}
static void bam_notify(void *dev, int event, unsigned long data)
@@ -509,10 +514,12 @@
goto exit;
}
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
if (msm_bam_dmux_is_ch_full(p->ch_id)) {
netif_stop_queue(dev);
DBG0("%s: High WM hit, stopping queue=%p\n", __func__, skb);
}
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
exit:
msm_bam_dmux_ul_power_unvote();
@@ -770,6 +777,7 @@
p->waiting_for_ul_skb = NULL;
p->in_reset = 0;
spin_lock_init(&p->lock);
+ spin_lock_init(&p->tx_queue_lock);
#ifdef CONFIG_MSM_RMNET_DEBUG
p->timeout_us = timeout_us;
p->wakeups_xmit = p->wakeups_rcv = 0;
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index 65bc654..ce72a5b 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -214,8 +214,8 @@
break;
}
if (i == ADC_WAIT_COUNT) {
- pr_err("waited too long for offset eoc\n");
- return rc;
+ pr_err("waited too long for offset eoc returning -EBUSY\n");
+ return -EBUSY;
}
rc = pm8xxx_readb(chip->dev->parent, ADC_ARB_SECP_DATA0, &data_lsb);
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 80f50de..0e121d1 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -440,7 +440,6 @@
int ret;
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
- wake_lock(&msm_uport->dma_wake_lock);
/* Set up the MREG/NREG/DREG/MNDREG */
ret = clk_set_rate(msm_uport->clk, uport->uartclk);
if (ret) {
@@ -456,6 +455,7 @@
if (msm_uport->pclk) {
ret = clk_enable(msm_uport->pclk);
if (ret) {
+ clk_disable(msm_uport->clk);
dev_err(uport->dev,
"Error could not turn on UART pclk\n");
return ret;
@@ -1578,10 +1578,14 @@
tx->dma_base = dma_map_single(uport->dev, tx_buf->buf, UART_XMIT_SIZE,
DMA_TO_DEVICE);
+ wake_lock(&msm_uport->dma_wake_lock);
/* turn on uart clk */
ret = msm_hs_init_clk(uport);
- if (unlikely(ret))
+ if (unlikely(ret)) {
+ pr_err("Turning ON uartclk error\n");
+ wake_unlock(&msm_uport->dma_wake_lock);
return ret;
+ }
/* Set auto RFR Level */
data = msm_hs_read(uport, UARTDM_MR1_ADDR);
@@ -1646,20 +1650,26 @@
if (use_low_power_wakeup(msm_uport)) {
ret = irq_set_irq_wake(msm_uport->wakeup.irq, 1);
- if (unlikely(ret))
- return ret;
+ if (unlikely(ret)) {
+ pr_err("%s():Err setting wakeup irq\n", __func__);
+ goto deinit_uart_clk;
+ }
}
ret = request_irq(uport->irq, msm_hs_isr, IRQF_TRIGGER_HIGH,
"msm_hs_uart", msm_uport);
- if (unlikely(ret))
- return ret;
+ if (unlikely(ret)) {
+ pr_err("%s():Error getting uart irq\n", __func__);
+ goto free_wake_irq;
+ }
if (use_low_power_wakeup(msm_uport)) {
ret = request_irq(msm_uport->wakeup.irq, msm_hs_wakeup_isr,
IRQF_TRIGGER_FALLING,
"msm_hs_wakeup", msm_uport);
- if (unlikely(ret))
- return ret;
+ if (unlikely(ret)) {
+ pr_err("%s():Err getting uart wakeup_irq\n", __func__);
+ goto free_uart_irq;
+ }
disable_irq(msm_uport->wakeup.irq);
}
@@ -1673,8 +1683,19 @@
dev_err(uport->dev, "set active error:%d\n", ret);
pm_runtime_enable(uport->dev);
-
return 0;
+
+free_uart_irq:
+ free_irq(uport->irq, msm_uport);
+free_wake_irq:
+ irq_set_irq_wake(msm_uport->wakeup.irq, 0);
+deinit_uart_clk:
+ clk_disable(msm_uport->clk);
+ if (msm_uport->pclk)
+ clk_disable(msm_uport->pclk);
+ wake_unlock(&msm_uport->dma_wake_lock);
+
+ return ret;
}
/* Initialize tx and rx data structures */
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 9cbfad8..8e0bef0 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2710,6 +2710,12 @@
return 0;
}
+static int is_sps_req(struct ci13xxx_req *mReq)
+{
+ return (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID &&
+ mReq->req.udc_priv & MSM_SPS_MODE);
+}
+
/**
* ep_set_halt: sets the endpoint halt feature
*
@@ -2731,7 +2737,9 @@
#ifndef STALL_IN
/* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
- !list_empty(&mEp->qh.queue)) {
+ !list_empty(&mEp->qh.queue) &&
+ !is_sps_req(list_entry(mEp->qh.queue.next, struct ci13xxx_req,
+ queue))){
spin_unlock_irqrestore(mEp->lock, flags);
return -EAGAIN;
}
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index cc26c85..b086428 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -488,20 +488,16 @@
}
dev->notify->driver_data = dev;
- if (dev->port.in->driver_data) {
- pr_debug("%s: reset port:%d\n", __func__, dev->port_num);
- gport_rmnet_disconnect(dev);
+ if (!dev->port.in->driver_data) {
+ if (config_ep_by_speed(cdev->gadget, f, dev->port.in) ||
+ config_ep_by_speed(cdev->gadget, f, dev->port.out)) {
+ dev->port.in->desc = NULL;
+ dev->port.out->desc = NULL;
+ return -EINVAL;
+ }
+ ret = gport_rmnet_connect(dev);
}
- if (config_ep_by_speed(cdev->gadget, f, dev->port.in) ||
- config_ep_by_speed(cdev->gadget, f, dev->port.out)) {
- dev->port.in->desc = NULL;
- dev->port.out->desc = NULL;
- return -EINVAL;
- }
-
- ret = gport_rmnet_connect(dev);
-
atomic_set(&dev->online, 1);
return ret;
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 061e69c..29d500a 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -343,6 +343,86 @@
return ret;
}
+static ssize_t hdmi_common_wta_vendor_name(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ uint8 *s = (uint8 *) buf;
+ uint8 *d = external_common_state->spd_vendor_name;
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ ret = (ret > 8) ? 8 : ret;
+
+ memset(external_common_state->spd_vendor_name, 0, 8);
+ while (*s) {
+ if (*s & 0x60 && *s ^ 0x7f) {
+ *d = *s;
+ } else {
+ /* stop copying if control character found */
+ break;
+ }
+
+ if (++s > (uint8 *) (buf + ret))
+ break;
+
+ d++;
+ }
+
+ DEV_DBG("%s: '%s'\n", __func__,
+ external_common_state->spd_vendor_name);
+
+ return ret;
+}
+
+static ssize_t hdmi_common_rda_vendor_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%s\n",
+ external_common_state->spd_vendor_name);
+ DEV_DBG("%s: '%s'\n", __func__,
+ external_common_state->spd_vendor_name);
+
+ return ret;
+}
+
+static ssize_t hdmi_common_wta_product_description(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ uint8 *s = (uint8 *) buf;
+ uint8 *d = external_common_state->spd_product_description;
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ ret = (ret > 16) ? 16 : ret;
+
+ memset(external_common_state->spd_product_description, 0, 16);
+ while (*s) {
+ if (*s & 0x60 && *s ^ 0x7f) {
+ *d = *s;
+ } else {
+ /* stop copying if control character found */
+ break;
+ }
+
+ if (++s > (uint8 *) (buf + ret))
+ break;
+
+ d++;
+ }
+
+ DEV_DBG("%s: '%s'\n", __func__,
+ external_common_state->spd_product_description);
+
+ return ret;
+}
+
+static ssize_t hdmi_common_rda_product_description(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%s\n",
+ external_common_state->spd_product_description);
+ DEV_DBG("%s: '%s'\n", __func__,
+ external_common_state->spd_product_description);
+
+ return ret;
+}
+
static ssize_t hdmi_common_rda_hdcp(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -711,6 +791,11 @@
hdmi_common_rda_edid_physical_address, NULL);
static DEVICE_ATTR(scan_info, S_IRUGO,
hdmi_common_rda_edid_scan_info, NULL);
+static DEVICE_ATTR(vendor_name, S_IRUGO | S_IWUSR, hdmi_common_rda_vendor_name,
+ hdmi_common_wta_vendor_name);
+static DEVICE_ATTR(product_description, S_IRUGO | S_IWUSR,
+ hdmi_common_rda_product_description,
+ hdmi_common_wta_product_description);
static DEVICE_ATTR(3d_present, S_IRUGO, hdmi_common_rda_3d_present, NULL);
static DEVICE_ATTR(hdcp_present, S_IRUGO, hdmi_common_rda_hdcp_present, NULL);
#endif
@@ -731,6 +816,8 @@
&dev_attr_hpd.attr,
&dev_attr_pa.attr,
&dev_attr_scan_info.attr,
+ &dev_attr_vendor_name.attr,
+ &dev_attr_product_description.attr,
&dev_attr_3d_present.attr,
&dev_attr_hdcp_present.attr,
#endif
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h
index b8d2e5f..0f44da5 100644
--- a/drivers/video/msm/external_common.h
+++ b/drivers/video/msm/external_common.h
@@ -221,6 +221,8 @@
uint8 pt_scan_info;
uint8 it_scan_info;
uint8 ce_scan_info;
+ uint8 spd_vendor_name[8];
+ uint8 spd_product_description[16];
boolean present_3d;
boolean present_hdcp;
uint32 audio_data_blocks[16];
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index d3bb4c7..354add7 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -3937,6 +3937,137 @@
}
#endif
+#define IFRAME_CHECKSUM_32(d) \
+ ((d & 0xff) + ((d >> 8) & 0xff) + \
+ ((d >> 16) & 0xff) + ((d >> 24) & 0xff))
+
+static void hdmi_msm_spd_infoframe_packetsetup(void)
+{
+ uint32 packet_header = 0;
+ uint32 check_sum = 0;
+ uint32 packet_payload = 0;
+ uint32 packet_control = 0;
+
+ uint8 *vendor_name = external_common_state->spd_vendor_name;
+ uint8 *product_description =
+ external_common_state->spd_product_description;
+
+ /* 0x00A4 GENERIC1_HDR
+ * HB0 7:0 NUM
+ * HB1 15:8 NUM
+ * HB2 23:16 NUM */
+ /* Setup Packet header and payload */
+ /* 0x83 InfoFrame Type Code
+ 0x01 InfoFrame Version Number
+ 0x19 Length of Source Product Description InfoFrame
+ */
+ packet_header = 0x83 | (0x01 << 8) | (0x19 << 16);
+ HDMI_OUTP(0x00A4, packet_header);
+ check_sum += IFRAME_CHECKSUM_32(packet_header);
+
+ /* Vendor Name (7bit ASCII code) */
+ /* 0x00A8 GENERIC1_0
+ * BYTE0 7:0 CheckSum
+ * BYTE1 15:8 VENDOR_NAME[0]
+ * BYTE2 23:16 VENDOR_NAME[1]
+ * BYTE3 31:24 VENDOR_NAME[2] */
+ packet_payload = ((vendor_name[0] & 0x7f) << 8)
+ | ((vendor_name[1] & 0x7f) << 16)
+ | ((vendor_name[2] & 0x7f) << 24);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+ packet_payload |= ((0x100 - (0xff & check_sum)) & 0xff);
+ HDMI_OUTP(0x00A8, packet_payload);
+
+ /* 0x00AC GENERIC1_1
+ * BYTE4 7:0 VENDOR_NAME[3]
+ * BYTE5 15:8 VENDOR_NAME[4]
+ * BYTE6 23:16 VENDOR_NAME[5]
+ * BYTE7 31:24 VENDOR_NAME[6] */
+ packet_payload = (vendor_name[3] & 0x7f)
+ | ((vendor_name[4] & 0x7f) << 8)
+ | ((vendor_name[5] & 0x7f) << 16)
+ | ((vendor_name[6] & 0x7f) << 24);
+ HDMI_OUTP(0x00AC, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* Product Description (7-bit ASCII code) */
+ /* 0x00B0 GENERIC1_2
+ * BYTE8 7:0 VENDOR_NAME[7]
+ * BYTE9 15:8 PRODUCT_NAME[ 0]
+ * BYTE10 23:16 PRODUCT_NAME[ 1]
+ * BYTE11 31:24 PRODUCT_NAME[ 2] */
+ packet_payload = (vendor_name[7] & 0x7f)
+ | ((product_description[0] & 0x7f) << 8)
+ | ((product_description[1] & 0x7f) << 16)
+ | ((product_description[2] & 0x7f) << 24);
+ HDMI_OUTP(0x00B0, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* 0x00B4 GENERIC1_3
+ * BYTE12 7:0 PRODUCT_NAME[ 3]
+ * BYTE13 15:8 PRODUCT_NAME[ 4]
+ * BYTE14 23:16 PRODUCT_NAME[ 5]
+ * BYTE15 31:24 PRODUCT_NAME[ 6] */
+ packet_payload = (product_description[3] & 0x7f)
+ | ((product_description[4] & 0x7f) << 8)
+ | ((product_description[5] & 0x7f) << 16)
+ | ((product_description[6] & 0x7f) << 24);
+ HDMI_OUTP(0x00B4, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* 0x00B8 GENERIC1_4
+ * BYTE16 7:0 PRODUCT_NAME[ 7]
+ * BYTE17 15:8 PRODUCT_NAME[ 8]
+ * BYTE18 23:16 PRODUCT_NAME[ 9]
+ * BYTE19 31:24 PRODUCT_NAME[10] */
+ packet_payload = (product_description[7] & 0x7f)
+ | ((product_description[8] & 0x7f) << 8)
+ | ((product_description[9] & 0x7f) << 16)
+ | ((product_description[10] & 0x7f) << 24);
+ HDMI_OUTP(0x00B8, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* 0x00BC GENERIC1_5
+ * BYTE20 7:0 PRODUCT_NAME[11]
+ * BYTE21 15:8 PRODUCT_NAME[12]
+ * BYTE22 23:16 PRODUCT_NAME[13]
+ * BYTE23 31:24 PRODUCT_NAME[14] */
+ packet_payload = (product_description[11] & 0x7f)
+ | ((product_description[12] & 0x7f) << 8)
+ | ((product_description[13] & 0x7f) << 16)
+ | ((product_description[14] & 0x7f) << 24);
+ HDMI_OUTP(0x00BC, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* 0x00C0 GENERIC1_6
+ * BYTE24 7:0 PRODUCT_NAME[15]
+ * BYTE25 15:8 Source Device Information
+ * BYTE26 23:16 NUM
+ * BYTE27 31:24 NUM */
+ /* Source Device Information
+ * 00h unknown
+ * 01h Digital STB
+ * 02h DVD
+ * 03h D-VHS
+ * 04h HDD Video
+ * 05h DVC
+ * 06h DSC
+ * 07h Video CD
+ * 08h Game
+ * 09h PC general */
+ packet_payload = (product_description[15] & 0x7f) | 0x00 << 8;
+ HDMI_OUTP(0x00C0, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* GENERIC1_LINE | GENERIC1_CONT | GENERIC1_SEND
+ * Setup HDMI TX generic packet control
+ * Enable this packet to transmit every frame
+ * Enable HDMI TX engine to transmit Generic packet 1 */
+ packet_control = HDMI_INP_ND(0x0034);
+ packet_control |= ((0x1 << 24) | (1 << 5) | (1 << 4));
+ HDMI_OUTP(0x0034, packet_control);
+}
+
int hdmi_msm_clk(int on)
{
int rc;
@@ -4012,6 +4143,7 @@
#ifdef CONFIG_FB_MSM_HDMI_3D
hdmi_msm_vendor_infoframe_packetsetup();
#endif
+ hdmi_msm_spd_infoframe_packetsetup();
/* set timeout to 4.1ms (max) for hardware debounce */
hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
@@ -4587,6 +4719,10 @@
#ifdef CONFIG_FB_MSM_HDMI_3D
external_common_state->switch_3d = hdmi_msm_switch_3d;
#endif
+ memset(external_common_state->spd_vendor_name, 0,
+ sizeof(external_common_state->spd_vendor_name));
+ memset(external_common_state->spd_product_description, 0,
+ sizeof(external_common_state->spd_product_description));
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
hdmi_msm_state->cec_queue_start =
diff --git a/include/linux/device.h b/include/linux/device.h
index e4f62d8..b44a3b1 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -506,6 +506,10 @@
* @mutex: Mutex to synchronize calls to its driver.
* @bus: Type of bus device is on.
* @driver: Which driver has allocated this
+ * @deferred_probe: entry in deferred_probe_list which is used to retry the
+ * binding of drivers which were unable to get all the resources
+ * needed by the device; typically because it depends on another
+ * driver getting probed first.
* @platform_data: Platform data specific to the device.
* Example: For devices on custom boards, as typical of embedded
* and SOC based hardware, Linux often uses platform_data to point
@@ -564,6 +568,7 @@
struct bus_type *bus; /* type of bus device is on */
struct device_driver *driver; /* which driver has allocated this
device */
+ struct list_head deferred_probe;
void *platform_data; /* Platform specific data, device
core doesn't touch it */
struct dev_pm_info power;
diff --git a/include/linux/errno.h b/include/linux/errno.h
index 4668583..2d09bfa 100644
--- a/include/linux/errno.h
+++ b/include/linux/errno.h
@@ -16,6 +16,7 @@
#define ERESTARTNOHAND 514 /* restart if no handler.. */
#define ENOIOCTLCMD 515 /* No ioctl command */
#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
+#define EPROBE_DEFER 517 /* Driver requests probe retry */
/* Defined for the NFSv3 protocol */
#define EBADHANDLE 521 /* Illegal NFS file handle */
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 672468e..8739122 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -164,6 +164,7 @@
int num_levels;
int (*set_grp_async)(void);
unsigned int idle_timeout;
+ bool strtstp_sleepwake;
unsigned int nap_allowed;
unsigned int clk_map;
unsigned int idle_needed;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 175b54f..0a0fb1b 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -652,6 +652,10 @@
#define V4L2_BUF_FLAG_ERROR 0x0040
#define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */
#define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */
+#define V4L2_BUF_FLAG_PREPARED 0x0400 /* Buffer is prepared for queuing */
+/* Cache handling flags */
+#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE 0x0800
+#define V4L2_BUF_FLAG_NO_CACHE_CLEAN 0x1000
/*
* O V E R L A Y P R E V I E W
@@ -2035,6 +2039,15 @@
__u32 revision; /* chip revision, chip specific */
} __attribute__ ((packed));
+/* VIDIOC_CREATE_BUFS */
+struct v4l2_create_buffers {
+ __u32 index; /* output: buffers index...index + count - 1 have been created */
+ __u32 count;
+ enum v4l2_memory memory;
+ struct v4l2_format format; /* "type" is used always, the rest if sizeimage == 0 */
+ __u32 reserved[8];
+};
+
/*
* I O C T L C O D E S F O R V I D E O D E V I C E S
*
@@ -2125,6 +2138,11 @@
#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription)
#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription)
+/* Experimental, the below two ioctls may change over the next couple of kernel
+ versions */
+#define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers)
+#define VIDIOC_PREPARE_BUF _IOWR('V', 93, struct v4l2_buffer)
+
/* Reminder: when adding new ioctls please add support for them to
drivers/media/video/v4l2-compat-ioctl32.c as well! */
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index de2b356..dfad18d 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -44,7 +44,14 @@
/* default data access */
#define DEFAULT_DATA_OFFSET 2
#define DEFAULT_DATA_SIZE 249
-
+/* Power levels are 0-7, but SOC will expect values from 0-255
+ * So the each level step size will be 255/7 = 36 */
+#define FM_TX_PWR_LVL_STEP_SIZE 36
+#define FM_TX_PWR_LVL_0 0 /* Lowest power lvl that can be set for Tx */
+#define FM_TX_PWR_LVL_MAX 7 /* Max power lvl for Tx */
+#define FM_TX_PHY_CFG_MODE 0x3c
+#define FM_TX_PHY_CFG_LEN 0x10
+#define FM_TX_PWR_GAIN_OFFSET 14
/* HCI timeouts */
#define RADIO_HCI_TIMEOUT (10000) /* 10 seconds */
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index dd9f1e7..4d1c74a 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -122,6 +122,8 @@
int (*vidioc_qbuf) (struct file *file, void *fh, struct v4l2_buffer *b);
int (*vidioc_dqbuf) (struct file *file, void *fh, struct v4l2_buffer *b);
+ int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b);
+ int (*vidioc_prepare_buf)(struct file *file, void *fh, struct v4l2_buffer *b);
int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
int (*vidioc_g_fbuf) (struct file *file, void *fh,
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f57113b..74d0851 100755
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2783,6 +2783,12 @@
if (!conn->ssp_mode && conn->auth_initiator &&
(conn->pending_sec_level == BT_SECURITY_HIGH))
conn->pending_sec_level = BT_SECURITY_MEDIUM;
+
+ if (conn->ssp_mode && conn->auth_initiator &&
+ conn->io_capability != 0x03) {
+ conn->pending_sec_level = BT_SECURITY_HIGH;
+ conn->auth_type = HCI_AT_DEDICATED_BONDING_MITM;
+ }
}
if (conn->state != BT_CONFIG)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 52c1fe6..bcd0dd7 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1614,13 +1614,9 @@
hci_dev_lock_bh(hdev);
io_cap = cp->io_cap;
- if (io_cap == 0x03) {
- sec_level = BT_SECURITY_MEDIUM;
- auth_type = HCI_AT_DEDICATED_BONDING;
- } else {
- sec_level = BT_SECURITY_HIGH;
- auth_type = HCI_AT_DEDICATED_BONDING_MITM;
- }
+
+ sec_level = BT_SECURITY_MEDIUM;
+ auth_type = HCI_AT_DEDICATED_BONDING;
entry = hci_find_adv_entry(hdev, &cp->bdaddr);
if (entry && entry->flags & 0x04) {