Merge "net/wireless: Check for number of sub bands" into msm-3.0
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index 084050e..0c1762d 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -21,6 +21,7 @@
- qcom,sdcc-nonremovable - specifies whether the card in slot is
hot pluggable or hard wired.
- qcom,sdcc-disable_cmd23 - disable sending CMD23 to card when controller can't support it.
+ - qcom,sdcc-hs200 - enable eMMC4.5 HS200 bus speed mode
Example:
diff --git a/arch/arm/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dts
index b9179a3..f7eb7b9 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dts
@@ -49,9 +49,10 @@
reg = <0xf980b000 0x1000>;
interrupts = <0 123 0>;
- qcom,sdcc-clk-rates = <400000 24000000 48000000>;
+ qcom,sdcc-clk-rates = <400000 24000000 48000000 96000000 192000000>;
qcom,sdcc-sup-voltages = <3300 3300>;
qcom,sdcc-bus-width = <8>;
+ qcom,sdcc-hs200;
qcom,sdcc-nonremovable;
qcom,sdcc-disable_cmd23;
};
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 19622f2..44986a4 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -231,7 +231,9 @@
# CONFIG_HWMON is not set
CONFIG_MARIMBA_CORE=y
CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_RC_CORE is not set
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
# CONFIG_MT9T013 is not set
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 988720f..6ba9790 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -232,7 +232,9 @@
# CONFIG_HWMON is not set
CONFIG_MARIMBA_CORE=y
CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_RC_CORE is not set
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
# CONFIG_MT9T013 is not set
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 97f8722..7b9bdac 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -236,7 +236,6 @@
static struct completion dfab_unvote_completion;
static DEFINE_SPINLOCK(wakelock_reference_lock);
static int wakelock_reference_count;
-static struct delayed_work msm9615_bam_init_work;
static int a2_pc_disabled_wakelock_skipped;
/* End A2 power collaspe */
@@ -1639,10 +1638,9 @@
if (polling_mode)
rx_switch_to_interrupt_mode();
- queue_rx();
-
toggle_apps_ack();
complete_all(&bam_connection_completion);
+ queue_rx();
}
static void disconnect_to_bam(void)
@@ -1959,10 +1957,10 @@
}
bam_mux_initialized = 1;
- queue_rx();
toggle_apps_ack();
bam_connection_is_active = 1;
complete_all(&bam_connection_completion);
+ queue_rx();
return 0;
rx_event_reg_failed:
@@ -2034,7 +2032,7 @@
return ret;
}
-static void msm9615_bam_init(struct work_struct *work)
+static void msm9615_bam_init(void)
{
int ret = 0;
@@ -2079,19 +2077,10 @@
} else if (new_state & SMSM_A2_POWER_CONTROL) {
bam_dmux_log("%s: init\n", __func__);
grab_wakelock();
- if (cpu_is_msm9615()) {
- /*
- * even though a2 has signaled it is ready via the
- * SMSM_A2_POWER_CONTROL bit, it has not yet
- * enabled the pipes as needed by sps_connect
- * in satallite mode. Add a short delay to give modem
- * time to enable the pipes.
- */
- schedule_delayed_work(&msm9615_bam_init_work,
- msecs_to_jiffies(100));
- } else {
+ if (cpu_is_msm9615())
+ msm9615_bam_init();
+ else
bam_init();
- }
} else {
bam_dmux_log("%s: bad state change\n", __func__);
pr_err("%s: unsupported state change\n", __func__);
@@ -2159,7 +2148,6 @@
init_completion(&bam_connection_completion);
init_completion(&dfab_unvote_completion);
INIT_DELAYED_WORK(&ul_timeout_work, ul_timeout);
- INIT_DELAYED_WORK(&msm9615_bam_init_work, msm9615_bam_init);
wake_lock_init(&bam_wakelock, WAKE_LOCK_SUSPEND, "bam_dmux_wakelock");
rc = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_A2_POWER_CONTROL,
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index 3a6a30d..db1fb46 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -437,7 +437,7 @@
static struct rpm_regulator_init_data
msm8930_rpm_regulator_init_data[] __devinitdata = {
/* ID a_on pd ss min_uV max_uV supply sys_uA freq */
- RPM_SMPS(S1, 1, 1, 1, 500000, 1150000, NULL, 100000, 4p80),
+ RPM_SMPS(S1, 0, 1, 1, 500000, 1150000, NULL, 100000, 4p80),
RPM_SMPS(S2, 1, 1, 0, 1400000, 1400000, NULL, 100000, 1p60),
RPM_SMPS(S3, 0, 1, 0, 1150000, 1150000, NULL, 100000, 3p20),
RPM_SMPS(S4, 1, 1, 0, 2200000, 2200000, NULL, 100000, 1p60),
@@ -463,7 +463,7 @@
RPM_LDO(L21, 0, 1, 0, 1900000, 1900000, "8038_s4", 0, 0),
RPM_LDO(L22, 1, 1, 0, 1850000, 2950000, NULL, 10000, 10000),
RPM_LDO(L23, 1, 1, 1, 1800000, 1800000, "8038_s4", 0, 0),
- RPM_LDO(L24, 1, 1, 1, 500000, 1150000, "8038_s2", 10000, 10000),
+ RPM_LDO(L24, 0, 1, 1, 500000, 1150000, "8038_s2", 10000, 10000),
RPM_LDO(L26, 1, 1, 0, 1050000, 1050000, "8038_s2", 10000, 10000),
/* ID a_on pd ss supply */
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index caab4a6..dbd6329 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1653,10 +1653,11 @@
};
static struct tsens_platform_data msm_tsens_pdata = {
- .slope = {872, 872, 872, 872, 872},
.tsens_factor = 1000,
- .hw_type = MSM_8960,
- .tsens_num_sensor = 5,
+ .hw_type = APQ_8064,
+ .tsens_num_sensor = 11,
+ .slope = {1176, 1176, 1154, 1176, 1111,
+ 1132, 1132, 1199, 1132, 1199, 1132},
};
#ifdef CONFIG_MSM_FAKE_BATTERY
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 74471dd..a1a0dc7 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -514,7 +514,9 @@
#ifdef CONFIG_LTC4088_CHARGER
&msm_device_charger,
#endif
+#ifndef CONFIG_USB_GADGET_CI13XXX_MSM_HSIC
&msm_device_otg,
+#endif
&msm_device_hsic_peripheral,
&msm_device_gadget_peripheral,
&msm_device_hsusb_host,
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index d07703b..ec2be96 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -948,6 +948,7 @@
static void __init msm8625_reserve(void)
{
msm7x27a_reserve();
+ memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
msm_pm_8625_boot_pdata.p_addr = memblock_alloc(SZ_8, SZ_64K);
}
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index a83cde0..41c02ab 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -843,6 +843,12 @@
msm_pm_8625_boot_pdata.p_addr = memblock_alloc(SZ_8, SZ_64K);
}
+static void __init msm8625_reserve(void)
+{
+ memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+ msm7627a_reserve();
+}
+
static void msmqrd_adsp_add_pdev(void)
{
int rc = 0;
@@ -1268,7 +1274,7 @@
MACHINE_START(MSM8625_EVB, "QRD MSM8625 EVB")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm8625_map_io,
- .reserve = msm7627a_reserve,
+ .reserve = msm8625_reserve,
.init_irq = msm8625_init_irq,
.init_machine = msm_qrd_init,
.timer = &msm_timer,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 18acb36..0b204a0 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -921,6 +921,7 @@
[16] = MSM_GPIO_TO_INT(15),
[19] = MSM_GPIO_TO_INT(26),
[20] = MSM_GPIO_TO_INT(28),
+ [22] = USB_HSIC_IRQ,
[23] = MSM_GPIO_TO_INT(19),
[24] = MSM_GPIO_TO_INT(23),
[26] = MSM_GPIO_TO_INT(3),
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index f7e67cb..beb0c55 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -17,7 +17,6 @@
#include <linux/regulator/machine.h>
#include <linux/init.h>
#include <linux/irq.h>
-#include <linux/memblock.h>
#include <mach/irqs.h>
#include <mach/msm_iomap.h>
#include <mach/board.h>
@@ -1625,32 +1624,8 @@
(void *)MSM_QGIC_CPU_BASE);
}
-static phys_addr_t msm8625_phys_base;
-
-static void __init msm_reserve_sdram_memblock(void)
-{
- phys_addr_t paddr;
-
- paddr = memblock_alloc(SZ_8, SZ_64K);
- pr_debug("%s physical address = %x\n", __func__, paddr);
-
- if (!paddr) {
- pr_err("%s: failed to reserve SZ_8 bytes\n", __func__);
- return;
- }
-
- msm8625_phys_base = paddr;
-}
-
-phys_addr_t msm8625_get_phys_base(void)
-{
- return msm8625_phys_base;
-}
-EXPORT_SYMBOL(msm8625_get_phys_base);
-
void __init msm8625_map_io(void)
{
- msm_reserve_sdram_memblock();
msm_map_msm8625_io();
if (socinfo_init() < 0)
diff --git a/arch/arm/mach-msm/devices-msm7x2xa.h b/arch/arm/mach-msm/devices-msm7x2xa.h
index 73b58e0..3c81ccf 100644
--- a/arch/arm/mach-msm/devices-msm7x2xa.h
+++ b/arch/arm/mach-msm/devices-msm7x2xa.h
@@ -31,5 +31,4 @@
void __init msm8625_map_io(void);
int ar600x_wlan_power(bool on);
void __init msm8x25_spm_device_init(void);
-phys_addr_t msm8625_get_phys_base(void);
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 48e3837..27965d3 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -93,6 +93,8 @@
0xFB600000 */
#define MSM_STRONGLY_ORDERED_PAGE 0xFA0F0000
+#define MSM8625_SECONDARY_PHYS 0x0FE00000
+
#if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27)
#define MSM_SHARED_RAM_SIZE SZ_1M
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
index 92ed764..3c46d0f 100644
--- a/arch/arm/mach-msm/platsmp-8625.c
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -17,7 +17,6 @@
#include <linux/jiffies.h>
#include <linux/smp.h>
#include <linux/io.h>
-#include <linux/highmem.h>
#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
@@ -26,9 +25,7 @@
#include <asm/unified.h>
#include <mach/msm_iomap.h>
#include <mach/smp.h>
-
#include "pm.h"
-#include "devices-msm7x2xa.h"
#define MSM_CORE1_RESET 0xA8600590
#define MSM_CORE1_STATUS_MSK 0x02800000
@@ -209,8 +206,7 @@
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
int i, value;
- phys_addr_t base;
- void *vaddr;
+ void __iomem *second_ptr;
/*
* Initialise the present map, which describes the set of CPUs
@@ -225,14 +221,18 @@
* Write the address of secondary startup into the
* boot remapper register. The secondary CPU branches to this address.
*/
- base = msm8625_get_phys_base();
- __raw_writel(base, (MSM_CFG_CTL_BASE + 0x34));
+ __raw_writel(MSM8625_SECONDARY_PHYS, (MSM_CFG_CTL_BASE + 0x34));
mb();
- vaddr = kmap_atomic(phys_to_page(base));
+ second_ptr = ioremap_nocache(MSM8625_SECONDARY_PHYS, SZ_8);
+ if (!second_ptr) {
+ pr_err("failed to ioremap for secondary core\n");
+ return;
+ }
- msm8625_boot_vector_init(vaddr, virt_to_phys(msm_secondary_startup));
- kunmap_atomic(vaddr);
+ msm8625_boot_vector_init(second_ptr,
+ virt_to_phys(msm_secondary_startup));
+ iounmap(second_ptr);
/* Enable boot remapper address: bit 26 for core1 */
value = __raw_readl(MSM_CFG_CTL_BASE + 0x30);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 9b10ffd..3faeb37 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -257,7 +257,6 @@
static struct socinfo_v1 dummy_socinfo = {
.format = 1,
.version = 1,
- .build_id = "Dummy socinfo placeholder"
};
uint32_t socinfo_get_id(void)
@@ -613,10 +612,14 @@
dummy_socinfo.id = 109;
else if (machine_is_msm9615_mtp() || machine_is_msm9615_cdp())
dummy_socinfo.id = 104;
- else if (early_machine_is_copper())
+ else if (early_machine_is_copper()) {
dummy_socinfo.id = 126;
- else if (machine_is_msm8625_rumi3())
+ strlcpy(dummy_socinfo.build_id, "copper - ",
+ sizeof(dummy_socinfo.build_id));
+ } else if (machine_is_msm8625_rumi3())
dummy_socinfo.id = 127;
+ strlcat(dummy_socinfo.build_id, "Dummy socinfo",
+ sizeof(dummy_socinfo.build_id));
return (void *) &dummy_socinfo;
}
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 78c474e..a7f6a8c 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -2392,6 +2392,13 @@
return rc;
}
+ strlcpy(pcam->mctl.media_dev.model, QCAMERA_NAME,
+ sizeof(pcam->mctl.media_dev.model));
+ pcam->mctl.media_dev.dev = &client->dev;
+ rc = media_device_register(&pcam->mctl.media_dev);
+ pvdev->v4l2_dev = &pcam->v4l2_dev;
+ pcam->v4l2_dev.mdev = &pcam->mctl.media_dev;
+
/* init video device's driver interface */
D("sensor name = %s, sizeof(pvdev->name)=%d\n",
pcam->mctl.sensor_sdev->name, sizeof(pvdev->name));
@@ -2406,6 +2413,10 @@
pvdev->minor = -1;
pvdev->vfl_type = 1;
+ media_entity_init(&pvdev->entity, 0, NULL, 0);
+ pvdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+ pvdev->entity.group_id = QCAMERA_VNODE_GROUP_ID;
+
/* register v4l2 video device to kernel as /dev/videoXX */
D("video_register_device\n");
rc = video_register_device(pvdev,
@@ -2415,6 +2426,7 @@
pr_err("%s: video_register_device failed\n", __func__);
goto reg_fail;
}
+ pvdev->entity.name = video_device_node_name(pvdev);
D("%s: video device registered as /dev/video%d\n",
__func__, pvdev->num);
@@ -2600,6 +2612,15 @@
g_server_dev.mctl_node_info.mctl_node_name
[g_server_dev.mctl_node_info.num_mctl_nodes]);
+ /*Temporary solution to store info in media device structure
+ until we can expand media device structure to support more
+ device info*/
+ snprintf(pcam->mctl.media_dev.serial,
+ sizeof(pcam->mctl.media_dev.serial),
+ "%s-%d-%d", QCAMERA_NAME,
+ sdata->sensor_platform_info->mount_angle,
+ sdata->camera_type);
+
g_server_dev.camera_info.num_cameras++;
g_server_dev.mctl_node_info.num_mctl_nodes++;
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index c90ab44..dd65c01 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -218,6 +218,8 @@
/* most-frequently accessed manager object*/
struct msm_sync sync;
+ /*Media device node*/
+ struct media_device media_dev;
/* the following reflect the HW topology information*/
/*mandatory*/
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index 31b8239..1b19c99 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -1208,6 +1208,75 @@
return rc;
}
+static long venc_set_header_mode(struct video_client_ctx *client_ctx,
+ __s32 mode)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_sps_pps_for_idr_enable sps_pps_for_idr_enable;
+ int rc = 0;
+
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ rc = -EINVAL;
+ goto err;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_ENABLE_SPS_PPS_FOR_IDR;
+ vcd_property_hdr.sz = sizeof(sps_pps_for_idr_enable);
+ switch (mode) {
+ case V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE:
+ sps_pps_for_idr_enable.sps_pps_for_idr_enable_flag = 0;
+ break;
+ case V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME:
+ sps_pps_for_idr_enable.sps_pps_for_idr_enable_flag = 1;
+ break;
+ case V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME:
+ default:
+ WFD_MSG_ERR("Video header mode %d not supported\n",
+ mode);
+ rc = -ENOTSUPP;
+ goto err;
+ }
+
+ rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &sps_pps_for_idr_enable);
+ if (rc) {
+ WFD_MSG_ERR("Failed to set enable_sps_pps_for_idr\n");
+ goto err;
+ }
+err:
+ return rc;
+}
+
+static long venc_get_header_mode(struct video_client_ctx *client_ctx,
+ __s32 *mode)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_sps_pps_for_idr_enable sps_pps_for_idr_enable;
+ int rc = 0;
+
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ rc = -EINVAL;
+ goto err;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_ENABLE_SPS_PPS_FOR_IDR;
+ vcd_property_hdr.sz = sizeof(sps_pps_for_idr_enable);
+ rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &sps_pps_for_idr_enable);
+ if (rc) {
+ WFD_MSG_ERR("Failed to get sps/pps for idr enable\n");
+ goto err;
+ }
+
+ *mode = sps_pps_for_idr_enable.sps_pps_for_idr_enable_flag ?
+ V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME :
+ V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
+err:
+ return rc;
+}
+
static long venc_alloc_input_buffer(struct v4l2_subdev *sd, void *arg)
{
struct mem_region *mregion = arg;
@@ -1497,6 +1566,9 @@
case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
rc = venc_set_qp_range(client_ctx, ctrl->id, ctrl->value);
break;
+ case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+ rc = venc_set_header_mode(client_ctx, ctrl->value);
+ break;
default:
WFD_MSG_ERR("Set property not suported: %d\n", ctrl->id);
rc = -ENOTSUPP;
@@ -1547,6 +1619,9 @@
case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
rc = venc_get_qp_range(client_ctx, ctrl->id, &ctrl->value);
break;
+ case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+ rc = venc_get_header_mode(client_ctx, &ctrl->value);
+ break;
default:
WFD_MSG_ERR("Get property not suported: %d\n", ctrl->id);
rc = -ENOTSUPP;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 1eb9d5f..20c59fc 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1246,7 +1246,7 @@
* If a host does all the power sequencing itself, ignore the
* initial MMC_POWER_UP stage.
*/
-static void mmc_power_up(struct mmc_host *host)
+void mmc_power_up(struct mmc_host *host)
{
int bit;
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 49684f6..d832d75 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -32,6 +32,8 @@
void mmc_init_erase(struct mmc_card *card);
+void mmc_power_up(struct mmc_host *host);
+void mmc_power_off(struct mmc_host *host);
void mmc_set_chip_select(struct mmc_host *host, int mode);
void mmc_set_clock(struct mmc_host *host, unsigned int hz);
void mmc_gate_clock(struct mmc_host *host);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index cd0eb4e..fb98b01 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1140,8 +1140,11 @@
if (err) {
printk(KERN_ERR "%s: Re-init card rc = %d (retries = %d)\n",
mmc_hostname(host), err, retries);
- mdelay(5);
retries--;
+ mmc_power_off(host);
+ usleep_range(5000, 5500);
+ mmc_power_up(host);
+ mmc_select_voltage(host, host->ocr);
continue;
}
break;
@@ -1278,6 +1281,10 @@
err = mmc_sd_init_card(host, host->ocr, NULL);
if (err) {
retries--;
+ mmc_power_off(host);
+ usleep_range(5000, 5500);
+ mmc_power_up(host);
+ mmc_select_voltage(host, host->ocr);
continue;
}
break;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 69921b1..ff12eb1 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -96,13 +96,24 @@
* An array holding the Tuning pattern to compare with when
* executing a tuning cycle.
*/
-static const u32 cmd19_tuning_block[16] = {
+static const u32 tuning_block_64[] = {
0x00FF0FFF, 0xCCC3CCFF, 0xFFCC3CC3, 0xEFFEFFFE,
0xDDFFDFFF, 0xFBFFFBFF, 0xFF7FFFBF, 0xEFBDF777,
0xF0FFF0FF, 0x3CCCFC0F, 0xCFCC33CC, 0xEEFFEFFF,
0xFDFFFDFF, 0xFFBFFFDF, 0xFFF7FFBB, 0xDE7B7FF7
};
+static const u32 tuning_block_128[] = {
+ 0xFF00FFFF, 0x0000FFFF, 0xCCCCFFFF, 0xCCCC33CC,
+ 0xCC3333CC, 0xFFFFCCCC, 0xFFFFEEFF, 0xFFEEEEFF,
+ 0xFFDDFFFF, 0xDDDDFFFF, 0xBBFFFFFF, 0xBBFFFFFF,
+ 0xFFFFFFBB, 0xFFFFFF77, 0x77FF7777, 0xFFEEDDBB,
+ 0x00FFFFFF, 0x00FFFFFF, 0xCCFFFF00, 0xCC33CCCC,
+ 0x3333CCCC, 0xFFCCCCCC, 0xFFEEFFFF, 0xEEEEFFFF,
+ 0xDDFFFFFF, 0xDDFFFFFF, 0xFFFFFFDD, 0xFFFFFFBB,
+ 0xFFFFBBBB, 0xFFFF77FF, 0xFF7777FF, 0xEEDDBB77
+};
+
#if IRQ_DEBUG == 1
static char *irq_status_bits[] = { "cmdcrcfail", "datcrcfail", "cmdtimeout",
"dattimeout", "txunderrun", "rxoverrun",
@@ -331,9 +342,6 @@
BUG_ON(host->curr.data);
- host->curr.mrq = NULL;
- host->curr.cmd = NULL;
-
del_timer(&host->req_tout_timer);
if (mrq->data)
@@ -341,6 +349,9 @@
if (mrq->cmd->error == -ETIMEDOUT)
mdelay(5);
+ /* Clear current request information as current request has ended */
+ memset(&host->curr, 0, sizeof(struct msmsdcc_curr_req));
+
/*
* Need to drop the host lock here; mmc_request_done may call
* back into the driver...
@@ -500,10 +511,13 @@
msmsdcc_stop_data(host);
if (!mrq->data->stop || mrq->cmd->error ||
(mrq->sbc && !mrq->data->error)) {
- host->curr.mrq = NULL;
- host->curr.cmd = NULL;
mrq->data->bytes_xfered = host->curr.data_xfered;
del_timer(&host->req_tout_timer);
+ /*
+ * Clear current request information as current
+ * request has ended
+ */
+ memset(&host->curr, 0, sizeof(struct msmsdcc_curr_req));
spin_unlock_irqrestore(&host->lock, flags);
mmc_request_done(host->mmc, mrq);
@@ -657,10 +671,13 @@
msmsdcc_stop_data(host);
if (!mrq->data->stop || mrq->cmd->error ||
(mrq->sbc && !mrq->data->error)) {
- host->curr.mrq = NULL;
- host->curr.cmd = NULL;
mrq->data->bytes_xfered = host->curr.data_xfered;
del_timer(&host->req_tout_timer);
+ /*
+ * Clear current request information as current
+ * request has ended
+ */
+ memset(&host->curr, 0, sizeof(struct msmsdcc_curr_req));
spin_unlock_irqrestore(&host->lock, flags);
mmc_request_done(host->mmc, mrq);
@@ -986,7 +1003,9 @@
*c |= MCI_CSPM_DATCMD;
/* Check if AUTO CMD19 is required or not? */
- if (host->tuning_needed) {
+ if (host->tuning_needed &&
+ !(host->mmc->ios.timing == MMC_TIMING_MMC_HS200)) {
+
/*
* For open ended block read operation (without CMD23),
* AUTO_CMD19 bit should be set while sending the READ command.
@@ -1518,7 +1537,7 @@
mmc_hostname(host->mmc), cmd->opcode);
cmd->error = -ETIMEDOUT;
} else if ((status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) &&
- !host->cmd19_tuning_in_progress) {
+ !host->tuning_in_progress) {
pr_err("%s: CMD%d: Command CRC error\n",
mmc_hostname(host->mmc), cmd->opcode);
msmsdcc_dump_sdcc_state(host);
@@ -1548,6 +1567,7 @@
host->curr.cmd = cmd;
} else {
host->prog_enable = 0;
+ host->curr.wait_for_auto_prog_done = 0;
if (host->dummy_52_needed)
host->dummy_52_needed = 0;
if (cmd->data && cmd->error)
@@ -2147,6 +2167,22 @@
return rc;
}
+static inline int msmsdcc_set_vccq_vol(struct msmsdcc_host *host, int level)
+{
+ struct msm_mmc_slot_reg_data *curr_slot = host->plat->vreg_data;
+ int rc = 0;
+
+ if (curr_slot && curr_slot->vccq_data) {
+ rc = msmsdcc_vreg_set_voltage(curr_slot->vccq_data,
+ level, level);
+ if (rc)
+ pr_err("%s: %s: failed to change vccq level to %d",
+ mmc_hostname(host->mmc), __func__, level);
+ }
+
+ return rc;
+}
+
static inline int msmsdcc_is_pwrsave(struct msmsdcc_host *host)
{
if (host->clk_rate > 400000 && msmsdcc_pwrsave)
@@ -2428,7 +2464,8 @@
* Select the controller timing mode according
* to current bus speed mode
*/
- if (ios->timing == MMC_TIMING_UHS_SDR104) {
+ if ((ios->timing == MMC_TIMING_UHS_SDR104) ||
+ (ios->timing == MMC_TIMING_MMC_HS200)) {
clk |= (4 << 14);
host->tuning_needed = 1;
} else if (ios->timing == MMC_TIMING_UHS_DDR50) {
@@ -2535,9 +2572,9 @@
host->clks_on = 0;
}
- if (host->cmd19_tuning_in_progress)
+ if (host->tuning_in_progress)
WARN(!host->clks_on,
- "cmd19_tuning_in_progress but SDCC clocks are OFF\n");
+ "tuning_in_progress but SDCC clocks are OFF\n");
spin_unlock_irqrestore(&host->lock, flags);
}
@@ -2723,6 +2760,16 @@
host->io_pad_pwr_switch = 0;
spin_unlock_irqrestore(&host->lock, flags);
+ /*
+ * For eMMC cards, VccQ voltage range must be changed
+ * only if it operates in HS200 SDR 1.2V mode or in
+ * DDR 1.2V mode.
+ */
+ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_120) {
+ rc = msmsdcc_set_vccq_vol(host, 1200000);
+ goto out;
+ }
+
if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
/* Change voltage level of VDDPX to high voltage */
rc = msmsdcc_set_vddp_high_vol(host);
@@ -3114,6 +3161,8 @@
struct msmsdcc_host *host = mmc_priv(mmc);
unsigned long flags;
u8 phase, *data_buf, tuned_phases[16], tuned_phase_cnt = 0;
+ const u32 *tuning_block_pattern = tuning_block_64;
+ int size = sizeof(tuning_block_64); /* Tuning pattern size in bytes */
pr_debug("%s: Enter %s\n", mmc_hostname(mmc), __func__);
@@ -3128,8 +3177,14 @@
WARN(!host->clks_on, "SDCC clocks are turned off\n");
WARN(host->sdcc_irq_disabled, "SDCC IRQ is disabled\n");
- host->cmd19_tuning_in_progress = 1;
+ host->tuning_in_progress = 1;
msmsdcc_delay(host);
+ if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) &&
+ (mmc->ios.bus_width == MMC_BUS_WIDTH_8)) {
+ tuning_block_pattern = tuning_block_128;
+ size = sizeof(tuning_block_128);
+ }
+
spin_unlock_irqrestore(&host->lock, flags);
/* first of all reset the tuning block */
@@ -3137,7 +3192,7 @@
if (rc)
goto out;
- data_buf = kmalloc(64, GFP_KERNEL);
+ data_buf = kmalloc(size, GFP_KERNEL);
if (!data_buf) {
rc = -ENOMEM;
goto out;
@@ -3158,23 +3213,23 @@
if (rc)
goto kfree;
- cmd.opcode = MMC_SEND_TUNING_BLOCK;
+ cmd.opcode = opcode;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
- data.blksz = 64;
+ data.blksz = size;
data.blocks = 1;
data.flags = MMC_DATA_READ;
data.timeout_ns = 1000 * 1000 * 1000; /* 1 sec */
data.sg = &sg;
data.sg_len = 1;
- sg_init_one(&sg, data_buf, 64);
- memset(data_buf, 0, 64);
+ sg_init_one(&sg, data_buf, size);
+ memset(data_buf, 0, size);
mmc_wait_for_req(mmc, &mrq);
if (!cmd.error && !data.error &&
- !memcmp(data_buf, cmd19_tuning_block, 64)) {
- /* tuning is successful with this tuning point */
+ !memcmp(data_buf, tuning_block_pattern, size)) {
+ /* tuning is successful at this tuning point */
tuned_phases[tuned_phase_cnt++] = phase;
pr_debug("%s: %s: found good phase = %d\n",
mmc_hostname(mmc), __func__, phase);
@@ -3211,7 +3266,7 @@
out:
spin_lock_irqsave(&host->lock, flags);
msmsdcc_delay(host);
- host->cmd19_tuning_in_progress = 0;
+ host->tuning_in_progress = 0;
spin_unlock_irqrestore(&host->lock, flags);
exit:
pr_debug("%s: Exit %s\n", mmc_hostname(mmc), __func__);
@@ -3933,6 +3988,7 @@
}
} else {
host->prog_enable = 0;
+ host->curr.wait_for_auto_prog_done = 0;
msmsdcc_reset_and_restore(host);
msmsdcc_request_end(host, mrq);
}
@@ -4343,6 +4399,12 @@
mmc->caps |= (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
MMC_CAP_SET_XPC_180);
+ if (pdev->dev.of_node) {
+ if (of_get_property((&pdev->dev)->of_node,
+ "qcom,sdcc-hs200", NULL))
+ mmc->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
+ }
+
if (plat->nonremovable)
mmc->caps |= MMC_CAP_NONREMOVABLE;
#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 8a728f2..0166173 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -2,7 +2,7 @@
* linux/drivers/mmc/host/msmsdcc.h - QCT MSM7K SDC Controller
*
* Copyright (C) 2008 Google, All Rights Reserved.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-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 as
@@ -394,7 +394,7 @@
struct timer_list req_tout_timer;
unsigned long reg_write_delay;
bool io_pad_pwr_switch;
- bool cmd19_tuning_in_progress;
+ bool tuning_in_progress;
bool tuning_needed;
bool sdio_gpio_lpm;
bool irq_wake_enabled;
diff --git a/drivers/staging/qcache/fmem.c b/drivers/staging/qcache/fmem.c
index c900647..acca6f1 100644
--- a/drivers/staging/qcache/fmem.c
+++ b/drivers/staging/qcache/fmem.c
@@ -16,6 +16,10 @@
#include <linux/fmem.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#ifdef CONFIG_MEMORY_HOTPLUG
+#include <linux/memory.h>
+#include <linux/memory_hotplug.h>
+#endif
#include "tmem.h"
#include <asm/mach/map.h>
@@ -23,6 +27,11 @@
enum fmem_state fmem_state;
static spinlock_t fmem_state_lock;
+#ifdef CONFIG_MEMORY_HOTPLUG
+static unsigned int section_powered_off[NR_MEM_SECTIONS];
+static unsigned int fmem_section_start, fmem_section_end;
+#endif
+
void *fmem_map_virtual_area(int cacheability)
{
unsigned long addr;
@@ -51,6 +60,10 @@
{
struct fmem_platform_data *pdata = pdev->dev.platform_data;
+#ifdef CONFIG_MEMORY_HOTPLUG
+ fmem_section_start = pdata->phys >> PA_SECTION_SHIFT;
+ fmem_section_end = (pdata->phys - 1 + pdata->size) >> PA_SECTION_SHIFT;
+#endif
fmem_data.phys = pdata->phys + pdata->reserved_size_low;
fmem_data.size = pdata->size - pdata->reserved_size_low -
pdata->reserved_size_high;
@@ -96,6 +109,10 @@
return snprintf(buf, 3, "t\n");
else if (fmem_state == FMEM_C_STATE)
return snprintf(buf, 3, "c\n");
+#ifdef CONFIG_MEMORY_HOTPLUG
+ else if (fmem_state == FMEM_O_STATE)
+ return snprintf(buf, 3, "o\n");
+#endif
else if (fmem_state == FMEM_UNINITIALIZED)
return snprintf(buf, 15, "uninitialized\n");
return snprintf(buf, 3, "?\n");
@@ -111,6 +128,10 @@
ret = fmem_set_state(FMEM_T_STATE);
else if (!strncmp(buf, "c", 1))
ret = fmem_set_state(FMEM_C_STATE);
+#ifdef CONFIG_MEMORY_HOTPLUG
+ else if (!strncmp(buf, "o", 1))
+ ret = fmem_set_state(FMEM_O_STATE);
+#endif
if (ret)
return ret;
return 1;
@@ -144,8 +165,92 @@
#endif
+#ifdef CONFIG_MEMORY_HOTPLUG
+bool fmem_is_disjoint(unsigned long start_pfn, unsigned long nr_pages)
+{
+ unsigned long fmem_start_pfn, fmem_end_pfn;
+ unsigned long unstable_end_pfn;
+ unsigned long highest_start_pfn, lowest_end_pfn;
+
+ fmem_start_pfn = (fmem_data.phys - fmem_data.reserved_size_low)
+ >> PAGE_SHIFT;
+ fmem_end_pfn = (fmem_data.phys + fmem_data.size +
+ fmem_data.reserved_size_high - 1) >> PAGE_SHIFT;
+ unstable_end_pfn = start_pfn + nr_pages - 1;
+
+ highest_start_pfn = max(fmem_start_pfn, start_pfn);
+ lowest_end_pfn = min(fmem_end_pfn, unstable_end_pfn);
+
+ return lowest_end_pfn < highest_start_pfn;
+}
+
+static int fmem_mem_going_offline_callback(void *arg)
+{
+ struct memory_notify *marg = arg;
+
+ if (fmem_is_disjoint(marg->start_pfn, marg->nr_pages))
+ return 0;
+ return fmem_set_state(FMEM_O_STATE);
+}
+
+static void fmem_mem_online_callback(void *arg)
+{
+ struct memory_notify *marg = arg;
+ int i;
+
+ section_powered_off[marg->start_pfn >> PFN_SECTION_SHIFT] = 0;
+
+ if (fmem_state != FMEM_O_STATE)
+ return;
+
+ for (i = fmem_section_start; i <= fmem_section_end; i++) {
+ if (section_powered_off[i])
+ return;
+ }
+
+ fmem_set_state(FMEM_T_STATE);
+}
+
+static void fmem_mem_offline_callback(void *arg)
+{
+ struct memory_notify *marg = arg;
+
+ section_powered_off[marg->start_pfn >> PFN_SECTION_SHIFT] = 1;
+}
+
+static int fmem_memory_callback(struct notifier_block *self,
+ unsigned long action, void *arg)
+{
+ int ret = 0;
+
+ switch (action) {
+ case MEM_ONLINE:
+ fmem_mem_online_callback(arg);
+ break;
+ case MEM_GOING_OFFLINE:
+ ret = fmem_mem_going_offline_callback(arg);
+ break;
+ case MEM_OFFLINE:
+ fmem_mem_offline_callback(arg);
+ break;
+ case MEM_GOING_ONLINE:
+ case MEM_CANCEL_ONLINE:
+ case MEM_CANCEL_OFFLINE:
+ break;
+ }
+ if (ret)
+ ret = notifier_from_errno(ret);
+ else
+ ret = NOTIFY_OK;
+ return ret;
+}
+#endif
+
static int __init fmem_init(void)
{
+#ifdef CONFIG_MEMORY_HOTPLUG
+ hotplug_memory_notifier(fmem_memory_callback, 0);
+#endif
return platform_driver_register(&fmem_driver);
}
@@ -184,13 +289,25 @@
tmem_enable();
create_sysfs = 1;
goto out_set;
- }
- if (new_state == FMEM_C_STATE) {
+ } else {
ret = -EINVAL;
goto out;
}
}
+#ifdef CONFIG_MEMORY_HOTPLUG
+ if (fmem_state == FMEM_C_STATE && new_state == FMEM_O_STATE) {
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ if (fmem_state == FMEM_O_STATE && new_state == FMEM_C_STATE) {
+ pr_warn("attempting to use powered off memory as fmem\n");
+ ret = -EAGAIN;
+ goto out;
+ }
+#endif
+
if (new_state == FMEM_T_STATE) {
void *v;
v = fmem_map_virtual_area(MT_DEVICE_CACHED);
diff --git a/drivers/usb/gadget/ci13xxx_msm_hsic.c b/drivers/usb/gadget/ci13xxx_msm_hsic.c
index 135c84d..12b6774 100644
--- a/drivers/usb/gadget/ci13xxx_msm_hsic.c
+++ b/drivers/usb/gadget/ci13xxx_msm_hsic.c
@@ -35,14 +35,17 @@
#define MSM_USB_BASE (mhsic->regs)
-#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
-#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
-#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
-#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
-#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
-#define HSIC_CFG_REG 0x30
-#define HSIC_IO_CAL_PER_REG 0x33
-#define HSIC_DBG1_REG 0x38
+#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
+#define USB_PHY_VDD_DIG_VOL_SUSP_MIN 500000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
+#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
+#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
+#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
+#define HSIC_CFG_REG 0x30
+#define HSIC_IO_CAL_PER_REG 0x33
+#define HSIC_DBG1_REG 0x38
struct msm_hsic_per *the_mhsic;
@@ -57,6 +60,11 @@
bool async_int;
void __iomem *regs;
int irq;
+ atomic_t in_lpm;
+ struct wake_lock wlock;
+ struct msm_xo_voter *xo_handle;
+ struct workqueue_struct *wq;
+ struct work_struct suspend_w;
};
static int msm_hsic_init_vddcx(struct msm_hsic_per *mhsic, int init)
@@ -302,6 +310,227 @@
}
}
+
+#ifdef CONFIG_PM_SLEEP
+static int msm_hsic_suspend(struct msm_hsic_per *mhsic)
+{
+ int cnt = 0, ret;
+ u32 val;
+
+ if (atomic_read(&mhsic->in_lpm)) {
+ dev_dbg(mhsic->dev, "%s called while in lpm\n", __func__);
+ return 0;
+ }
+ disable_irq(mhsic->irq);
+
+ /*
+ * PHY may take some time or even fail to enter into low power
+ * mode (LPM). Hence poll for 500 msec and reset the PHY and link
+ * in failure case.
+ */
+ val = readl_relaxed(USB_PORTSC) | PORTSC_PHCD;
+ writel_relaxed(val, USB_PORTSC);
+
+ while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
+ if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
+ break;
+ udelay(1);
+ cnt++;
+ }
+
+ if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
+ dev_err(mhsic->dev, "Unable to suspend PHY\n");
+ msm_hsic_reset(mhsic);
+ }
+
+ /*
+ * PHY has capability to generate interrupt asynchronously in low
+ * power mode (LPM). This interrupt is level triggered. So USB IRQ
+ * line must be disabled till async interrupt enable bit is cleared
+ * in USBCMD register. Assert STP (ULPI interface STOP signal) to
+ * block data communication from PHY.
+ */
+ writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
+ ULPI_STP_CTRL, USB_USBCMD);
+
+ /*
+ * Ensure that hardware is put in low power mode before
+ * clocks are turned OFF and VDD is allowed to minimize.
+ */
+ mb();
+
+ clk_disable(mhsic->iface_clk);
+ clk_disable(mhsic->core_clk);
+ clk_disable(mhsic->phy_clk);
+ clk_disable(mhsic->cal_clk);
+
+ ret = msm_xo_mode_vote(mhsic->xo_handle, MSM_XO_MODE_OFF);
+ if (ret)
+ dev_err(mhsic->dev, "%s failed to devote for TCXO %d\n"
+ , __func__, ret);
+
+ ret = regulator_set_voltage(mhsic->hsic_vddcx,
+ USB_PHY_VDD_DIG_VOL_SUSP_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret < 0)
+ dev_err(mhsic->dev, "unable to set vddcx voltage: min:0.5v max:1.32v\n");
+
+ if (device_may_wakeup(mhsic->dev))
+ enable_irq_wake(mhsic->irq);
+
+ atomic_set(&mhsic->in_lpm, 1);
+ enable_irq(mhsic->irq);
+ wake_unlock(&mhsic->wlock);
+
+ dev_info(mhsic->dev, "HSIC-USB in low power mode\n");
+
+ return 0;
+}
+
+static int msm_hsic_resume(struct msm_hsic_per *mhsic)
+{
+ int cnt = 0, ret;
+ unsigned temp;
+
+ if (!atomic_read(&mhsic->in_lpm)) {
+ dev_dbg(mhsic->dev, "%s called while not in lpm\n", __func__);
+ return 0;
+ }
+
+ wake_lock(&mhsic->wlock);
+ ret = regulator_set_voltage(mhsic->hsic_vddcx,
+ USB_PHY_VDD_DIG_VOL_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret < 0)
+ dev_err(mhsic->dev,
+ "unable to set vddcx voltage: min:1.045v max:1.32v\n");
+
+ ret = msm_xo_mode_vote(mhsic->xo_handle, MSM_XO_MODE_ON);
+ if (ret)
+ dev_err(mhsic->dev, "%s failed to vote for TCXO %d\n",
+ __func__, ret);
+
+ clk_enable(mhsic->iface_clk);
+ clk_enable(mhsic->core_clk);
+ clk_enable(mhsic->phy_clk);
+ clk_enable(mhsic->cal_clk);
+
+ temp = readl_relaxed(USB_USBCMD);
+ temp &= ~ASYNC_INTR_CTRL;
+ temp &= ~ULPI_STP_CTRL;
+ writel_relaxed(temp, USB_USBCMD);
+
+ if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
+ goto skip_phy_resume;
+
+ temp = readl_relaxed(USB_PORTSC) & ~PORTSC_PHCD;
+ writel_relaxed(temp, USB_PORTSC);
+ while (cnt < PHY_RESUME_TIMEOUT_USEC) {
+ if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
+ (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
+ break;
+ udelay(1);
+ cnt++;
+ }
+
+ if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
+ /*
+ * This is a fatal error. Reset the link and
+ * PHY to make hsic working.
+ */
+ dev_err(mhsic->dev, "Unable to resume USB. Reset the hsic\n");
+ msm_hsic_reset(mhsic);
+ }
+skip_phy_resume:
+ if (device_may_wakeup(mhsic->dev))
+ disable_irq_wake(mhsic->irq);
+
+ atomic_set(&mhsic->in_lpm, 0);
+
+ if (mhsic->async_int) {
+ mhsic->async_int = false;
+ enable_irq(mhsic->irq);
+ }
+
+ dev_info(mhsic->dev, "HSIC-USB exited from low power mode\n");
+
+ return 0;
+}
+
+static int msm_hsic_pm_suspend(struct device *dev)
+{
+ struct msm_hsic_per *mhsic = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "MSM HSIC Peripheral PM suspend\n");
+
+ return msm_hsic_suspend(mhsic);
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int msm_hsic_pm_resume(struct device *dev)
+{
+ dev_dbg(dev, "MSM HSIC Peripheral PM resume\n");
+
+ /*
+ * Do not resume hardware as part of system resume,
+ * rather, wait for the ASYNC INT from the h/w
+ */
+ return 0;
+}
+#else
+static int msm_hsic_pm_resume(struct device *dev)
+{
+ struct msm_hsic_per *mhsic = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "MSM HSIC Peripheral PM resume\n");
+
+ return msm_hsic_resume(mhsic);
+}
+#endif
+
+static void msm_hsic_pm_suspend_work(struct work_struct *w)
+{
+ pm_runtime_put_noidle(the_mhsic->dev);
+ pm_runtime_suspend(the_mhsic->dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_RUNTIME
+static int msm_hsic_runtime_idle(struct device *dev)
+{
+ dev_dbg(dev, "MSM HSIC Peripheral runtime idle\n");
+
+ return 0;
+}
+
+static int msm_hsic_runtime_suspend(struct device *dev)
+{
+ struct msm_hsic_per *mhsic = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "MSM HSIC Peripheral runtime suspend\n");
+
+ return msm_hsic_suspend(mhsic);
+}
+
+static int msm_hsic_runtime_resume(struct device *dev)
+{
+ struct msm_hsic_per *mhsic = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "MSM HSIC Peripheral runtime resume\n");
+ pm_runtime_get_noresume(mhsic->dev);
+
+ return msm_hsic_resume(mhsic);
+}
+#endif
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
+ SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
+ msm_hsic_runtime_idle)
+};
+#endif
+
/**
* Dummy match function - will be called only for HSIC msm
* device (msm_device_gadget_hsic_peripheral).
@@ -320,6 +549,15 @@
static irqreturn_t msm_udc_hsic_irq(int irq, void *data)
{
+ struct msm_hsic_per *mhsic = data;
+
+ if (atomic_read(&mhsic->in_lpm)) {
+ disable_irq_nosync(mhsic->irq);
+ mhsic->async_int = true;
+ pm_request_resume(mhsic->dev);
+ return IRQ_HANDLED;
+ }
+
return udc_irq();
}
@@ -338,6 +576,10 @@
dev_dbg(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
msm_hsic_start();
break;
+ case CI13XXX_CONTROLLER_SUSPEND_EVENT:
+ dev_dbg(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
+ queue_work(mhsic->wq, &mhsic->suspend_w);
+ break;
default:
dev_dbg(dev, "unknown ci13xxx_udc event\n");
break;
@@ -378,6 +620,15 @@
goto error;
}
+ mhsic->wq = alloc_workqueue("mhsic_wq", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ if (!mhsic->wq) {
+ pr_err("%s: Unable to create workqueue mhsic wq\n",
+ __func__);
+ ret = -ENOMEM;
+ goto error;
+ }
+ INIT_WORK(&mhsic->suspend_w, msm_hsic_pm_suspend_work);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Unable to get memory resource\n");
@@ -392,6 +643,21 @@
}
dev_info(&pdev->dev, "HSIC Peripheral regs = %p\n", mhsic->regs);
+ mhsic->xo_handle = msm_xo_get(MSM_XO_CXO, "hsic_peripheral");
+ if (IS_ERR(mhsic->xo_handle)) {
+ dev_err(&pdev->dev, "%s not able to get the handle "
+ "to vote for TCXO\n", __func__);
+ ret = PTR_ERR(mhsic->xo_handle);
+ goto unmap;
+ }
+
+ ret = msm_xo_mode_vote(mhsic->xo_handle, MSM_XO_MODE_ON);
+ if (ret) {
+ dev_err(&pdev->dev, "%s failed to vote for TCXO %d\n",
+ __func__, ret);
+ goto free_xo_handle;
+ }
+
ret = msm_hsic_enable_clocks(pdev, mhsic, true);
if (ret) {
@@ -422,16 +688,21 @@
msm_hsic_connect_peripheral(&pdev->dev);
+ device_init_wakeup(&pdev->dev, 1);
+ wake_lock_init(&mhsic->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
+ wake_lock(&mhsic->wlock);
+
ret = request_irq(mhsic->irq, msm_udc_hsic_irq,
- IRQF_SHARED, pdev->name, pdev);
+ IRQF_SHARED, pdev->name, mhsic);
if (ret < 0) {
dev_err(&pdev->dev, "request_irq failed\n");
ret = -ENODEV;
goto udc_remove;
}
- pm_runtime_no_callbacks(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
return 0;
udc_remove:
@@ -440,9 +711,13 @@
msm_hsic_init_vddcx(mhsic, 0);
deinit_clocks:
msm_hsic_enable_clocks(pdev, mhsic, 0);
+ msm_xo_mode_vote(mhsic->xo_handle, MSM_XO_MODE_OFF);
+free_xo_handle:
+ msm_xo_put(mhsic->xo_handle);
unmap:
iounmap(mhsic->regs);
error:
+ destroy_workqueue(mhsic->wq);
kfree(mhsic);
return ret;
}
@@ -452,19 +727,29 @@
struct msm_hsic_per *mhsic = platform_get_drvdata(pdev);
device_init_wakeup(&pdev->dev, 0);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+
msm_hsic_init_vddcx(mhsic, 0);
msm_hsic_enable_clocks(pdev, mhsic, 0);
+ msm_xo_put(mhsic->xo_handle);
+ wake_lock_destroy(&mhsic->wlock);
+ destroy_workqueue(mhsic->wq);
udc_remove();
iounmap(mhsic->regs);
kfree(mhsic);
return 0;
}
+
static struct platform_driver msm_hsic_peripheral_driver = {
.probe = msm_hsic_probe,
.remove = __devexit_p(hsic_msm_remove),
.driver = {
.name = "msm_hsic_peripheral",
+#ifdef CONFIG_PM
+ .pm = &msm_hsic_dev_pm_ops,
+#endif
},
};
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index b64a38a..562b36a 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -3176,6 +3176,9 @@
udc->suspended = 1;
spin_unlock(udc->lock);
udc->driver->suspend(&udc->gadget);
+ if (udc->udc_driver->notify_event)
+ udc->udc_driver->notify_event(udc,
+ CI13XXX_CONTROLLER_SUSPEND_EVENT);
spin_lock(udc->lock);
}
isr_statistics.sli++;
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 13b54c7..684517b 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -129,6 +129,7 @@
#define CI13XXX_CONTROLLER_RESET_EVENT 0
#define CI13XXX_CONTROLLER_CONNECT_EVENT 1
+#define CI13XXX_CONTROLLER_SUSPEND_EVENT 2
void (*notify_event) (struct ci13xxx *udc, unsigned event);
};
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index a9c03ca..579899c 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2078,9 +2078,13 @@
else if (mdp4_overlay_is_rgb_type(req->src.format))
return OVERLAY_PERF_LEVEL1;
- if (req->src.width*req->src.height <= OVERLAY_VGA_SIZE)
- return OVERLAY_PERF_LEVEL4;
- else if (req->src.width*req->src.height <= OVERLAY_720P_TILE_SIZE) {
+ if (req->src.width*req->src.height <= OVERLAY_VGA_SIZE) {
+ if (mfd->mdp_rev >= MDP_REV_42)
+ return OVERLAY_PERF_LEVEL4;
+ else
+ return OVERLAY_PERF_LEVEL3;
+
+ } else if (req->src.width*req->src.height <= OVERLAY_720P_TILE_SIZE) {
u32 max, min;
max = (req->dst_rect.h > req->dst_rect.w) ?
req->dst_rect.h : req->dst_rect.w;
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 599567a..cf7157c 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1258,4 +1258,8 @@
uint8_t vpe_can_use;
};
+#define QCAMERA_NAME "qcamera"
+#define QCAMERA_DEVICE_GROUP_ID 1
+#define QCAMERA_VNODE_GROUP_ID 2
+
#endif /* __LINUX_MSM_CAMERA_H */
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 3e8de2c..9c089e0 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -161,7 +161,6 @@
struct mgmt_cp_pair_device {
bdaddr_t bdaddr;
__u8 io_cap;
- __u8 ssp_cap;
} __packed;
struct mgmt_rp_pair_device {
bdaddr_t bdaddr;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index ca33664..a8e5af9 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -787,6 +787,10 @@
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
struct hci_cp_auth_requested cp;
+
+ /* encrypt must be pending if auth is also pending */
+ set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
+
cp.handle = cpu_to_le16(conn->handle);
hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
sizeof(cp), &cp);
@@ -817,7 +821,7 @@
return 0;
} else if (conn->link_mode & HCI_LM_ENCRYPT) {
return hci_conn_auth(conn, sec_level, auth_type);
- } else if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
+ } else if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
return 0;
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index deba87c..aac934a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2748,7 +2748,7 @@
conn->ssp_mode = (ev->features[0] & 0x01);
/*In case if remote device ssp supported/2.0 device
reduce the security level to MEDIUM if it is HIGH*/
- if (!conn->ssp_mode &&
+ if (!conn->ssp_mode && conn->auth_initiator &&
(conn->pending_sec_level == BT_SECURITY_HIGH))
conn->pending_sec_level = BT_SECURITY_MEDIUM;
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 64d478b..bc68c9f 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1613,9 +1613,8 @@
hci_dev_lock_bh(hdev);
- BT_DBG("SSP Cap is %d", cp->ssp_cap);
io_cap = cp->io_cap;
- if ((cp->ssp_cap == 0) || (io_cap == 0x03)) {
+ if (io_cap == 0x03) {
sec_level = BT_SECURITY_MEDIUM;
auth_type = HCI_AT_DEDICATED_BONDING;
} else {
@@ -1633,6 +1632,7 @@
io_cap = 0x01;
conn = hci_connect(hdev, ACL_LINK, 0, &cp->bdaddr, sec_level,
auth_type);
+ conn->auth_initiator = 1;
}
if (IS_ERR(conn)) {
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 2c52866..d2690c3 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -47,7 +47,20 @@
# If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
# it, because this version is defined in the top level Makefile.
- if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
+ if atag="`git describe --exact-match --abbrev=0 2>/dev/null`"; then
+ # Make sure we're at the tag that matches the Makefile.
+ # If not place the hash of the tag as well for
+ # v2.6.30-rc5-g314aef
+ if [ "x$atag" -ne "x$VERSION" ]; then
+ # If only the short version is requested,
+ # don't bother running further git commands
+ if $short; then
+ echo "+"
+ return
+ fi
+ printf '%s%s' -g "`git show-ref -s --abbrev $atag 2>/dev/null`"
+ fi
+ else
# If only the short version is requested, don't bother
# running further git commands
@@ -55,17 +68,18 @@
echo "+"
return
fi
+ # If we are past a tagged commit (like
+ # "v2.6.30-rc5-302-g72357d5"), we pretty print it and
+ # include the hash of any new tag on top.
+ if atag="`git describe 2>/dev/null`"; then
+ tag="`git describe --abbrev=0 2>/dev/null`"
+ commit="`echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'`"
+ printf '%s%s%s' -g "`git show-ref -s --abbrev $tag 2>/dev/null`" $commit
+ # If we don't have a tag at all we print -g{commitish}.
+ else
+ printf '%s%s' -g $head
+ fi
fi
- # If we are past a tagged commit (like
- # "v2.6.30-rc5-302-g72357d5"), we pretty print it but strip
- # off the v2.6.30-rc5 part because that's in the Makefile.
- if atag="`git describe 2>/dev/null`"; then
- atag="-${atag/v$KERNELVERSION-/}"
- # If we don't have a tag at all we print -g{commitish}.
- else
- atag="-g$head"
- fi
- printf '%s' "$atag"
# Is this git on svn?
if git config --get svn-remote.svn.url >/dev/null; then