Merge "power: pm8921-charger: use trickle time for trickle charging" into msm-3.0
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4690de3..f34719f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1606,6 +1606,10 @@
def_bool n
depends on MEMORY_HOTPLUG
+config FIX_MOVABLE_ZONE
+ def_bool n
+ depends on MEMORY_HOTPLUG
+
config DONT_MAP_HOLE_AFTER_MEMBANK0
def_bool n
depends on SPARSEMEM
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index c9082f0..d377460 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -315,6 +315,8 @@
CONFIG_MT9E013=y
CONFIG_MSM_GEMINI=y
CONFIG_RADIO_TAVARUA=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 2045ff8..76ac964 100755
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -388,11 +388,18 @@
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
+CONFIG_SLUB_DEBUG_ON=y
# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_PAGEALLOC=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
CONFIG_CRYPTO_SHA256=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index fa6475b..714e630 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -221,7 +221,9 @@
CONFIG_LIB80211=m
CONFIG_NETDEVICES=y
CONFIG_WLAN=y
-CONFIG_MSM_RMNET=y
+# CONFIG_MSM_RMNET is not set
+CONFIG_MSM_BAM_DMUX=y
+CONFIG_MSM_RMNET_BAM=y
CONFIG_HOSTAP=m
CONFIG_WIRELESS_EXT=y
CONFIG_WEXT_SPY=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 756603e..486d80e 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1573,6 +1573,16 @@
This bug is not applicable to any ScorpionMP or Scorpion Uni 65nm(SC65U) cores.
+config MSM_BUSPM_DEV
+ tristate "MSM Bus Performance Monitor Kernel Module"
+ depends on (ARCH_MSM8X60 || ARCH_MSM8960)
+ default m
+ help
+ This kernel module is used to mmap() hardware registers for the
+ performance monitors, counters, etc. The module can also be used to
+ allocate physical memory which is used by bus performance hardware to
+ dump performance data.
+
config MSM_RPM_LOG
tristate "MSM Resource Power Manager Log Driver"
depends on DEBUG_FS
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 8693875..292cee2 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -254,6 +254,7 @@
obj-$(CONFIG_MSM_RPM_LOG) += rpm_log.o
obj-$(CONFIG_MSM_XO) += msm_xo.o
obj-$(CONFIG_MSM_BUS_SCALING) += msm_bus/
+obj-$(CONFIG_MSM_BUSPM_DEV) += msm-buspm-dev.o
obj-$(CONFIG_MSM_IOMMU) += iommu.o iommu_dev.o devices-iommu.o iommu_domains.o
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 03307f0..9fb9fb6 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -389,6 +389,14 @@
return rc;
}
+/* TODO: Put the regulator to LPM / HPM in suspend/resume*/
+static int cyttsp_platform_suspend(struct i2c_client *client)
+{
+ msleep(20);
+
+ return CY_OK;
+}
+
static int cyttsp_platform_resume(struct i2c_client *client)
{
/* add any special code to strobe a wakeup pin or chip reset */
@@ -432,6 +440,7 @@
*/
.lp_intrvl = CY_LP_INTRVL_DFLT,
.resume = cyttsp_platform_resume,
+ .suspend = cyttsp_platform_suspend,
.init = cyttsp_platform_init,
.sleep_gpio = -1,
.resout_gpio = -1,
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 1449e34..103a224 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -3341,14 +3341,16 @@
.name = "vdd",
.min_uV = CY_TMA300_VTG_MIN_UV,
.max_uV = CY_TMA300_VTG_MAX_UV,
- .load_uA = CY_TMA300_CURR_24HZ_UA,
+ .hpm_load_uA = CY_TMA300_CURR_24HZ_UA,
+ .lpm_load_uA = CY_TMA300_SLEEP_CURR_UA,
},
/* TODO: Remove after runtime PM is enabled in I2C driver */
{
.name = "vcc_i2c",
.min_uV = CY_I2C_VTG_MIN_UV,
.max_uV = CY_I2C_VTG_MAX_UV,
- .load_uA = CY_I2C_CURR_UA,
+ .hpm_load_uA = CY_I2C_CURR_UA,
+ .lpm_load_uA = CY_I2C_SLEEP_CURR_UA,
},
};
@@ -4696,6 +4698,7 @@
.timer = &msm_timer,
.init_machine = msm8960_cdp_init,
.init_early = msm8960_allocate_memory_regions,
+ .init_very_early = msm8960_early_memory,
MACHINE_END
MACHINE_START(MSM8930_MTP, "QCT MSM8930 MTP")
@@ -4705,6 +4708,7 @@
.timer = &msm_timer,
.init_machine = msm8960_cdp_init,
.init_early = msm8960_allocate_memory_regions,
+ .init_very_early = msm8960_early_memory,
MACHINE_END
MACHINE_START(MSM8930_FLUID, "QCT MSM8930 FLUID")
@@ -4714,5 +4718,6 @@
.timer = &msm_timer,
.init_machine = msm8960_cdp_init,
.init_early = msm8960_allocate_memory_regions,
+ .init_very_early = msm8960_early_memory,
MACHINE_END
#endif
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 61b70cf..d891fdf 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -109,6 +109,10 @@
#include "rpm_resources.h"
#include "acpuclock.h"
#include "pm-boot.h"
+
+#include <linux/ion.h>
+#include <mach/ion.h>
+
#define MSM_SHARED_RAM_PHYS 0x40000000
/* Macros assume PMIC GPIOs start at 0 */
@@ -2624,6 +2628,16 @@
#define USER_SMI_SIZE (MSM_SMI_SIZE - KERNEL_SMI_SIZE)
#define MSM_PMEM_SMIPOOL_SIZE USER_SMI_SIZE
+#define MSM_ION_EBI_SIZE MSM_PMEM_SF_SIZE
+#define MSM_ION_ADSP_SIZE MSM_PMEM_ADSP_SIZE
+#define MSM_ION_SMI_SIZE MSM_USER_SMI_SIZE
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#define MSM_ION_HEAP_NUM 5
+#else
+#define MSM_ION_HEAP_NUM 2
+#endif
+
static unsigned fb_size;
static int __init fb_size_setup(char *p)
{
@@ -2753,6 +2767,7 @@
};
#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
static struct android_pmem_platform_data android_pmem_pdata = {
.name = "pmem",
.allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
@@ -2778,7 +2793,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,
@@ -2802,6 +2817,7 @@
}, \
.num_paths = 1, \
}
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
static struct msm_bus_paths pmem_smi_table[] = {
[0] = PMEM_BUS_WIDTH(0), /* Off */
[1] = PMEM_BUS_WIDTH(1), /* On */
@@ -2846,7 +2862,7 @@
.id = 7,
.dev = { .platform_data = &android_pmem_smipool_pdata },
};
-
+#endif
#endif
#define GPIO_DONGLE_PWR_EN 258
@@ -3193,6 +3209,14 @@
return rc;
}
+/* TODO: Put the regulator to LPM / HPM in suspend/resume*/
+static int cyttsp_platform_suspend(struct i2c_client *client)
+{
+ msleep(20);
+
+ return CY_OK;
+}
+
static int cyttsp_platform_resume(struct i2c_client *client)
{
/* add any special code to strobe a wakeup pin or chip reset */
@@ -3232,6 +3256,7 @@
.resout_gpio = -1,
.irq_gpio = CYTTSP_TS_GPIO_IRQ,
.resume = cyttsp_platform_resume,
+ .suspend = cyttsp_platform_suspend,
.init = cyttsp_platform_init,
};
@@ -3274,6 +3299,7 @@
.resout_gpio = -1,
.irq_gpio = CYTTSP_TS_GPIO_IRQ,
.resume = cyttsp_platform_resume,
+ .suspend = cyttsp_platform_suspend,
.init = cyttsp_platform_init,
.disable_ghost_det = true,
};
@@ -5001,11 +5027,13 @@
&msm_batt_device,
#endif
#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
&android_pmem_device,
&android_pmem_adsp_device,
- &android_pmem_audio_device,
&android_pmem_smipool_device,
#endif
+ &android_pmem_audio_device,
+#endif
#ifdef CONFIG_MSM_ROTATOR
&msm_rotator_device,
#endif
@@ -5098,9 +5126,59 @@
&msm_tsens_device,
&msm_rpm_device,
-
+#ifdef CONFIG_ION_MSM
+ &ion_dev,
+#endif
};
+#ifdef CONFIG_ION_MSM
+struct ion_platform_data ion_pdata = {
+ .nr = MSM_ION_HEAP_NUM,
+ .heaps = {
+ {
+ .id = ION_HEAP_SYSTEM_ID,
+ .type = ION_HEAP_TYPE_SYSTEM,
+ .name = ION_VMALLOC_HEAP_NAME,
+ },
+ {
+ .id = ION_HEAP_SYSTEM_CONTIG_ID,
+ .type = ION_HEAP_TYPE_SYSTEM_CONTIG,
+ .name = ION_KMALLOC_HEAP_NAME,
+ },
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ {
+ .id = ION_HEAP_EBI_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_EBI1_HEAP_NAME,
+ .size = MSM_ION_EBI_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ },
+ {
+ .id = ION_HEAP_ADSP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_ADSP_HEAP_NAME,
+ .size = MSM_ION_ADSP_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ },
+ {
+ .id = ION_HEAP_SMI_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_SMI_HEAP_NAME,
+ .size = MSM_ION_SMI_SIZE,
+ .memory_type = ION_SMI_TYPE,
+ },
+#endif
+ }
+};
+
+struct platform_device ion_dev = {
+ .name = "ion-msm",
+ .id = 1,
+ .dev = { .platform_data = &ion_pdata },
+};
+#endif
+
+
static struct memtype_reserve msm8x60_reserve_table[] __initdata = {
/* Kernel SMI memory pool for video core, used for firmware */
/* and encoder, decoder scratch buffers */
@@ -5128,14 +5206,25 @@
},
};
+static void reserve_ion_memory(void)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+ msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_EBI_SIZE;
+ msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_ADSP_SIZE;
+ msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_SMI_SIZE;
+#endif
+}
+
static void __init size_pmem_devices(void)
{
#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
android_pmem_adsp_pdata.size = pmem_adsp_size;
android_pmem_smipool_pdata.size = MSM_PMEM_SMIPOOL_SIZE;
- android_pmem_audio_pdata.size = MSM_PMEM_AUDIO_SIZE;
android_pmem_pdata.size = pmem_sf_size;
#endif
+ android_pmem_audio_pdata.size = MSM_PMEM_AUDIO_SIZE;
+#endif
}
static void __init reserve_memory_for(struct android_pmem_platform_data *p)
@@ -5146,18 +5235,23 @@
static void __init reserve_pmem_memory(void)
{
#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
reserve_memory_for(&android_pmem_adsp_pdata);
reserve_memory_for(&android_pmem_smipool_pdata);
- reserve_memory_for(&android_pmem_audio_pdata);
reserve_memory_for(&android_pmem_pdata);
+#endif
+ reserve_memory_for(&android_pmem_audio_pdata);
msm8x60_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
#endif
}
+
+
static void __init msm8x60_calculate_reserve_sizes(void)
{
size_pmem_devices();
reserve_pmem_memory();
+ reserve_ion_memory();
}
static int msm8x60_paddr_to_memtype(unsigned int paddr)
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index bbe8748..a0c6878 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5223,7 +5223,7 @@
CLK_LOOKUP("usb_hsic_p_clk", usb_hsic_p_clk.c, NULL),
CLK_LOOKUP("ebi1_msmbus_clk", ebi1_msmbus_clk.c, NULL),
- CLK_LOOKUP("ebi1_clk", ebi1_adm_clk.c, "msm_dmov"),
+ CLK_LOOKUP("mem_clk", ebi1_adm_clk.c, "msm_dmov"),
CLK_LOOKUP("l2_mclk", l2_m_clk, NULL),
CLK_LOOKUP("krait0_mclk", krait0_m_clk, NULL),
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 4e0d3e9..ab4d8c1 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -174,7 +174,7 @@
/* Find max frequency supported within voltage constraints. */
if (!clock->vdd_class) {
- fmax = ULONG_MAX;
+ fmax = INT_MAX;
} else {
for (level = 0; level < ARRAY_SIZE(clock->fmax); level++)
if (clock->fmax[level])
@@ -213,7 +213,7 @@
if (!debugfs_base)
return -ENOMEM;
- strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1);
+ strlcpy(temp, clock->dbg_name, ARRAY_SIZE(temp));
for (ptr = temp; *ptr; ptr++)
*ptr = tolower(*ptr);
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 74e7871..13772ce 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -721,20 +721,19 @@
};
static uint8_t spm_wfi_cmd_sequence[] __initdata = {
- 0x00, 0x03, 0x0B, 0x00,
- 0x0f,
+ 0x00, 0x03, 0x00, 0x0f,
};
static uint8_t spm_power_collapse_without_rpm[] __initdata = {
- 0x30, 0x20, 0x10, 0x00,
- 0x50, 0x03, 0x50, 0x00,
- 0x10, 0x20, 0x30, 0x0f,
+ 0x34, 0x24, 0x14, 0x04,
+ 0x54, 0x03, 0x54, 0x04,
+ 0x14, 0x24, 0x3e, 0x0f,
};
static uint8_t spm_power_collapse_with_rpm[] __initdata = {
- 0x30, 0x20, 0x10, 0x00,
- 0x50, 0x07, 0x50, 0x00,
- 0x10, 0x20, 0x30, 0x0f,
+ 0x34, 0x24, 0x14, 0x04,
+ 0x54, 0x07, 0x54, 0x04,
+ 0x14, 0x24, 0x3e, 0x0f,
};
static struct msm_spm_seq_entry msm_spm_seq_list[] __initdata = {
@@ -759,7 +758,7 @@
[0] = {
.reg_base_addr = MSM_SAW0_BASE,
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
- .reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
+ .reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1001,
.num_modes = ARRAY_SIZE(msm_spm_seq_list),
.modes = msm_spm_seq_list,
},
diff --git a/arch/arm/mach-msm/msm-buspm-dev.c b/arch/arm/mach-msm/msm-buspm-dev.c
new file mode 100644
index 0000000..296418d
--- /dev/null
+++ b/arch/arm/mach-msm/msm-buspm-dev.c
@@ -0,0 +1,256 @@
+/* Copyright (c) 2011, 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.
+ */
+
+/* #define DEBUG */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/memory_alloc.h>
+#include "msm-buspm-dev.h"
+
+#define MSM_BUSPM_DRV_NAME "msm-buspm-dev"
+
+/*
+ * Allocate kernel buffer.
+ * Currently limited to one buffer per file descriptor. If alloc() is
+ * called twice for the same descriptor, the original buffer is freed.
+ * There is also no locking protection so the same descriptor can not be shared.
+ */
+
+static inline void *msm_buspm_dev_get_vaddr(struct file *filp)
+{
+ struct msm_buspm_map_dev *dev = filp->private_data;
+
+ return (dev) ? dev->vaddr : NULL;
+}
+
+static inline unsigned long msm_buspm_dev_get_paddr(struct file *filp)
+{
+ struct msm_buspm_map_dev *dev = filp->private_data;
+
+ return (dev) ? dev->paddr : 0L;
+}
+
+static void msm_buspm_dev_free(struct file *filp)
+{
+ struct msm_buspm_map_dev *dev = filp->private_data;
+
+ if (dev) {
+ pr_debug("freeing memory at 0x%p\n", dev->vaddr);
+ free_contiguous_memory(dev->vaddr);
+ dev->paddr = 0L;
+ dev->vaddr = NULL;
+ }
+}
+
+static int msm_buspm_dev_open(struct inode *inode, struct file *filp)
+{
+ struct msm_buspm_map_dev *dev;
+
+ if (capable(CAP_SYS_ADMIN)) {
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev)
+ filp->private_data = dev;
+ else
+ return -ENOMEM;
+ } else {
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int
+msm_buspm_dev_alloc(struct file *filp, struct buspm_alloc_params data)
+{
+ unsigned long paddr;
+ void *vaddr;
+ struct msm_buspm_map_dev *dev = filp->private_data;
+
+ /* If buffer already allocated, then free it */
+ if (dev->vaddr)
+ msm_buspm_dev_free(filp);
+
+ /* Allocate uncached memory */
+ vaddr = allocate_contiguous_ebi(data.size, PAGE_SIZE, 0);
+ paddr = (vaddr) ? memory_pool_node_paddr(vaddr) : 0L;
+
+ if (vaddr == NULL) {
+ pr_err("allocation of 0x%x bytes failed", data.size);
+ return -ENOMEM;
+ }
+
+ dev->vaddr = vaddr;
+ dev->paddr = paddr;
+ dev->buflen = data.size;
+ filp->f_pos = 0;
+ pr_debug("virt addr = 0x%p\n", dev->vaddr);
+ pr_debug("phys addr = 0x%lx\n", dev->paddr);
+
+ return 0;
+}
+
+static long
+msm_buspm_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ struct buspm_xfer_req xfer;
+ struct buspm_alloc_params alloc_data;
+ unsigned long paddr;
+ int retval = 0;
+ void *buf = msm_buspm_dev_get_vaddr(filp);
+ unsigned char *dbgbuf = buf;
+
+ switch (cmd) {
+ case MSM_BUSPM_IOC_FREE:
+ pr_debug("cmd = 0x%x (FREE)\n", cmd);
+ msm_buspm_dev_free(filp);
+ break;
+
+ case MSM_BUSPM_IOC_ALLOC:
+ pr_debug("cmd = 0x%x (ALLOC)\n", cmd);
+ retval = __get_user(alloc_data.size, (size_t __user *)arg);
+
+ if (retval == 0)
+ retval = msm_buspm_dev_alloc(filp, alloc_data);
+ break;
+
+ case MSM_BUSPM_IOC_RD_PHYS_ADDR:
+ pr_debug("Read Physical Address\n");
+ paddr = msm_buspm_dev_get_paddr(filp);
+ if (paddr == 0L) {
+ retval = -EINVAL;
+ } else {
+ pr_debug("phys addr = 0x%lx\n", paddr);
+ retval = __put_user(paddr,
+ (unsigned long __user *)arg);
+ }
+ break;
+
+ case MSM_BUSPM_IOC_RDBUF:
+ pr_debug("Read Buffer: 0x%x%x%x%x\n",
+ dbgbuf[0], dbgbuf[1], dbgbuf[2], dbgbuf[3]);
+
+ if (!buf) {
+ retval = -EINVAL;
+ break;
+ }
+
+ if (copy_from_user(&xfer, (void __user *)arg, sizeof(xfer))) {
+ retval = -EFAULT;
+ break;
+ }
+
+ if ((xfer.size <= sizeof(buf)) &&
+ (copy_to_user((void __user *)xfer.data, buf,
+ xfer.size))) {
+ retval = -EFAULT;
+ break;
+ }
+ break;
+
+ case MSM_BUSPM_IOC_WRBUF:
+ pr_debug("Write Buffer\n");
+
+ if (!buf) {
+ retval = -EINVAL;
+ break;
+ }
+
+ if (copy_from_user(&xfer, (void __user *)arg, sizeof(xfer))) {
+ retval = -EFAULT;
+ break;
+ }
+
+ if ((sizeof(buf) <= xfer.size) &&
+ (copy_from_user(buf, (void __user *)xfer.data,
+ xfer.size))) {
+ retval = -EFAULT;
+ break;
+ }
+ break;
+
+ default:
+ pr_debug("Unknown command 0x%x\n", cmd);
+ retval = -EINVAL;
+ break;
+ }
+
+ return retval;
+}
+
+static int msm_buspm_dev_release(struct inode *inode, struct file *filp)
+{
+ struct msm_buspm_map_dev *dev = filp->private_data;
+
+ msm_buspm_dev_free(filp);
+ kfree(dev);
+ filp->private_data = NULL;
+
+ return 0;
+}
+
+static int msm_buspm_dev_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ pr_debug("vma = 0x%p\n", vma);
+
+ /* Mappings are uncached */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+ return -EFAULT;
+
+ return 0;
+}
+
+static const struct file_operations msm_buspm_dev_fops = {
+ .owner = THIS_MODULE,
+ .mmap = msm_buspm_dev_mmap,
+ .open = msm_buspm_dev_open,
+ .unlocked_ioctl = msm_buspm_dev_ioctl,
+ .llseek = noop_llseek,
+ .release = msm_buspm_dev_release,
+};
+
+struct miscdevice msm_buspm_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = MSM_BUSPM_DRV_NAME,
+ .fops = &msm_buspm_dev_fops,
+};
+
+static int __init msm_buspm_dev_init(void)
+{
+ int ret = 0;
+
+ ret = misc_register(&msm_buspm_misc);
+ if (ret < 0)
+ pr_err("%s: Cannot register misc device\n", __func__);
+
+ return ret;
+}
+
+static void __exit msm_buspm_dev_exit(void)
+{
+ misc_deregister(&msm_buspm_misc);
+}
+module_init(msm_buspm_dev_init);
+module_exit(msm_buspm_dev_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:"MSM_BUSPM_DRV_NAME);
diff --git a/arch/arm/mach-msm/msm-buspm-dev.h b/arch/arm/mach-msm/msm-buspm-dev.h
new file mode 100644
index 0000000..5839087
--- /dev/null
+++ b/arch/arm/mach-msm/msm-buspm-dev.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2011, 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 __MSM_BUSPM_DEV_H__
+#define __MSM_BUSPM_DEV_H__
+
+#include <linux/ioctl.h>
+
+struct msm_buspm_map_dev {
+ void *vaddr;
+ unsigned long paddr;
+ size_t buflen;
+};
+
+/* Read/write data into kernel buffer */
+struct buspm_xfer_req {
+ int size; /* Size of this request, in bytes */
+ void *data; /* Data buffer to transfer data to/from */
+};
+
+struct buspm_alloc_params {
+ int size;
+};
+
+#define MSM_BUSPM_IOC_MAGIC 'p'
+
+#define MSM_BUSPM_IOC_FREE \
+ _IOW(MSM_BUSPM_IOC_MAGIC, 0, void *)
+
+#define MSM_BUSPM_IOC_ALLOC \
+ _IOW(MSM_BUSPM_IOC_MAGIC, 1, size_t)
+
+#define MSM_BUSPM_IOC_RDBUF \
+ _IOW(MSM_BUSPM_IOC_MAGIC, 2, struct buspm_xfer_req)
+
+#define MSM_BUSPM_IOC_WRBUF \
+ _IOW(MSM_BUSPM_IOC_MAGIC, 3, struct buspm_xfer_req)
+
+#define MSM_BUSPM_IOC_RD_PHYS_ADDR \
+ _IOR(MSM_BUSPM_IOC_MAGIC, 4, unsigned long)
+#endif
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index b597fb1..1df3c23 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -336,6 +336,7 @@
struct msm_clock *clock;
struct msm_clock_percpu_data *clock_state, *gpt_state;
unsigned long irq_flags;
+ struct irq_chip *chip;
clock = clockevent_to_clock(evt);
clock_state = &__get_cpu_var(msm_clocks_percpu)[clock->index];
@@ -355,11 +356,9 @@
get_cpu_var(msm_active_clock) = clock;
put_cpu_var(msm_active_clock);
__raw_writel(TIMER_ENABLE_EN, clock->regbase + TIMER_ENABLE);
- if (irq_get_chip(clock->irq.irq) &&
- irq_get_chip(clock->irq.irq)->irq_unmask) {
- irq_get_chip(clock->irq.irq)->irq_unmask(
- irq_get_irq_data(clock->irq.irq));
- }
+ chip = irq_get_chip(clock->irq.irq);
+ if (chip && chip->irq_unmask)
+ chip->irq_unmask(irq_get_irq_data(clock->irq.irq));
if (clock != &msm_clocks[MSM_CLOCK_GPT])
__raw_writel(TIMER_ENABLE_EN,
msm_clocks[MSM_CLOCK_GPT].regbase +
@@ -375,11 +374,9 @@
msm_read_timer_count(clock, LOCAL_TIMER) +
clock_state->sleep_offset;
__raw_writel(0, clock->regbase + TIMER_MATCH_VAL);
- if (irq_get_chip(clock->irq.irq) &&
- irq_get_chip(clock->irq.irq)->irq_mask) {
- irq_get_chip(clock->irq.irq)->irq_mask(
- irq_get_irq_data(clock->irq.irq));
- }
+ chip = irq_get_chip(clock->irq.irq);
+ if (chip && chip->irq_mask)
+ chip->irq_mask(irq_get_irq_data(clock->irq.irq));
if (!is_smp() || clock != &msm_clocks[MSM_CLOCK_DGT]
|| smp_processor_id())
@@ -973,6 +970,7 @@
{
int i;
int res;
+ struct irq_chip *chip;
struct msm_clock *dgt = &msm_clocks[MSM_CLOCK_DGT];
struct msm_clock *gpt = &msm_clocks[MSM_CLOCK_GPT];
@@ -1056,8 +1054,9 @@
printk(KERN_ERR "msm_timer_init: setup_irq "
"failed for %s\n", cs->name);
- irq_get_chip(clock->irq.irq)->irq_mask(irq_get_irq_data(
- clock->irq.irq));
+ chip = irq_get_chip(clock->irq.irq);
+ if (chip && chip->irq_mask)
+ chip->irq_mask(irq_get_irq_data(clock->irq.irq));
clockevents_register_device(ce);
}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 350e5a9..aeaa173 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -791,6 +791,19 @@
{
int i, j, highmem = 0;
+#if (defined CONFIG_HIGHMEM) && (defined CONFIG_FIX_MOVABLE_ZONE)
+
+/* For now, we must ensure that a small highmem zone exists
+ * after most of it is transformed into the movable zone.
+ */
+#define MIN_HIGHMEM_SIZE (5 * SECTION_SIZE)
+ void *v_movable_start;
+
+ v_movable_start = __va(movable_reserved_start) - MIN_HIGHMEM_SIZE;
+
+ if (vmalloc_min > v_movable_start)
+ vmalloc_min = v_movable_start;
+#endif
for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
struct membank *bank = &meminfo.bank[j];
*bank = meminfo.bank[i];
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index f6097ac..71dea89 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -101,13 +101,27 @@
struct scatterlist *ion_carveout_heap_map_dma(struct ion_heap *heap,
struct ion_buffer *buffer)
{
- return ERR_PTR(-EINVAL);
+ struct scatterlist *sglist;
+ struct page *page = phys_to_page(buffer->priv_phys);
+
+ if (page == NULL)
+ return NULL;
+
+ sglist = vmalloc(sizeof(struct scatterlist));
+ if (!sglist)
+ return ERR_PTR(-ENOMEM);
+
+ sg_init_table(sglist, 1);
+ sg_set_page(sglist, page, buffer->size, 0);
+
+ return sglist;
}
void ion_carveout_heap_unmap_dma(struct ion_heap *heap,
struct ion_buffer *buffer)
{
- return;
+ if (buffer->sglist)
+ vfree(buffer->sglist);
}
void *ion_carveout_heap_map_kernel(struct ion_heap *heap,
@@ -192,6 +206,8 @@
.map_user = ion_carveout_heap_map_user,
.map_kernel = ion_carveout_heap_map_kernel,
.unmap_kernel = ion_carveout_heap_unmap_kernel,
+ .map_dma = ion_carveout_heap_map_dma,
+ .unmap_dma = ion_carveout_heap_unmap_dma,
.cache_op = ion_carveout_cache_ops,
.get_allocated = ion_carveout_get_allocated,
.get_total = ion_carveout_get_total,
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 6cd57b3..9e14247 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -411,7 +411,7 @@
unsigned int sizedwords;
if (device->state & KGSL_STATE_HUNG) {
- return -EINVAL;
+ result = -EINVAL;
goto error;
}
if (numibs != 1) {
diff --git a/drivers/input/touchscreen/cyttsp-i2c.c b/drivers/input/touchscreen/cyttsp-i2c.c
index a3446a3..aefce3e 100644
--- a/drivers/input/touchscreen/cyttsp-i2c.c
+++ b/drivers/input/touchscreen/cyttsp-i2c.c
@@ -2419,7 +2419,7 @@
}
rc = regulator_set_optimum_mode(ts->vdd[i],
- reg_info[i].load_uA);
+ reg_info[i].hpm_load_uA);
if (rc < 0) {
pr_err("%s: regulator_set_optimum_mode failed rc=%d\n",
__func__, rc);
@@ -2838,6 +2838,57 @@
}
#ifdef CONFIG_PM
+static int cyttsp_regulator_lpm(struct cyttsp *ts, bool on)
+{
+ int rc = 0, i;
+ const struct cyttsp_regulator *reg_info =
+ ts->platform_data->regulator_info;
+ u8 num_reg = ts->platform_data->num_regulators;
+
+ if (on == false)
+ goto regulator_hpm;
+
+ for (i = 0; i < num_reg; i++) {
+ rc = regulator_set_optimum_mode(ts->vdd[i],
+ reg_info[i].lpm_load_uA);
+ if (rc < 0) {
+ pr_err("%s: regulator_set_optimum failed rc = %d\n",
+ __func__, rc);
+ goto fail_regulator_lpm;
+ }
+
+ }
+
+ return 0;
+
+regulator_hpm:
+ for (i = 0; i < num_reg; i++) {
+ rc = regulator_set_optimum_mode(ts->vdd[i],
+ reg_info[i].hpm_load_uA);
+ if (rc < 0) {
+ pr_err("%s: regulator_set_optimum failed"
+ "rc = %d\n", __func__, rc);
+ goto fail_regulator_hpm;
+ }
+ }
+
+ return 0;
+
+fail_regulator_lpm:
+ while (i--)
+ regulator_set_optimum_mode(ts->vdd[i],
+ reg_info[i].hpm_load_uA);
+
+ return rc;
+
+fail_regulator_hpm:
+ while (i--)
+ regulator_set_optimum_mode(ts->vdd[i],
+ reg_info[i].lpm_load_uA);
+
+ return rc;
+}
+
/* Function to manage power-on resume */
static int cyttsp_resume(struct device *dev)
{
@@ -2865,6 +2916,8 @@
(ts->platform_data->power_state != CY_ACTIVE_STATE)) {
if (ts->platform_data->resume)
retval = ts->platform_data->resume(ts->client);
+ else
+ retval = cyttsp_regulator_lpm(ts, false);
/* take TTSP device out of bootloader mode;
* switch back to TrueTouch operational mode */
if (!(retval < CY_OK)) {
@@ -2948,14 +3001,23 @@
if (!(retval < CY_OK)) {
if (ts->platform_data->use_sleep &&
(ts->platform_data->power_state == CY_ACTIVE_STATE)) {
+ if (ts->platform_data->suspend) {
+ retval =
+ ts->platform_data->suspend(ts->client);
+ } else {
+ retval = cyttsp_regulator_lpm(ts, true);
+ }
if (ts->platform_data->use_sleep & CY_USE_DEEP_SLEEP_SEL)
sleep_mode = CY_DEEP_SLEEP_MODE;
else
sleep_mode = CY_LOW_PWR_MODE;
- retval = i2c_smbus_write_i2c_block_data(ts->client,
- CY_REG_BASE,
- sizeof(sleep_mode), &sleep_mode);
+ if (!(retval < CY_OK)) {
+ retval =
+ i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ sizeof(sleep_mode), &sleep_mode);
+ }
}
}
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index a09514b..2bf95a0 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -126,6 +126,10 @@
idx = msm_mctl_out_type_to_inst_index(
p_mctl->sync.pcam_sync, msg_type);
+ if (idx < 0) {
+ pr_err("%s Invalid instance. returning\n", __func__);
+ return -EINVAL;
+ }
pcam_inst = p_mctl->sync.pcam_sync->dev_inst[idx];
vb = msm_mctl_buf_find(p_mctl, pcam_inst,
del_buf, msg_type, fbuf);
@@ -192,27 +196,52 @@
}
static int msm_mctl_pp_get_phy_addr(
+ struct msm_cam_v4l2_dev_inst *pcam_inst,
uint32_t frame_handle,
struct msm_pp_frame *pp_frame)
{
struct msm_frame_buffer *vb = NULL;
struct videobuf2_contig_pmem *mem;
+ int i, buf_idx = 0;
vb = (struct msm_frame_buffer *)frame_handle;
- mem = vb2_plane_cookie(&vb->vidbuf, 0);
+ buf_idx = vb->vidbuf.v4l2_buf.index;
memset(pp_frame, 0, sizeof(struct msm_pp_frame));
pp_frame->handle = (uint32_t)vb;
pp_frame->frame_id = vb->vidbuf.v4l2_buf.sequence;
- pp_frame->image_type = (unsigned short)mem->path;
pp_frame->timestamp = vb->vidbuf.v4l2_buf.timestamp;
- /* hard coded for now. Will need to expand to MP case */
- pp_frame->num_planes = 1;
- pp_frame->sp.addr_offset = mem->addr_offset;
- pp_frame->sp.phy_addr = videobuf2_to_pmem_contig(&vb->vidbuf, 0);
- pp_frame->sp.y_off = 0;
- pp_frame->sp.cbcr_off = mem->offset.sp_off.cbcr_off;
- pp_frame->sp.length = mem->size;
- pp_frame->sp.fd = (int)mem->vaddr;
+ /* Get the cookie for 1st plane and store the path.
+ * Also use this to check the number of planes in
+ * this buffer.*/
+ mem = vb2_plane_cookie(&vb->vidbuf, 0);
+ pp_frame->image_type = (unsigned short)mem->path;
+ if (mem->buffer_type == VIDEOBUF2_SINGLE_PLANE) {
+ pp_frame->num_planes = 1;
+ pp_frame->sp.addr_offset = mem->addr_offset;
+ pp_frame->sp.phy_addr =
+ videobuf2_to_pmem_contig(&vb->vidbuf, 0);
+ pp_frame->sp.y_off = 0;
+ pp_frame->sp.cbcr_off = mem->offset.sp_off.cbcr_off;
+ pp_frame->sp.length = mem->size;
+ pp_frame->sp.fd = (int)mem->vaddr;
+ } else {
+ pp_frame->num_planes = pcam_inst->plane_info.num_planes;
+ for (i = 0; i < pp_frame->num_planes; i++) {
+ mem = vb2_plane_cookie(&vb->vidbuf, i);
+ pp_frame->mp[i].addr_offset = mem->addr_offset;
+ pp_frame->mp[i].phy_addr =
+ videobuf2_to_pmem_contig(&vb->vidbuf, i);
+ pp_frame->mp[i].data_offset =
+ pcam_inst->buf_offset[buf_idx][i].data_offset;
+ pp_frame->mp[i].fd = (int)mem->vaddr;
+ pp_frame->mp[i].length = mem->size;
+ D("%s frame id %d buffer %d plane %d phy addr 0x%x"
+ " fd %d length %d\n", __func__,
+ pp_frame->frame_id, buf_idx, i,
+ (uint32_t)pp_frame->mp[i].phy_addr,
+ pp_frame->mp[i].fd, pp_frame->mp[i].length);
+ }
+ }
return 0;
}
@@ -235,12 +264,38 @@
return 0;
}
+static int msm_mctl_pp_path_to_inst_index(struct msm_cam_v4l2_device *pcam,
+ int out_type)
+{
+ int image_mode;
+ switch (out_type) {
+ case OUTPUT_TYPE_P:
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
+ break;
+ case OUTPUT_TYPE_V:
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
+ break;
+ case OUTPUT_TYPE_S:
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
+ break;
+ default:
+ image_mode = -1;
+ break;
+ }
+ if ((image_mode >= 0) && pcam->dev_inst_map[image_mode])
+ return pcam->dev_inst_map[image_mode]->my_index;
+ else
+ return -EINVAL;
+}
+
int msm_mctl_pp_proc_vpe_cmd(
struct msm_cam_media_controller *p_mctl,
struct msm_mctl_pp_cmd *pp_cmd)
{
- int rc = 0;
+ int rc = 0, idx;
void __user *argp = (void __user *)pp_cmd->value;
+ struct msm_cam_v4l2_dev_inst *pcam_inst;
+
switch (pp_cmd->id) {
case VPE_CMD_INIT:
case VPE_CMD_DEINIT:
@@ -422,15 +477,27 @@
zoom->pp_frame_cmd.cookie,
zoom->pp_frame_cmd.vpe_output_action,
zoom->pp_frame_cmd.path);
-
+ idx = msm_mctl_pp_path_to_inst_index(p_mctl->sync.pcam_sync,
+ zoom->pp_frame_cmd.path);
+ if (idx < 0) {
+ pr_err("%s Invalid path, returning\n", __func__);
+ kfree(zoom);
+ return idx;
+ }
+ pcam_inst = p_mctl->sync.pcam_sync->dev_inst[idx];
+ if (!pcam_inst) {
+ pr_err("%s Invalid instance, returning\n", __func__);
+ kfree(zoom);
+ return -EINVAL;
+ }
zoom->user_cmd = pp_cmd->id;
- rc = msm_mctl_pp_get_phy_addr(
+ rc = msm_mctl_pp_get_phy_addr(pcam_inst,
zoom->pp_frame_cmd.src_buf_handle, &zoom->src_frame);
if (rc) {
kfree(zoom);
break;
}
- rc = msm_mctl_pp_get_phy_addr(
+ rc = msm_mctl_pp_get_phy_addr(pcam_inst,
zoom->pp_frame_cmd.dest_buf_handle, &zoom->dest_frame);
if (rc) {
kfree(zoom);
diff --git a/drivers/mfd/wcd9310-core.c b/drivers/mfd/wcd9310-core.c
index aef0754..8eca7aa 100644
--- a/drivers/mfd/wcd9310-core.c
+++ b/drivers/mfd/wcd9310-core.c
@@ -573,6 +573,7 @@
int ret = 0;
int sgla_retry_cnt;
+ dev_info(&slim->dev, "Initialized slim device %s\n", slim->name);
pdata = slim->dev.platform_data;
if (!pdata) {
@@ -727,17 +728,35 @@
.remove = tabla_slim_remove,
.id_table = slimtest_id,
};
+
+static const struct slim_device_id slimtest2x_id[] = {
+ {"tabla2x-slim", 0},
+ {}
+};
+
+static struct slim_driver tabla2x_slim_driver = {
+ .driver = {
+ .name = "tabla2x-slim",
+ .owner = THIS_MODULE,
+ },
+ .probe = tabla_slim_probe,
+ .remove = tabla_slim_remove,
+ .id_table = slimtest2x_id,
+};
+
static int __init tabla_init(void)
{
- int ret;
+ int ret1, ret2;
- ret = slim_driver_register(&tabla_slim_driver);
- if (ret != 0) {
- pr_err("Failed to register tabla SB driver: %d\n", ret);
- goto err;
- }
-err:
- return ret;
+ ret1 = slim_driver_register(&tabla_slim_driver);
+ if (ret1 != 0)
+ pr_err("Failed to register tabla SB driver: %d\n", ret1);
+
+ ret2 = slim_driver_register(&tabla2x_slim_driver);
+ if (ret2 != 0)
+ pr_err("Failed to register tabla2x SB driver: %d\n", ret2);
+
+ return (ret1 && ret2) ? -1 : 0;
}
module_init(tabla_init);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index c1df55e..31c4172 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -132,6 +132,8 @@
static void
msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
u32 c);
+static inline void msmsdcc_delay(struct msmsdcc_host *host);
+
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
@@ -207,77 +209,83 @@
* @host - Pointer to driver's host structure
*
*/
-static void msmsdcc_soft_reset_and_restore(struct msmsdcc_host *host)
+static void msmsdcc_soft_reset(struct msmsdcc_host *host)
{
- if (host->is_sps_mode) {
- /* Reset DML first */
- msmsdcc_dml_reset(host);
- /*
- * delay the SPS pipe reset in thread context as
- * sps_connect/sps_disconnect APIs can be called
- * only from non-atomic context.
- */
- host->sps.pipe_reset_pending = true;
- }
/*
* Reset SDCC controller's DPSM (data path state machine
* and CPSM (command path state machine).
*/
- mb();
writel_relaxed(0, host->base + MMCICOMMAND);
+ msmsdcc_delay(host);
writel_relaxed(0, host->base + MMCIDATACTRL);
- mb();
+ msmsdcc_delay(host);
+}
- pr_debug("%s: Applied soft reset to Controller\n",
- mmc_hostname(host->mmc));
+static void msmsdcc_hard_reset(struct msmsdcc_host *host)
+{
+ int ret;
- if (host->is_sps_mode)
- msmsdcc_dml_init(host);
+ /* Reset the controller */
+ ret = clk_reset(host->clk, CLK_RESET_ASSERT);
+ if (ret)
+ pr_err("%s: Clock assert failed at %u Hz"
+ " with err %d\n", mmc_hostname(host->mmc),
+ host->clk_rate, ret);
+
+ ret = clk_reset(host->clk, CLK_RESET_DEASSERT);
+ if (ret)
+ pr_err("%s: Clock deassert failed at %u Hz"
+ " with err %d\n", mmc_hostname(host->mmc),
+ host->clk_rate, ret);
+
+ /* Give some delay for clock reset to propogate to controller */
+ msmsdcc_delay(host);
}
static void msmsdcc_reset_and_restore(struct msmsdcc_host *host)
{
if (host->plat->sdcc_v4_sup) {
- msmsdcc_soft_reset_and_restore(host);
+ if (host->is_sps_mode) {
+ /* Reset DML first */
+ msmsdcc_dml_reset(host);
+ /*
+ * delay the SPS pipe reset in thread context as
+ * sps_connect/sps_disconnect APIs can be called
+ * only from non-atomic context.
+ */
+ host->sps.pipe_reset_pending = true;
+ }
+ mb();
+ msmsdcc_soft_reset(host);
+
+ pr_debug("%s: Applied soft reset to Controller\n",
+ mmc_hostname(host->mmc));
+
+ if (host->is_sps_mode)
+ msmsdcc_dml_init(host);
} else {
/* Give Clock reset (hard reset) to controller */
u32 mci_clk = 0;
u32 mci_mask0 = 0;
- int ret;
/* Save the controller state */
mci_clk = readl_relaxed(host->base + MMCICLOCK);
mci_mask0 = readl_relaxed(host->base + MMCIMASK0);
-
mb();
- /* Reset the controller */
- ret = clk_reset(host->clk, CLK_RESET_ASSERT);
- if (ret)
- pr_err("%s: Clock assert failed at %u Hz"
- " with err %d\n", mmc_hostname(host->mmc),
- host->clk_rate, ret);
- ret = clk_reset(host->clk, CLK_RESET_DEASSERT);
- if (ret)
- pr_err("%s: Clock deassert failed at %u Hz"
- " with err %d\n", mmc_hostname(host->mmc),
- host->clk_rate, ret);
-
+ msmsdcc_hard_reset(host);
pr_debug("%s: Controller has been reinitialized\n",
mmc_hostname(host->mmc));
- mb();
/* Restore the contoller state */
writel_relaxed(host->pwr, host->base + MMCIPOWER);
+ msmsdcc_delay(host);
writel_relaxed(mci_clk, host->base + MMCICLOCK);
+ msmsdcc_delay(host);
writel_relaxed(mci_mask0, host->base + MMCIMASK0);
- ret = clk_set_rate(host->clk, host->clk_rate);
- if (ret)
- pr_err("%s: Failed to set clk rate %u Hz. err %d\n",
- mmc_hostname(host->mmc),
- host->clk_rate, ret);
- mb();
+ mb(); /* no delay required after writing to MASK0 register */
}
+
if (host->dummy_52_needed)
host->dummy_52_needed = 0;
}
@@ -310,8 +318,6 @@
return retval;
}
-static inline void msmsdcc_delay(struct msmsdcc_host *host);
-
static void
msmsdcc_stop_data(struct msmsdcc_host *host)
{
@@ -361,8 +367,13 @@
msmsdcc_start_command_exec(struct msmsdcc_host *host, u32 arg, u32 c)
{
writel_relaxed(arg, host->base + MMCIARGUMENT);
- msmsdcc_delay(host);
writel_relaxed(c, host->base + MMCICOMMAND);
+ /*
+ * As after sending the command, we don't write any of the
+ * controller registers and just wait for the
+ * CMD_RESPOND_END/CMD_SENT/Command failure notication
+ * from Controller.
+ */
mb();
}
@@ -374,7 +385,6 @@
writel_relaxed(host->cmd_timeout, host->base + MMCIDATATIMER);
writel_relaxed((unsigned int)host->curr.xfer_size,
host->base + MMCIDATALENGTH);
- msmsdcc_delay(host); /* Allow data parms to be applied */
writel_relaxed(host->cmd_datactrl, host->base + MMCIDATACTRL);
msmsdcc_delay(host); /* Force delay prior to ADM or command */
@@ -607,6 +617,7 @@
host->dummy_52_sent = 1;
msmsdcc_start_command(host, &dummy52cmd,
MCI_CPSM_PROGENA);
+ spin_unlock_irqrestore(&host->lock, flags);
return;
}
msmsdcc_stop_data(host);
@@ -931,7 +942,7 @@
}
}
- if (host->prog_scan && (cmd->opcode == 12)) {
+ if ((cmd->flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
*c |= MCI_CPSM_PROGENA;
host->prog_enable = 1;
}
@@ -1013,6 +1024,8 @@
if (data->flags & MMC_DATA_READ)
datactrl |= (MCI_DPSM_DIRECTION | MCI_RX_DATA_PEND);
+ else if (data->flags & MMC_DATA_WRITE)
+ datactrl |= MCI_DATA_PEND;
clks = (unsigned long long)data->timeout_ns * host->clk_rate;
do_div(clks, 1000000000UL);
@@ -1029,8 +1042,6 @@
host->dma.hdr.exec_func = msmsdcc_dma_exec_func;
host->dma.hdr.user = (void *)host;
host->dma.busy = 1;
- if ((data->flags & MMC_DATA_WRITE) && !host->curr.mrq->sbc)
- host->prog_scan = 1;
if (cmd) {
msmsdcc_start_command_deferred(host, cmd, &c);
@@ -1043,8 +1054,6 @@
msm_dmov_enqueue_cmd_ext(host->dma.channel, &host->dma.hdr);
} else {
/* SPS-BAM mode or PIO mode */
- if ((data->flags & MMC_DATA_WRITE) && !host->curr.mrq->sbc)
- host->prog_scan = 1;
writel_relaxed(timeout, base + MMCIDATATIMER);
writel_relaxed(host->curr.xfer_size, base + MMCIDATALENGTH);
@@ -1052,8 +1061,14 @@
writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
(~(MCI_IRQ_PIO))) | pio_irqmask,
host->base + MMCIMASK0);
- msmsdcc_delay(host); /* Allow parms to be applied */
writel_relaxed(datactrl, base + MMCIDATACTRL);
+ /*
+ * We don't need delay after writing to DATA_CTRL register
+ * if we are not writing to CMD register immediately after
+ * this. As we already have delay before sending the
+ * command, we just need mb() here.
+ */
+ mb();
if (cmd) {
msmsdcc_delay(host); /* Delay between data/command */
@@ -1239,8 +1254,10 @@
(~(MCI_IRQ_PIO))) | MCI_RXDATAAVLBLMASK,
host->base + MMCIMASK0);
if (!host->curr.xfer_remain) {
- /* Delay needed (same port was just written) */
- msmsdcc_delay(host);
+ /*
+ * back to back write to MASK0 register don't need
+ * synchronization delay.
+ */
writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
(~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
}
@@ -1329,16 +1346,12 @@
} else { /* host->data == NULL */
if (!cmd->error && host->prog_enable) {
if (status & MCI_PROGDONE) {
- host->prog_scan = 0;
host->prog_enable = 0;
- msmsdcc_request_end(host, cmd->mrq);
+ msmsdcc_request_end(host, cmd->mrq);
} else
host->curr.cmd = cmd;
} else {
- if (host->prog_enable) {
- host->prog_scan = 0;
- host->prog_enable = 0;
- }
+ host->prog_enable = 0;
if (host->dummy_52_needed)
host->dummy_52_needed = 0;
if (cmd->data && cmd->error)
@@ -1351,9 +1364,6 @@
msmsdcc_start_command(host, host->curr.mrq->cmd, 0);
else
msmsdcc_request_start(host, host->curr.mrq);
- } else if (cmd->data) {
- if (!(cmd->data->flags & MMC_DATA_READ))
- msmsdcc_start_data(host, cmd->data, NULL, 0);
}
}
@@ -1560,9 +1570,9 @@
static void
msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq)
{
- if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
+ if (mrq->data) {
/* Queue/read data, daisy-chain command when data starts */
- if (mrq->sbc)
+ if (mrq->sbc && (mrq->data->flags & MMC_DATA_READ))
msmsdcc_start_data(host, mrq->data, mrq->sbc, 0);
else
msmsdcc_start_data(host, mrq->data, mrq->cmd, 0);
@@ -1922,7 +1932,9 @@
if (!IS_ERR(host->pclk))
clk_enable(host->pclk);
clk_enable(host->clk);
+ msmsdcc_delay(host);
} else {
+ msmsdcc_delay(host);
clk_disable(host->clk);
if (!IS_ERR(host->pclk))
clk_disable(host->pclk);
@@ -2120,6 +2132,10 @@
writel_relaxed(host->mci_irqenable,
host->base + MMCIMASK0);
}
+ } else {
+ writel_relaxed(host->mci_irqenable,
+ host->base + MMCIMASK0);
+ mb();
}
}
spin_unlock_irqrestore(&host->lock, flags);
@@ -2222,6 +2238,7 @@
msmsdcc_setup_pins(host, false);
break;
case MMC_POWER_UP:
+ /* writing PWR_UP bit is redundant */
pwr |= MCI_PWR_UP;
if (host->sdcc_irq_disabled) {
if (host->plat->cfg_mpm_sdiowakeup)
@@ -2255,7 +2272,7 @@
if (host->pwr != pwr) {
host->pwr = pwr;
writel_relaxed(pwr, host->base + MMCIPOWER);
- mb();
+ msmsdcc_delay(host);
}
if (!host->clks_on) {
/* force the clocks to be off */
@@ -2279,7 +2296,7 @@
writel_relaxed(MCI_SDIOINTMASK,
host->base + MMCIMASK0);
}
- msmsdcc_delay(host);
+ mb();
}
msmsdcc_setup_clocks(host, false);
host->clks_on = 0;
@@ -2299,7 +2316,7 @@
else
clk &= ~MCI_CLK_PWRSAVE;
writel_relaxed(clk, host->base + MMCICLOCK);
- mb();
+ msmsdcc_delay(host);
return 0;
}
@@ -2446,7 +2463,7 @@
/* Stop SD CLK output. */
writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
-
+ msmsdcc_delay(host);
spin_unlock_irqrestore(&host->lock, flags);
/*
@@ -2460,6 +2477,7 @@
spin_lock_irqsave(&host->lock, flags);
writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
IO_PAD_PWR_SWITCH), host->base + MMCICLOCK);
+ msmsdcc_delay(host);
host->io_pad_pwr_switch = 1;
spin_unlock_irqrestore(&host->lock, flags);
@@ -2470,6 +2488,7 @@
/* Start SD CLK output. */
writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+ msmsdcc_delay(host);
spin_unlock_irqrestore(&host->lock, flags);
/*
@@ -2683,6 +2702,7 @@
*/
writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+ msmsdcc_delay(host);
/* first of all reset the tuning block */
rc = msmsdcc_init_cm_sdc4_dll(host);
if (rc)
@@ -2757,6 +2777,7 @@
/* re-enable PWESAVE */
writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+ msmsdcc_delay(host);
host->cmd19_tuning_in_progress = 0;
return rc;
}
@@ -3463,10 +3484,7 @@
msmsdcc_request_end(host, mrq);
}
} else {
- if (host->prog_enable) {
- host->prog_scan = 0;
- host->prog_enable = 0;
- }
+ host->prog_enable = 0;
msmsdcc_reset_and_restore(host);
msmsdcc_request_end(host, mrq);
}
@@ -3678,6 +3696,8 @@
msmsdcc_get_min_sup_clk_rate(host)));
host->clks_on = 1;
+ /* Apply Hard reset to SDCC to put it in power on default state */
+ msmsdcc_hard_reset(host);
ret = msmsdcc_vreg_init(host, true);
if (ret) {
@@ -3709,6 +3729,7 @@
mmc->caps |= plat->mmc_bus_width;
mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
+ mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
/*
* If we send the CMD23 before multi block write/read command
@@ -3749,8 +3770,6 @@
writel_relaxed(0, host->base + MMCIMASK0);
writel_relaxed(MCI_CLEAR_STATIC_MASK, host->base + MMCICLEAR);
- /* Delay needed (MMCIMASK0 was just written above) */
- msmsdcc_delay(host);
writel_relaxed(MCI_IRQENABLE, host->base + MMCIMASK0);
mb();
host->mci_irqenable = MCI_IRQENABLE;
@@ -4143,12 +4162,14 @@
* part of LPM), then clocks should be turned on before
* calling mmc_suspend_host() because mmc_suspend_host might
* send some commands to the card. The clocks will be turned
- * off again after mmc_suspend_host. Thus for SD/MMC/SDIO
+ * off again after mmc_suspend_host. Thus for SDIO
* cards, clocks will be turned on before mmc_suspend_host
* and turned off after mmc_suspend_host.
*/
- mmc->ios.clock = host->clk_rate;
- mmc->ops->set_ios(host->mmc, &host->mmc->ios);
+ if (mmc->card && mmc_card_sdio(mmc->card)) {
+ mmc->ios.clock = host->clk_rate;
+ mmc->ops->set_ios(host->mmc, &host->mmc->ios);
+ }
/*
* MMC core thinks that host is disabled by now since
@@ -4217,26 +4238,26 @@
enable_irq(host->core_irqres->start);
host->sdcc_irq_disabled = 0;
}
- }
- mmc->ios.clock = host->clk_rate;
- mmc->ops->set_ios(host->mmc, &host->mmc->ios);
+ mmc->ios.clock = host->clk_rate;
+ mmc->ops->set_ios(host->mmc, &host->mmc->ios);
- spin_lock_irqsave(&host->lock, flags);
- writel_relaxed(host->mci_irqenable, host->base + MMCIMASK0);
- mb();
+ spin_lock_irqsave(&host->lock, flags);
+ writel_relaxed(host->mci_irqenable,
+ host->base + MMCIMASK0);
+ mb();
- if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO) &&
- (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) &&
- !host->sdio_irq_disabled) {
+ if ((mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) &&
+ !host->sdio_irq_disabled) {
if (host->plat->sdiowakeup_irq) {
disable_irq_nosync(
host->plat->sdiowakeup_irq);
msmsdcc_disable_irq_wake(host);
host->sdio_irq_disabled = 1;
}
- }
+ }
- spin_unlock_irqrestore(&host->lock, flags);
+ spin_unlock_irqrestore(&host->lock, flags);
+ }
mmc_resume_host(mmc);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 31ece6e..590c293 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -77,6 +77,7 @@
#define MCI_DPSM_DIRECTION (1 << 1)
#define MCI_DPSM_MODE (1 << 2)
#define MCI_DPSM_DMAENABLE (1 << 3)
+#define MCI_DATA_PEND (1 << 17)
#define MCI_AUTO_PROG_DONE (1 << 19)
#define MCI_RX_DATA_PEND (1 << 20)
@@ -208,7 +209,7 @@
#define NR_SG 32
-#define MSM_MMC_IDLE_TIMEOUT 10000 /* msecs */
+#define MSM_MMC_IDLE_TIMEOUT 5000 /* msecs */
/*
* Set the request timeout to 10secs to allow
@@ -332,7 +333,6 @@
struct tasklet_struct dma_tlet;
- unsigned int prog_scan;
unsigned int prog_enable;
/* Command parameters */
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 179a4ac..cca1035 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -261,7 +261,8 @@
config ISL9519_CHARGER
tristate "isl9519 charger"
- depends on BATTERY_MSM8X60
+ depends on (BATTERY_MSM8X60 || PM8921_CHARGER)
+ depends on I2C
default n
help
The isl9519q charger chip from intersil is connected to an external
diff --git a/drivers/power/isl9519q.c b/drivers/power/isl9519q.c
index a45d286..733de45 100644
--- a/drivers/power/isl9519q.c
+++ b/drivers/power/isl9519q.c
@@ -20,9 +20,11 @@
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/msm-charger.h>
+#include <linux/mfd/pm8xxx/pm8921-charger.h>
#include <linux/slab.h>
#include <linux/i2c/isl9519.h>
#include <linux/msm_adc.h>
+#include <linux/spinlock.h>
#define CHG_CURRENT_REG 0x14
#define MAX_SYS_VOLTAGE_REG 0x15
@@ -34,7 +36,7 @@
#define TRCKL_CHG_STATUS_BIT 0x80
-#define ISL9519_CHG_PERIOD ((HZ) * 150)
+#define ISL9519_CHG_PERIOD_SEC 150
struct isl9519q_struct {
struct i2c_client *client;
@@ -52,6 +54,10 @@
struct msm_hardware_charger adapter_hw_chg;
int suspended;
int charge_at_resume;
+ struct ext_chg_pm8921 ext_chg;
+ spinlock_t lock;
+ bool notify_by_pmic;
+ bool trickle;
};
static int isl9519q_read_reg(struct i2c_client *client, int reg,
@@ -70,6 +76,8 @@
} else
*val = ret;
+ pr_debug("%s.reg=0x%x.val=0x%x.\n", __func__, reg, *val);
+
return 0;
}
@@ -79,6 +87,8 @@
int ret;
struct isl9519q_struct *isl_chg;
+ pr_debug("%s.reg=0x%x.val=0x%x.\n", __func__, reg, val);
+
isl_chg = i2c_get_clientdata(client);
ret = i2c_smbus_write_word_data(isl_chg->client, reg, val);
@@ -91,6 +101,14 @@
return 0;
}
+/**
+ * Read charge-current via ADC.
+ *
+ * The ISL CCMON (charge-current-monitor) pin is connected to
+ * the PMIC MPP#X pin.
+ * This not required when notify_by_pmic is used where the PMIC
+ * uses BMS to notify the ISL on charging-done / charge-resume.
+ */
static int isl_read_adc(int channel, int *mv_reading)
{
int ret;
@@ -136,98 +154,129 @@
out:
*mv_reading = 0;
pr_debug("%s: done with error for %d\n", __func__, channel);
- return -EINVAL;
+ return -EINVAL;
}
-static void isl9519q_charge(struct work_struct *isl9519_work)
+static bool is_trickle_charging(struct isl9519q_struct *isl_chg)
{
- u16 temp;
+ u16 ctrl = 0;
int ret;
+
+ ret = isl9519q_read_reg(isl_chg->client, CONTROL_REG, &ctrl);
+
+ if (!ret) {
+ pr_debug("%s.control_reg=0x%x.\n", __func__, ctrl);
+ } else {
+ dev_err(&isl_chg->client->dev,
+ "%s couldnt read cntrl reg\n", __func__);
+ }
+
+ if (ctrl & TRCKL_CHG_STATUS_BIT)
+ return true;
+
+ return false;
+}
+
+static void isl_adapter_check_ichg(struct isl9519q_struct *isl_chg)
+{
+ int ichg; /* isl charger current */
+ int mv_reading = 0;
+
+ ichg = isl_read_adc(CHANNEL_ADC_BATT_AMON, &mv_reading);
+
+ dev_dbg(&isl_chg->client->dev, "%s mv_reading=%d\n",
+ __func__, mv_reading);
+ dev_dbg(&isl_chg->client->dev, "%s isl_charger_current=%d\n",
+ __func__, ichg);
+
+ if (ichg >= 0 && ichg <= isl_chg->term_current)
+ msm_charger_notify_event(&isl_chg->adapter_hw_chg,
+ CHG_DONE_EVENT);
+
+ isl_chg->trickle = is_trickle_charging(isl_chg);
+ if (isl_chg->trickle)
+ msm_charger_notify_event(&isl_chg->adapter_hw_chg,
+ CHG_BATT_BEGIN_FAST_CHARGING);
+}
+
+/**
+ * isl9519q_worker
+ *
+ * Periodic task required to kick the ISL HW watchdog to keep
+ * charging.
+ *
+ * @isl9519_work: work context.
+ */
+static void isl9519q_worker(struct work_struct *isl9519_work)
+{
struct isl9519q_struct *isl_chg;
- int isl_charger_current;
- int mv_reading;
isl_chg = container_of(isl9519_work, struct isl9519q_struct,
charge_work.work);
dev_dbg(&isl_chg->client->dev, "%s\n", __func__);
- if (isl_chg->charging) {
- isl_charger_current = isl_read_adc(CHANNEL_ADC_BATT_AMON,
- &mv_reading);
- dev_dbg(&isl_chg->client->dev, "%s mv_reading=%d\n",
- __func__, mv_reading);
- dev_dbg(&isl_chg->client->dev, "%s isl_charger_current=%d\n",
- __func__, isl_charger_current);
- if (isl_charger_current >= 0
- && isl_charger_current <= isl_chg->term_current) {
- msm_charger_notify_event(
- &isl_chg->adapter_hw_chg,
- CHG_DONE_EVENT);
- }
- isl9519q_write_reg(isl_chg->client, CHG_CURRENT_REG,
- isl_chg->chgcurrent);
- ret = isl9519q_read_reg(isl_chg->client, CONTROL_REG, &temp);
- if (!ret) {
- if (!(temp & TRCKL_CHG_STATUS_BIT))
- msm_charger_notify_event(
- &isl_chg->adapter_hw_chg,
- CHG_BATT_BEGIN_FAST_CHARGING);
- } else {
- dev_err(&isl_chg->client->dev,
- "%s couldnt read cntrl reg\n", __func__);
- }
- schedule_delayed_work(&isl_chg->charge_work,
- ISL9519_CHG_PERIOD);
+ if (!isl_chg->charging) {
+ pr_info("%s.stop charging.\n", __func__);
+ isl9519q_write_reg(isl_chg->client, CHG_CURRENT_REG, 0);
+ return; /* Stop periodic worker */
}
+
+ /* Kick the dog by writting to CHG_CURRENT_REG */
+ isl9519q_write_reg(isl_chg->client, CHG_CURRENT_REG,
+ isl_chg->chgcurrent);
+
+ if (isl_chg->notify_by_pmic)
+ isl_chg->trickle = is_trickle_charging(isl_chg);
+ else
+ isl_adapter_check_ichg(isl_chg);
+
+ schedule_delayed_work(&isl_chg->charge_work,
+ (ISL9519_CHG_PERIOD_SEC * HZ));
}
-static int isl9519q_start_charging(struct msm_hardware_charger *hw_chg,
- int chg_voltage, int chg_current)
+static int isl9519q_start_charging(struct isl9519q_struct *isl_chg,
+ int chg_voltage, int chg_current)
{
- struct isl9519q_struct *isl_chg;
int ret = 0;
- isl_chg = container_of(hw_chg, struct isl9519q_struct, adapter_hw_chg);
- if (isl_chg->charging)
- /* we are already charging */
+ pr_info("%s.\n", __func__);
+
+ if (isl_chg->charging) {
+ pr_warn("%s.already charging.\n", __func__);
return 0;
+ }
if (isl_chg->suspended) {
+ pr_warn("%s.suspended - can't start charging.\n", __func__);
isl_chg->charge_at_resume = 1;
return 0;
}
- dev_dbg(&isl_chg->client->dev, "%s\n", __func__);
+ dev_dbg(&isl_chg->client->dev,
+ "%s starting timed work.period=%d seconds.\n",
+ __func__, (int) ISL9519_CHG_PERIOD_SEC);
- ret = isl9519q_write_reg(isl_chg->client, CHG_CURRENT_REG,
- isl_chg->chgcurrent);
- if (ret) {
- dev_err(&isl_chg->client->dev,
- "%s coulnt write to current_reg\n", __func__);
- goto out;
- }
+ /*
+ * The ISL will start charging from the worker context.
+ * This API might be called from interrupt context.
+ */
+ schedule_delayed_work(&isl_chg->charge_work, 1);
- dev_dbg(&isl_chg->client->dev, "%s starting timed work\n",
- __func__);
- schedule_delayed_work(&isl_chg->charge_work,
- ISL9519_CHG_PERIOD);
isl_chg->charging = true;
-out:
return ret;
}
-static int isl9519q_stop_charging(struct msm_hardware_charger *hw_chg)
+static int isl9519q_stop_charging(struct isl9519q_struct *isl_chg)
{
- struct isl9519q_struct *isl_chg;
- int ret = 0;
+ pr_info("%s.\n", __func__);
- isl_chg = container_of(hw_chg, struct isl9519q_struct, adapter_hw_chg);
- if (!(isl_chg->charging))
- /* we arent charging */
+ if (!(isl_chg->charging)) {
+ pr_warn("%s.already not charging.\n", __func__);
return 0;
+ }
if (isl_chg->suspended) {
isl_chg->charge_at_resume = 0;
@@ -236,17 +285,71 @@
dev_dbg(&isl_chg->client->dev, "%s\n", __func__);
- ret = isl9519q_write_reg(isl_chg->client, CHG_CURRENT_REG, 0);
- if (ret) {
- dev_err(&isl_chg->client->dev,
- "%s coulnt write to current_reg\n", __func__);
- goto out;
- }
-
isl_chg->charging = false;
- cancel_delayed_work(&isl_chg->charge_work);
-out:
- return ret;
+ isl_chg->trickle = false;
+ /*
+ * The ISL will stop charging from the worker context.
+ * This API might be called from interrupt context.
+ */
+ schedule_delayed_work(&isl_chg->charge_work, 1);
+
+ return 0;
+}
+
+static int isl_ext_start_charging(void *ctx)
+{
+ int rc;
+ struct isl9519q_struct *isl_chg = ctx;
+ unsigned long flags;
+
+ spin_lock_irqsave(&isl_chg->lock, flags);
+ rc = isl9519q_start_charging(isl_chg, 0, isl_chg->chgcurrent);
+ spin_unlock_irqrestore(&isl_chg->lock, flags);
+
+ return rc;
+}
+
+static int isl_ext_stop_charging(void *ctx)
+{
+ int rc;
+ struct isl9519q_struct *isl_chg = ctx;
+ unsigned long flags;
+
+ spin_lock_irqsave(&isl_chg->lock, flags);
+ rc = isl9519q_stop_charging(isl_chg);
+ spin_unlock_irqrestore(&isl_chg->lock, flags);
+
+ return rc;
+}
+
+static bool isl_ext_is_trickle(void *ctx)
+{
+ struct isl9519q_struct *isl_chg = ctx;
+
+ return isl_chg->trickle;
+}
+
+static int isl_adapter_start_charging(struct msm_hardware_charger *hw_chg,
+ int chg_voltage, int chg_current)
+{
+ int rc;
+ struct isl9519q_struct *isl_chg;
+
+ isl_chg = container_of(hw_chg, struct isl9519q_struct, adapter_hw_chg);
+ rc = isl9519q_start_charging(isl_chg, chg_voltage, chg_current);
+
+ return rc;
+}
+
+static int isl_adapter_stop_charging(struct msm_hardware_charger *hw_chg)
+{
+ int rc;
+ struct isl9519q_struct *isl_chg;
+
+ isl_chg = container_of(hw_chg, struct isl9519q_struct, adapter_hw_chg);
+ rc = isl9519q_stop_charging(isl_chg);
+
+ return rc;
}
static int isl9519q_charging_switched(struct msm_hardware_charger *hw_chg)
@@ -296,6 +399,93 @@
#define DEFAULT_MAX_VOLTAGE_REG_VALUE 0x1070
#define DEFAULT_MIN_VOLTAGE_REG_VALUE 0x0D00
+static int __devinit isl9519q_init_adapter(struct isl9519q_struct *isl_chg)
+{
+ int ret;
+ struct isl_platform_data *pdata = isl_chg->client->dev.platform_data;
+ struct i2c_client *client = isl_chg->client;
+
+ isl_chg->adapter_hw_chg.type = CHG_TYPE_AC;
+ isl_chg->adapter_hw_chg.rating = 2;
+ isl_chg->adapter_hw_chg.name = "isl-adapter";
+ isl_chg->adapter_hw_chg.start_charging = isl_adapter_start_charging;
+ isl_chg->adapter_hw_chg.stop_charging = isl_adapter_stop_charging;
+ isl_chg->adapter_hw_chg.charging_switched = isl9519q_charging_switched;
+
+ ret = gpio_request(pdata->valid_n_gpio, "isl_charger_valid");
+ if (ret) {
+ dev_err(&client->dev, "%s gpio_request failed "
+ "for %d ret=%d\n",
+ __func__, pdata->valid_n_gpio, ret);
+ goto out;
+ }
+
+ ret = msm_charger_register(&isl_chg->adapter_hw_chg);
+ if (ret) {
+ dev_err(&client->dev,
+ "%s msm_charger_register failed for ret =%d\n",
+ __func__, ret);
+ goto free_gpio;
+ }
+
+ ret = request_threaded_irq(client->irq, NULL,
+ isl_valid_handler,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING,
+ "isl_charger_valid", client);
+ if (ret) {
+ dev_err(&client->dev,
+ "%s request_threaded_irq failed "
+ "for %d ret =%d\n",
+ __func__, client->irq, ret);
+ goto unregister;
+ }
+ irq_set_irq_wake(client->irq, 1);
+
+ ret = gpio_get_value_cansleep(isl_chg->valid_n_gpio);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "%s gpio_get_value failed for %d ret=%d\n",
+ __func__, pdata->valid_n_gpio, ret);
+ /* assume absent */
+ ret = 1;
+ }
+ if (!ret) {
+ msm_charger_notify_event(&isl_chg->adapter_hw_chg,
+ CHG_INSERTED_EVENT);
+ isl_chg->present = 1;
+ }
+
+ return 0;
+
+unregister:
+ msm_charger_unregister(&isl_chg->adapter_hw_chg);
+free_gpio:
+ gpio_free(pdata->valid_n_gpio);
+out:
+ return ret;
+
+}
+
+static int __devinit isl9519q_init_ext_chg(struct isl9519q_struct *isl_chg)
+{
+ int ret;
+
+ isl_chg->ext_chg.name = "isl9519q";
+ isl_chg->ext_chg.ctx = isl_chg;
+ isl_chg->ext_chg.start_charging = isl_ext_start_charging;
+ isl_chg->ext_chg.stop_charging = isl_ext_stop_charging;
+ isl_chg->ext_chg.is_trickle = isl_ext_is_trickle;
+ ret = register_external_dc_charger(&isl_chg->ext_chg);
+ if (ret) {
+ pr_err("%s.failed to register external dc charger.ret=%d.\n",
+ __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static int __devinit isl9519q_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -306,6 +496,8 @@
ret = 0;
pdata = client->dev.platform_data;
+ pr_info("%s.\n", __func__);
+
if (pdata == NULL) {
dev_err(&client->dev, "%s no platform data\n", __func__);
ret = -EINVAL;
@@ -324,7 +516,9 @@
goto out;
}
- INIT_DELAYED_WORK(&isl_chg->charge_work, isl9519q_charge);
+ spin_lock_init(&isl_chg->lock);
+
+ INIT_DELAYED_WORK(&isl_chg->charge_work, isl9519q_worker);
isl_chg->client = client;
isl_chg->chgcurrent = pdata->chgcurrent;
isl_chg->term_current = pdata->term_current;
@@ -337,12 +531,14 @@
isl_chg->chgcurrent &= ~0x7F;
isl_chg->input_current &= ~0x7F;
- isl_chg->adapter_hw_chg.type = CHG_TYPE_AC;
- isl_chg->adapter_hw_chg.rating = 2;
- isl_chg->adapter_hw_chg.name = "isl-adapter";
- isl_chg->adapter_hw_chg.start_charging = isl9519q_start_charging;
- isl_chg->adapter_hw_chg.stop_charging = isl9519q_stop_charging;
- isl_chg->adapter_hw_chg.charging_switched = isl9519q_charging_switched;
+ /**
+ * ISL is Notified by PMIC to start/stop charging, rather than
+ * handling interrupt from ISL for End-Of-Chargring, and
+ * monitoring the charge-current periodically. The valid_n_gpio
+ * is also not used, dc-present is detected by PMIC.
+ */
+ isl_chg->notify_by_pmic = (client->irq == 0);
+ i2c_set_clientdata(client, isl_chg);
if (pdata->chg_detection_config) {
ret = pdata->chg_detection_config();
@@ -353,35 +549,6 @@
}
}
- ret = gpio_request(pdata->valid_n_gpio, "isl_charger_valid");
- if (ret) {
- dev_err(&client->dev, "%s gpio_request failed for %d ret=%d\n",
- __func__, pdata->valid_n_gpio, ret);
- goto free_isl_chg;
- }
-
- i2c_set_clientdata(client, isl_chg);
-
- ret = msm_charger_register(&isl_chg->adapter_hw_chg);
- if (ret) {
- dev_err(&client->dev,
- "%s msm_charger_register failed for ret =%d\n",
- __func__, ret);
- goto free_gpio;
- }
-
- ret = request_threaded_irq(client->irq, NULL,
- isl_valid_handler,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "isl_charger_valid", client);
- if (ret) {
- dev_err(&client->dev,
- "%s request_threaded_irq failed for %d ret =%d\n",
- __func__, client->irq, ret);
- goto unregister;
- }
- irq_set_irq_wake(client->irq, 1);
-
isl_chg->max_system_voltage &= MAX_VOLTAGE_REG_MASK;
isl_chg->min_system_voltage &= MIN_VOLTAGE_REG_MASK;
if (isl_chg->max_system_voltage == 0)
@@ -391,57 +558,34 @@
ret = isl9519q_write_reg(isl_chg->client, MAX_SYS_VOLTAGE_REG,
isl_chg->max_system_voltage);
- if (ret) {
- dev_err(&client->dev,
- "%s couldnt write to MAX_SYS_VOLTAGE_REG ret=%d\n",
- __func__, ret);
- goto free_irq;
- }
+ if (ret)
+ goto free_isl_chg;
ret = isl9519q_write_reg(isl_chg->client, MIN_SYS_VOLTAGE_REG,
isl_chg->min_system_voltage);
- if (ret) {
- dev_err(&client->dev,
- "%s couldnt write to MIN_SYS_VOLTAGE_REG ret=%d\n",
- __func__, ret);
- goto free_irq;
- }
+ if (ret)
+ goto free_isl_chg;
if (isl_chg->input_current) {
ret = isl9519q_write_reg(isl_chg->client,
INPUT_CURRENT_REG,
isl_chg->input_current);
- if (ret) {
- dev_err(&client->dev,
- "%s couldnt write INPUT_CURRENT_REG ret=%d\n",
- __func__, ret);
- goto free_irq;
- }
+ if (ret)
+ goto free_isl_chg;
}
- ret = gpio_get_value_cansleep(isl_chg->valid_n_gpio);
- if (ret < 0) {
- dev_err(&client->dev,
- "%s gpio_get_value failed for %d ret=%d\n", __func__,
- pdata->valid_n_gpio, ret);
- /* assume absent */
- ret = 1;
- }
- if (!ret) {
- msm_charger_notify_event(&isl_chg->adapter_hw_chg,
- CHG_INSERTED_EVENT);
- isl_chg->present = 1;
- }
+ if (isl_chg->notify_by_pmic)
+ ret = isl9519q_init_ext_chg(isl_chg);
+ else
+ ret = isl9519q_init_adapter(isl_chg);
- pr_debug("%s OK chg_present=%d\n", __func__, isl_chg->present);
+ if (ret)
+ goto free_isl_chg;
+
+ pr_info("%s OK.\n", __func__);
+
return 0;
-free_irq:
- free_irq(client->irq, NULL);
-unregister:
- msm_charger_unregister(&isl_chg->adapter_hw_chg);
-free_gpio:
- gpio_free(pdata->valid_n_gpio);
free_isl_chg:
kfree(isl_chg);
out:
@@ -493,7 +637,7 @@
isl_chg->suspended = 0;
if (isl_chg->charge_at_resume) {
isl_chg->charge_at_resume = 0;
- isl9519q_start_charging(&isl_chg->adapter_hw_chg, 0, 0);
+ isl9519q_start_charging(isl_chg, 0, 0);
}
return 0;
}
@@ -519,10 +663,12 @@
static int __init isl9519q_init(void)
{
+ pr_info("%s. isl9519q SW rev 1.01\n", __func__);
+
return i2c_add_driver(&isl9519q_driver);
}
-module_init(isl9519q_init);
+late_initcall_sync(isl9519q_init);
static void __exit isl9519q_exit(void)
{
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 4a2ad3f..1e4302b 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -21,7 +21,6 @@
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/clk.h>
-#include <linux/pm_runtime.h>
#include <mach/sps.h>
/* Per spec.max 40 bytes per received message */
@@ -45,7 +44,6 @@
#define MSM_SLIM_PERF_SUMM_THRESHOLD 0x8000
#define MSM_SLIM_NCHANS 32
#define MSM_SLIM_NPORTS 24
-#define MSM_SLIM_AUTOSUSPEND MSEC_PER_SEC
/*
* Need enough descriptors to receive present messages from slaves
@@ -82,7 +80,6 @@
#define QC_DEVID_SAT1 0x3
#define QC_DEVID_SAT2 0x4
#define QC_DEVID_PGD 0x5
-#define QC_MSM_DEVS 5
/* Component registers */
enum comp_reg {
@@ -187,12 +184,6 @@
REF_CLK_GEAR = 15,
};
-enum msm_ctrl_state {
- MSM_CTRL_AWAKE,
- MSM_CTRL_SLEEPING,
- MSM_CTRL_ASLEEP,
-};
-
struct msm_slim_sps_bam {
u32 hdl;
void __iomem *base;
@@ -235,12 +226,10 @@
struct mutex tx_lock;
u8 pgdla;
bool use_rx_msgqs;
+ int suspended;
int pipe_b;
struct completion reconf;
bool reconf_busy;
- bool chan_active;
- enum msm_ctrl_state state;
- int numdevs;
};
struct msm_slim_sat {
@@ -461,11 +450,6 @@
* before exiting ISR
*/
mb();
- if (dev->ctrl.sched.usedslots == 0 &&
- dev->state != MSM_CTRL_SLEEPING) {
- dev->chan_active = false;
- pm_runtime_put(dev->dev);
- }
complete(&dev->reconf);
}
pstat = readl_relaxed(dev->base + PGD_PORT_INT_ST_EEn + (16 * dev->ee));
@@ -665,37 +649,17 @@
u8 *puc;
int timeout;
u8 la = txn->la;
- /*
- * Voting for runtime PM: Slimbus has 2 possible use cases:
- * 1. messaging
- * 2. Data channels
- * Messaging case goes through messaging slots and data channels
- * use their own slots
- * This "get" votes for messaging bandwidth
- */
- if (txn->mc < SLIM_MSG_MC_BEGIN_RECONFIGURATION ||
- txn->mc > SLIM_MSG_MC_RECONFIGURE_NOW ||
- dev->state != MSM_CTRL_SLEEPING)
- pm_runtime_get_sync(dev->dev);
mutex_lock(&dev->tx_lock);
- if (dev->state == MSM_CTRL_ASLEEP) {
- dev_err(dev->dev, "runtime or system PM suspended state");
- mutex_unlock(&dev->tx_lock);
- pm_runtime_put(dev->dev);
- return -EBUSY;
- }
if (txn->mt == SLIM_MSG_MT_CORE &&
- txn->mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION) {
- if (dev->reconf_busy) {
+ txn->mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
+ dev->reconf_busy) {
wait_for_completion(&dev->reconf);
dev->reconf_busy = false;
- }
- /* This "get" votes for data channels */
- if (dev->ctrl.sched.usedslots != 0 &&
- !dev->chan_active) {
- dev->chan_active = true;
- pm_runtime_get(dev->dev);
- }
+ }
+ if (dev->suspended) {
+ dev_err(dev->dev, "No transaction in suspended state");
+ mutex_unlock(&dev->tx_lock);
+ return -EBUSY;
}
txn->rl--;
pbuf = msm_get_msg_buf(ctrl, txn->rl);
@@ -704,10 +668,6 @@
if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
mutex_unlock(&dev->tx_lock);
- if (txn->mc < SLIM_MSG_MC_BEGIN_RECONFIGURATION ||
- txn->mc > SLIM_MSG_MC_RECONFIGURE_NOW ||
- dev->state != MSM_CTRL_SLEEPING)
- pm_runtime_put(dev->dev);
return -EPROTONOSUPPORT;
}
if (txn->mt == SLIM_MSG_MT_CORE && txn->la == 0xFF &&
@@ -755,15 +715,11 @@
*/
dev->pipes[*puc].connected = false;
mutex_unlock(&dev->tx_lock);
- if (dev->state != MSM_CTRL_SLEEPING)
- pm_runtime_put(dev->dev);
return 0;
}
if (dev->err) {
dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
mutex_unlock(&dev->tx_lock);
- if (dev->state != MSM_CTRL_SLEEPING)
- pm_runtime_put(dev->dev);
return dev->err;
}
*(puc) = *(puc) + dev->pipe_b;
@@ -774,37 +730,10 @@
dev->wr_comp = &done;
msm_send_msg_buf(ctrl, pbuf, txn->rl);
timeout = wait_for_completion_timeout(&done, HZ);
-
- if (dev->state == MSM_CTRL_SLEEPING &&
- txn->mc == SLIM_MSG_MC_RECONFIGURE_NOW &&
- txn->mt == SLIM_MSG_MT_CORE && timeout) {
- timeout = wait_for_completion_timeout(&dev->reconf, HZ);
- dev->reconf_busy = false;
- if (timeout) {
- clk_disable(dev->rclk);
- disable_irq(dev->irq);
- dev->state = MSM_CTRL_ASLEEP;
- }
- }
- if (!timeout && dev->state == MSM_CTRL_SLEEPING &&
- txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
- txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW &&
- txn->mt == SLIM_MSG_MT_CORE) {
- dev->reconf_busy = false;
- dev->state = MSM_CTRL_AWAKE;
- dev_err(dev->dev, "clock pause failed");
- mutex_unlock(&dev->tx_lock);
- return -ETIMEDOUT;
- }
-
- mutex_unlock(&dev->tx_lock);
- if (!txn->rbuf && dev->state == MSM_CTRL_AWAKE)
- pm_runtime_put(dev->dev);
-
if (!timeout)
dev_err(dev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
txn->mt);
-
+ mutex_unlock(&dev->tx_lock);
return timeout ? dev->err : -ETIMEDOUT;
}
@@ -834,7 +763,6 @@
static int msm_clk_pause_wakeup(struct slim_controller *ctrl)
{
struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
- enable_irq(dev->irq);
clk_enable(dev->rclk);
writel_relaxed(1, dev->base + FRM_WAKEUP);
/* Make sure framer wakeup write goes through before exiting function */
@@ -849,7 +777,6 @@
* we get the message
*/
usleep_range(5000, 5000);
- dev->state = MSM_CTRL_AWAKE;
return 0;
}
@@ -994,9 +921,6 @@
e_addr[1] == QC_DEVID_PGD &&
e_addr[2] != QC_CHIPID_SL)
dev->pgdla = laddr;
- dev->numdevs++;
- if (!ret && dev->numdevs == QC_MSM_DEVS)
- pm_runtime_enable(dev->dev);
} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
mc == SLIM_MSG_MC_REPLY_VALUE) {
@@ -1004,7 +928,6 @@
dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len - 4);
slim_msg_response(&dev->ctrl, &buf[4], tid,
len - 4);
- pm_runtime_put(dev->dev);
} else if (mc == SLIM_MSG_MC_REPORT_INFORMATION) {
u8 l_addr = buf[2];
u16 ele = (u16)buf[4] << 4;
@@ -1057,19 +980,11 @@
for (i = 0; i < 6; i++)
e_addr[i] = buf[7-i];
- pm_runtime_get_sync(dev->dev);
slim_assign_laddr(&dev->ctrl, e_addr, 6, &laddr);
sat->satcl.laddr = laddr;
- } else if (mt != SLIM_MSG_MT_CORE &&
- mc != SLIM_MSG_MC_REPORT_PRESENT)
- pm_runtime_get_sync(dev->dev);
+ }
switch (mc) {
case SLIM_MSG_MC_REPORT_PRESENT:
- /* Remove runtime_pm vote once satellite acks */
- if (mt != SLIM_MSG_MT_CORE) {
- pm_runtime_put(dev->dev);
- continue;
- }
/* send a Manager capability msg */
if (sat->sent_capability)
continue;
@@ -1170,11 +1085,8 @@
default:
break;
}
- if (!gen_ack) {
- if (mc != SLIM_MSG_MC_REPORT_PRESENT)
- pm_runtime_put(dev->dev);
+ if (!gen_ack)
continue;
- }
wbuf[0] = tid;
if (!ret)
wbuf[1] = MSM_SAT_SUCCSS;
@@ -1187,7 +1099,6 @@
txn.wbuf = wbuf;
txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
msm_xfer_msg(&dev->ctrl, &txn);
- pm_runtime_put(dev->dev);
}
}
@@ -1791,9 +1702,6 @@
* function
*/
mb();
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_autosuspend_delay(&pdev->dev, MSM_SLIM_AUTOSUSPEND);
- pm_runtime_set_active(&pdev->dev);
dev_dbg(dev->dev, "MSM SB controller is up!\n");
return 0;
@@ -1827,13 +1735,12 @@
struct resource *slew_mem = dev->slew_mem;
struct msm_slim_sat *sat = dev->satd;
slim_remove_device(&sat->satcl);
- pm_runtime_disable(&pdev->dev);
- pm_runtime_set_suspended(&pdev->dev);
kfree(sat->satch);
destroy_workqueue(sat->wq);
kfree(sat);
free_irq(dev->irq, dev);
slim_del_controller(&dev->ctrl);
+ clk_disable(dev->rclk);
clk_put(dev->rclk);
msm_slim_sps_exit(dev);
kthread_stop(dev->rx_msgq_thread);
@@ -1853,78 +1760,79 @@
return 0;
}
-#ifdef CONFIG_PM_RUNTIME
-static int msm_slim_runtime_idle(struct device *device)
+#ifdef CONFIG_PM
+static int msm_slim_suspend(struct device *device)
{
struct platform_device *pdev = to_platform_device(device);
struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
- dev_dbg(device, "pm_runtime: idle...\n");
- pm_runtime_mark_last_busy(dev->dev);
- pm_request_autosuspend(device);
- return -EAGAIN;
-}
-#endif
-
-/*
- * If PM_RUNTIME is not defined, these 2 functions become helper
- * functions to be called from system suspend/resume. So they are not
- * inside ifdef CONFIG_PM_RUNTIME
- */
-static int msm_slim_runtime_suspend(struct device *device)
-{
- struct platform_device *pdev = to_platform_device(device);
- struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
- dev_dbg(device, "pm_runtime: suspending...\n");
- dev->state = MSM_CTRL_SLEEPING;
- return slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
-}
-
-static int msm_slim_runtime_resume(struct device *device)
-{
- struct platform_device *pdev = to_platform_device(device);
- struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
- dev_dbg(device, "pm_runtime: resuming...\n");
+ int ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
+ /* Make sure clock pause goes through */
mutex_lock(&dev->tx_lock);
- if (dev->state == MSM_CTRL_ASLEEP) {
- mutex_unlock(&dev->tx_lock);
- return slim_ctrl_clk_pause(&dev->ctrl, true, 0);
+ if (!ret && dev->reconf_busy) {
+ wait_for_completion(&dev->reconf);
+ dev->reconf_busy = false;
}
mutex_unlock(&dev->tx_lock);
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int msm_slim_suspend(struct device *dev)
-{
- int ret = 0;
- if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
- dev_dbg(dev, "system suspend");
- ret = msm_slim_runtime_suspend(dev);
- }
- if (ret == -EBUSY) {
+ if (!ret) {
+ clk_disable(dev->rclk);
+ disable_irq(dev->irq);
+ dev->suspended = 1;
+ } else if (ret == -EBUSY) {
/*
- * If the clock pause failed due to active channels, there is
- * a possibility that some audio stream is active during suspend
- * We dont want to return suspend failure in that case so that
- * display and relevant components can still go to suspend.
- * If there is some other error, then it should be passed-on
- * to system level suspend
- */
+ * If the clock pause failed due to active channels, there is
+ * a possibility that some audio stream is active during suspend
+ * We dont want to return suspend failure in that case so that
+ * display and relevant components can still go to suspend.
+ * If there is some other error, then it should be passed-on
+ * to system level suspend
+ */
ret = 0;
}
return ret;
}
-static int msm_slim_resume(struct device *dev)
+static int msm_slim_resume(struct device *device)
{
- /* If runtime_pm is enabled, this resume shouldn't do anything */
- if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
- dev_dbg(dev, "system resume");
- return msm_slim_runtime_resume(dev);
+ struct platform_device *pdev = to_platform_device(device);
+ struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
+ mutex_lock(&dev->tx_lock);
+ if (dev->suspended) {
+ dev->suspended = 0;
+ mutex_unlock(&dev->tx_lock);
+ enable_irq(dev->irq);
+ return slim_ctrl_clk_pause(&dev->ctrl, true, 0);
}
+ mutex_unlock(&dev->tx_lock);
return 0;
}
-#endif /* CONFIG_PM_SLEEP */
+#else
+#define msm_slim_suspend NULL
+#define msm_slim_resume NULL
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM_RUNTIME
+static int msm_slim_runtime_idle(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: idle...\n");
+ return 0;
+}
+
+static int msm_slim_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+ return 0;
+}
+
+static int msm_slim_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+#else
+#define msm_slim_runtime_idle NULL
+#define msm_slim_runtime_suspend NULL
+#define msm_slim_runtime_resume NULL
+#endif
static const struct dev_pm_ops msm_slim_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index bb30570..3b79129 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -892,6 +892,10 @@
cur = slim_slicecodefromsize(sl);
ec = ((sl | (1 << 3)) | ((msg->start_offset & 0xFFF) << 4));
+ ret = slim_ctrl_clk_pause(ctrl, true, 0);
+ if (ret)
+ return ret;
+
if (wbuf)
mlen += len;
if (rbuf) {
@@ -1123,6 +1127,10 @@
u8 chan = (u8)(chanh & 0xFF);
struct slim_ich *slc = &ctrl->chans[chan];
+ ret = slim_ctrl_clk_pause(ctrl, true, 0);
+ if (ret)
+ return ret;
+
mutex_lock(&ctrl->m_ctrl);
/* Make sure the channel is not already pending reconf. or active */
if (slc->state >= SLIM_CH_PENDING_ACTIVE) {
@@ -1185,8 +1193,11 @@
int slim_disconnect_ports(struct slim_device *sb, u32 *ph, int nph)
{
struct slim_controller *ctrl = sb->ctrl;
- int i;
+ int i, ret;
+ ret = slim_ctrl_clk_pause(ctrl, true, 0);
+ if (ret)
+ return ret;
mutex_lock(&ctrl->m_ctrl);
for (i = 0; i < nph; i++)
@@ -2378,6 +2389,10 @@
u32 segdist;
struct slim_pending_ch *pch;
+ ret = slim_ctrl_clk_pause(ctrl, true, 0);
+ if (ret)
+ return ret;
+
mutex_lock(&ctrl->sched.m_reconf);
mutex_lock(&ctrl->m_ctrl);
ctrl->sched.pending_msgsl += sb->pending_msgsl - sb->cur_msgsl;
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 06d614b..bc1a25b 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -262,7 +262,10 @@
gsbi_resource = platform_get_resource_byname(pdev,
IORESOURCE_MEM,
"gsbi_resource");
- size = gsbi_resource->end - gsbi_resource->start + 1;
+ if (unlikely(!gsbi_resource))
+ return;
+
+ size = resource_size(gsbi_resource);
release_mem_region(gsbi_resource->start, size);
iounmap(msm_uport->mapped_gsbi);
msm_uport->mapped_gsbi = NULL;
@@ -280,7 +283,7 @@
IORESOURCE_MEM,
"gsbi_resource");
if (gsbi_resource) {
- size = gsbi_resource->end - gsbi_resource->start + 1;
+ size = resource_size(gsbi_resource);
if (unlikely(!request_mem_region(gsbi_resource->start, size,
"msm_serial_hs")))
return -EBUSY;
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index ad085f9..a7b53e4 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -799,7 +799,6 @@
struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
struct platform_device *pdev = to_platform_device(port->dev);
struct resource *uart_resource;
- struct resource *gsbi_resource;
resource_size_t size;
uart_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -815,11 +814,6 @@
if (msm_serial_hsl_has_gsbi(port)) {
iowrite32(GSBI_PROTOCOL_IDLE, msm_hsl_port->mapped_gsbi +
GSBI_CONTROL_ADDR);
- gsbi_resource = platform_get_resource_byname(pdev,
- IORESOURCE_MEM,
- "gsbi_resource");
-
- size = gsbi_resource->end - gsbi_resource->start + 1;
iounmap(msm_hsl_port->mapped_gsbi);
msm_hsl_port->mapped_gsbi = NULL;
}
diff --git a/drivers/usb/gadget/f_rmnet_sdio.c b/drivers/usb/gadget/f_rmnet_sdio.c
index b15c221..f63d939 100644
--- a/drivers/usb/gadget/f_rmnet_sdio.c
+++ b/drivers/usb/gadget/f_rmnet_sdio.c
@@ -1358,17 +1358,20 @@
struct rmnet_sdio_dev *dev = container_of(f, struct rmnet_sdio_dev,
function);
+ cancel_delayed_work_sync(&dev->sdio_open_work);
destroy_workqueue(dev->wq);
- rmnet_sdio_free_buf(dev);
dev->epout = dev->epin = dev->epnotify = NULL; /* release endpoints */
- msm_sdio_dmux_close(rmnet_sdio_data_ch);
- sdio_cmux_close(rmnet_sdio_ctl_ch);
+ if (test_bit(RMNET_SDIO_CH_OPEN, &dev->data_ch_status)) {
+ msm_sdio_dmux_close(rmnet_sdio_data_ch);
+ clear_bit(RMNET_SDIO_CH_OPEN, &dev->data_ch_status);
+ }
-
- clear_bit(RMNET_SDIO_CH_OPEN, &dev->data_ch_status);
- clear_bit(RMNET_SDIO_CH_OPEN, &dev->ctrl_ch_status);
+ if (test_bit(RMNET_SDIO_CH_OPEN, &dev->ctrl_ch_status)) {
+ sdio_cmux_close(rmnet_sdio_ctl_ch);
+ clear_bit(RMNET_SDIO_CH_OPEN, &dev->ctrl_ch_status);
+ }
debugfs_remove_recursive(dev->dent);
@@ -1454,7 +1457,7 @@
static void rmnet_sdio_debugfs_init(struct rmnet_sdio_dev *dev)
{
- dev->dent = debugfs_create_dir("usb_rmnet", 0);
+ dev->dent = debugfs_create_dir("usb_rmnet_sdio", 0);
if (IS_ERR(dev->dent))
return;
diff --git a/drivers/usb/gadget/f_rmnet_smd.c b/drivers/usb/gadget/f_rmnet_smd.c
index b8dd3a5..08f461f 100644
--- a/drivers/usb/gadget/f_rmnet_smd.c
+++ b/drivers/usb/gadget/f_rmnet_smd.c
@@ -1218,7 +1218,7 @@
static void rmnet_smd_debugfs_init(struct rmnet_smd_dev *dev)
{
- dent_smd = debugfs_create_dir("usb_rmnet", 0);
+ dent_smd = debugfs_create_dir("usb_rmnet_smd", 0);
if (IS_ERR(dent_smd))
return;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 93933f3..5cf79c1 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -555,6 +555,10 @@
void mdp4_overlay0_done_dsi_video(struct mdp_dma_data *dma)
{
spin_lock(&mdp_spin_lock);
+ if (dsi_pipe->blt_addr == 0) {
+ spin_unlock(&mdp_spin_lock);
+ return;
+ }
dma->busy = FALSE;
mdp4_dsi_video_blt_dmap_update(dsi_pipe);
dsi_pipe->dmap_cnt++;
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index e840230..0eda69a 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -451,6 +451,10 @@
void mdp4_overlay0_done_lcdc(struct mdp_dma_data *dma)
{
spin_lock(&mdp_spin_lock);
+ if (lcdc_pipe->blt_addr == 0) {
+ spin_unlock(&mdp_spin_lock);
+ return;
+ }
dma->busy = FALSE;
mdp4_lcdc_blt_dmap_update(lcdc_pipe);
lcdc_pipe->dmap_cnt++;
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 99607e7..3d78a13 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -419,6 +419,55 @@
spin_unlock(&mdp_spin_lock);
}
#endif
+
+#ifdef CONFIG_FB_MSM_OVERLAY
+ if (isr & INTR_OVERLAY0_DONE) {
+ mdp4_stat.intr_overlay0++;
+ dma = &dma2_data;
+ if (panel & (MDP4_PANEL_LCDC | MDP4_PANEL_DSI_VIDEO)) {
+ /* disable LCDC interrupt */
+ spin_lock(&mdp_spin_lock);
+ mdp_intr_mask &= ~INTR_OVERLAY0_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->waiting = FALSE;
+ spin_unlock(&mdp_spin_lock);
+ if (panel & MDP4_PANEL_LCDC)
+ mdp4_overlay0_done_lcdc(dma);
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ else if (panel & MDP4_PANEL_DSI_VIDEO)
+ mdp4_overlay0_done_dsi_video(dma);
+#endif
+ } else { /* MDDI, DSI_CMD */
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ if (panel & MDP4_PANEL_DSI_CMD)
+ mdp4_overlay0_done_dsi_cmd(dma);
+#else
+ if (panel & MDP4_PANEL_MDDI)
+ mdp4_overlay0_done_mddi(dma);
+#endif
+ }
+ mdp_hw_cursor_done();
+ }
+ if (isr & INTR_OVERLAY1_DONE) {
+ mdp4_stat.intr_overlay1++;
+ /* disable DTV interrupt */
+ dma = &dma_e_data;
+ spin_lock(&mdp_spin_lock);
+ mdp_intr_mask &= ~INTR_OVERLAY1_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->waiting = FALSE;
+ spin_unlock(&mdp_spin_lock);
+#if defined(CONFIG_FB_MSM_DTV)
+ if (panel & MDP4_PANEL_DTV)
+ mdp4_overlay1_done_dtv();
+#endif
+#if defined(CONFIG_FB_MSM_TVOUT)
+ if (panel & MDP4_PANEL_ATV)
+ mdp4_overlay1_done_atv();
+#endif
+ }
+#endif /* OVERLAY */
+
if (isr & INTR_DMA_P_DONE) {
mdp4_stat.intr_dma_p++;
dma = &dma2_data;
@@ -488,53 +537,6 @@
}
spin_unlock(&mdp_spin_lock);
}
-#ifdef CONFIG_FB_MSM_OVERLAY
- if (isr & INTR_OVERLAY0_DONE) {
- mdp4_stat.intr_overlay0++;
- dma = &dma2_data;
- if (panel & (MDP4_PANEL_LCDC | MDP4_PANEL_DSI_VIDEO)) {
- /* disable LCDC interrupt */
- spin_lock(&mdp_spin_lock);
- mdp_intr_mask &= ~INTR_OVERLAY0_DONE;
- outp32(MDP_INTR_ENABLE, mdp_intr_mask);
- dma->waiting = FALSE;
- spin_unlock(&mdp_spin_lock);
- if (panel & MDP4_PANEL_LCDC)
- mdp4_overlay0_done_lcdc(dma);
-#ifdef CONFIG_FB_MSM_MIPI_DSI
- else if (panel & MDP4_PANEL_DSI_VIDEO)
- mdp4_overlay0_done_dsi_video(dma);
-#endif
- } else { /* MDDI, DSI_CMD */
-#ifdef CONFIG_FB_MSM_MIPI_DSI
- if (panel & MDP4_PANEL_DSI_CMD)
- mdp4_overlay0_done_dsi_cmd(dma);
-#else
- if (panel & MDP4_PANEL_MDDI)
- mdp4_overlay0_done_mddi(dma);
-#endif
- }
- mdp_hw_cursor_done();
- }
- if (isr & INTR_OVERLAY1_DONE) {
- mdp4_stat.intr_overlay1++;
- /* disable DTV interrupt */
- dma = &dma_e_data;
- spin_lock(&mdp_spin_lock);
- mdp_intr_mask &= ~INTR_OVERLAY1_DONE;
- outp32(MDP_INTR_ENABLE, mdp_intr_mask);
- dma->waiting = FALSE;
- spin_unlock(&mdp_spin_lock);
-#if defined(CONFIG_FB_MSM_DTV)
- if (panel & MDP4_PANEL_DTV)
- mdp4_overlay1_done_dtv();
-#endif
-#if defined(CONFIG_FB_MSM_TVOUT)
- if (panel & MDP4_PANEL_ATV)
- mdp4_overlay1_done_atv();
-#endif
- }
-#endif /* OVERLAY */
if (isr & INTR_DMA_P_HISTOGRAM) {
isr = inpdw(MDP_DMA_P_HIST_INTR_STATUS);
mask = inpdw(MDP_DMA_P_HIST_INTR_ENABLE);
diff --git a/drivers/video/msm/mipi_chimei_wxga_pt.c b/drivers/video/msm/mipi_chimei_wxga_pt.c
index fe7035a..4729d83 100644
--- a/drivers/video/msm/mipi_chimei_wxga_pt.c
+++ b/drivers/video/msm/mipi_chimei_wxga_pt.c
@@ -168,7 +168,12 @@
pinfo->mipi.stream = false; /* dma_p */
pinfo->mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
pinfo->mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
- pinfo->mipi.fixed_packet_size = 4;
+ /*
+ * toshiba d2l chip does not need max_pkt_szie dcs cmd
+ * client reply len is directly configure through
+ * RDPKTLN register (0x0404)
+ */
+ pinfo->mipi.no_max_pkt_size = 1;
pinfo->mipi.force_clk_lane_hs = 1;
ret = mipi_tc358764_dsi2lvds_register(pinfo, MIPI_DSI_PRIM,
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 600aac5..8d07e56 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -1159,20 +1159,22 @@
struct dsi_buf *tp, struct dsi_buf *rp,
struct dsi_cmd_desc *cmds, int rlen)
{
- int i , cnt, len, diff, pkt_size;
+ int cnt, len, diff, pkt_size;
unsigned long flag;
char cmd;
+ if (mfd->panel_info.mipi.no_max_pkt_size) {
+ /* Only support rlen = 4*n */
+ rlen += 3;
+ rlen &= 0x03;
+ }
+
len = rlen;
diff = 0;
if (len <= 2)
cnt = 4; /* short read */
- else if (mfd->panel_info.mipi.fixed_packet_size) {
- len = mfd->panel_info.mipi.fixed_packet_size;
- pkt_size = len; /* Avoid command to the device */
- cnt = (len + 6 + 3) & ~0x03; /* Add padding for align */
- } else {
+ else {
if (len > MIPI_DSI_LEN)
len = MIPI_DSI_LEN; /* 8 bytes at most */
@@ -1203,7 +1205,7 @@
dsi_mdp_busy = TRUE;
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
- if (!mfd->panel_info.mipi.fixed_packet_size) {
+ if (!mfd->panel_info.mipi.no_max_pkt_size) {
/* packet size need to be set at every read */
pkt_size = len;
max_pktsize[0] = pkt_size;
@@ -1223,10 +1225,15 @@
* at RDBK_DATA register already
*/
mipi_dsi_buf_init(rp);
- mipi_dsi_cmd_dma_rx(rp, cnt);
+ if (mfd->panel_info.mipi.no_max_pkt_size) {
+ /*
+ * expect rlen = n * 4
+ * short alignement for start addr
+ */
+ rp->data += 2;
+ }
- for (i = 0; i < cnt ; i++)
- pr_debug("%s.rp->data[%d]=0x%x.\n", __func__, i, rp->data[i]);
+ mipi_dsi_cmd_dma_rx(rp, cnt);
spin_lock_irqsave(&dsi_mdp_lock, flag);
dsi_mdp_busy = FALSE;
@@ -1234,12 +1241,16 @@
complete(&dsi_mdp_comp);
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
- /* Remove leading padding zeros if exist */
- for (i = 0; i < cnt ; i++)
- if (rp->data[0] == 0)
- rp->data++;
- else
- break;
+ if (mfd->panel_info.mipi.no_max_pkt_size) {
+ /*
+ * remove extra 2 bytes from previous
+ * rx transaction at shift register
+ * which was inserted during copy
+ * shift registers to rx buffer
+ * rx payload start from long alignment addr
+ */
+ rp->data += 2;
+ }
cmd = rp->data[0];
switch (cmd) {
diff --git a/drivers/video/msm/msm_fb_panel.h b/drivers/video/msm/msm_fb_panel.h
index 4c415b6..16979b1 100644
--- a/drivers/video/msm/msm_fb_panel.h
+++ b/drivers/video/msm/msm_fb_panel.h
@@ -122,7 +122,7 @@
char dma_trigger;
uint32 dsi_pclk_rate;
/* The packet-size should not bet changed */
- char fixed_packet_size;
+ char no_max_pkt_size;
/* Clock required during LP commands */
char force_clk_lane_hs;
/* Pad width */
diff --git a/include/linux/cyttsp.h b/include/linux/cyttsp.h
index 8d69031..0e5cac7 100644
--- a/include/linux/cyttsp.h
+++ b/include/linux/cyttsp.h
@@ -87,9 +87,11 @@
#define CY_TMA300_VTG_MAX_UV 5500000
#define CY_TMA300_VTG_MIN_UV 1710000
#define CY_TMA300_CURR_24HZ_UA 17500
+#define CY_TMA300_SLEEP_CURR_UA 10
#define CY_I2C_VTG_MAX_UV 1800000
#define CY_I2C_VTG_MIN_UV 1800000
#define CY_I2C_CURR_UA 9630
+#define CY_I2C_SLEEP_CURR_UA 10
/* define for inclusion of TTSP App Update Load File
@@ -445,9 +447,10 @@
struct cyttsp_regulator {
const char *name;
- u32 min_uV;
u32 max_uV;
- u32 load_uA;
+ u32 min_uV;
+ u32 hpm_load_uA;
+ u32 lpm_load_uA;
};
struct cyttsp_platform_data {
@@ -484,6 +487,7 @@
#ifdef CY_USE_I2C_DRIVER
s32 (*init)(struct i2c_client *client);
s32 (*resume)(struct i2c_client *client);
+ s32 (*suspend)(struct i2c_client *client);
#endif
#ifdef CY_USE_SPI_DRIVER
s32 (*init)(struct spi_device *spi);
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 9f220f8..4b7b8b7d1 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -65,6 +65,7 @@
#define ION_VMALLOC_HEAP_NAME "vmalloc"
#define ION_EBI1_HEAP_NAME "EBI1"
#define ION_ADSP_HEAP_NAME "adsp"
+#define ION_SMI_HEAP_NAME "smi"
#define CACHED 1
#define UNCACHED 0
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index fef8dc3..18f239c 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4652,6 +4652,9 @@
unsigned long totalpages = early_calculate_totalpages();
int usable_nodes = nodes_weight(node_states[N_HIGH_MEMORY]);
+#ifdef CONFIG_FIX_MOVABLE_ZONE
+ required_movablecore = movable_reserved_size >> PAGE_SHIFT;
+#endif
/*
* If movablecore was specified, calculate what size of
* kernelcore that corresponds so that memory usable for
diff --git a/mm/slub.c b/mm/slub.c
index 35f351f..adf609e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -557,10 +557,10 @@
memset(p + s->objsize, val, s->inuse - s->objsize);
}
-static u8 *check_bytes(u8 *start, unsigned int value, unsigned int bytes)
+static u8 *check_bytes8(u8 *start, u8 value, unsigned int bytes)
{
while (bytes) {
- if (*start != (u8)value)
+ if (*start != value)
return start;
start++;
bytes--;
@@ -568,6 +568,38 @@
return NULL;
}
+static u8 *check_bytes(u8 *start, u8 value, unsigned int bytes)
+{
+ u64 value64;
+ unsigned int words, prefix;
+
+ if (bytes <= 16)
+ return check_bytes8(start, value, bytes);
+
+ value64 = value | value << 8 | value << 16 | value << 24;
+ value64 = (value64 & 0xffffffff) | value64 << 32;
+ prefix = 8 - ((unsigned long)start) % 8;
+
+ if (prefix) {
+ u8 *r = check_bytes8(start, value, prefix);
+ if (r)
+ return r;
+ start += prefix;
+ bytes -= prefix;
+ }
+
+ words = bytes / 8;
+
+ while (words) {
+ if (*(u64 *)start != value64)
+ return check_bytes8(start, value, 8);
+ start += 8;
+ words--;
+ }
+
+ return check_bytes8(start, value, bytes % 8);
+}
+
static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
void *from, void *to)
{
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 620822c..2adf035 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -2919,6 +2919,8 @@
static const struct tabla_reg_mask_val tabla_codec_reg_init_val[] = {
+ {TABLA_A_QFUSE_CTL, 0xFF, 0x03},
+
/* Initialize gain registers to use register gain */
{TABLA_A_RX_HPH_L_GAIN, 0x10, 0x10},
{TABLA_A_RX_HPH_R_GAIN, 0x10, 0x10},