msm: Ensure droop detectors do not affect krait PLLs

The Droop detector mechanism present in Glitch-Free (GFMUX)
goes to nondeterministic state during frequent
standalone power collapse operation. It affects
Krait PLL output so that the PLL won't lock to
required frequency.

Since Droop detector isn't used, set sc_pdn (PLL_CLAMP)
permanently high to ensure droop detector is off and it
does not affect Krait PLL.
CRs-Fixed: 381144

Conflicts:

	arch/arm/mach-msm/Kconfig
	arch/arm/mach-msm/Makefile

Change-Id: I69a0dffeccaa3837302d6e3dd53f6b62fa683368
Signed-off-by: Jay Chokshi <jchokshi@codeaurora.org>
Signed-off-by: Neha Pandey <nehap@codeaurora.org>
This commit is contained in:
Jay Chokshi 2012-12-06 20:48:23 -08:00 committed by Stephen Boyd
parent c27fdab5fc
commit 9ce61ba4ea
3 changed files with 104 additions and 0 deletions

View file

@ -177,6 +177,7 @@ config ARCH_MSM8960
select ARM_HAS_SG_CHAIN
select MSM_KRAIT_WFE_FIXUP
select MSM_IOMMU_GPU_SYNC
select MSM_CPU_PWRCTL
config ARCH_MSM8930
bool "MSM8930"
@ -210,6 +211,7 @@ config ARCH_MSM8930
select ARM_HAS_SG_CHAIN
select MSM_KRAIT_WFE_FIXUP
select MSM_IOMMU_GPU_SYNC
select MSM_CPU_PWRCTL
config ARCH_APQ8064
bool "APQ8064"
@ -238,6 +240,7 @@ config ARCH_APQ8064
select ARM_HAS_SG_CHAIN
select MSM_KRAIT_WFE_FIXUP
select MSM_IOMMU_GPU_SYNC
select MSM_CPU_PWRCTL
config ARCH_MSM8974
bool "MSM8974"
@ -2593,4 +2596,11 @@ config MSM_HSIC_SYSMON_TEST
can be read and written to send character data to the sysmon port of
the modem over USB.
config MSM_CPU_PWRCTL
bool "Ensures that krait droop detectors are always off"
help
Droop detector mechanism can adversely affect krait plls during
stand alone power collapse operation. Selecting this option
ensures that they are always off.
endif

View file

@ -389,3 +389,4 @@ obj-$(CONFIG_MSM_VP_REGULATOR) += msm_vp.o
ifdef CONFIG_MSM_CPR
obj-$(CONFIG_DEBUG_FS) += msm_cpr-debug.o
endif
obj-$(CONFIG_MSM_CPU_PWRCTL) += msm_cpu_pwrctl.o

View file

@ -0,0 +1,93 @@
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/cpu.h>
#include <linux/cpumask.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/compiler.h>
#include <linux/notifier.h>
#include <linux/percpu.h>
#include <linux/workqueue.h>
#define MSM_CPU_SECONDARY_CORE_OFFSET 0x10000
static const phys_addr_t primary_cpu_pwrctl_phys = 0x2088004;
static DEFINE_PER_CPU(int, pll_clamp_set);
static void msm_cpu_pwrctl_work_cb(struct work_struct *work);
static __cpuinitdata DECLARE_WORK(msm_cpu_pwrctl_work, msm_cpu_pwrctl_work_cb);
static int nr_cpus_done;
static int __cpuinit msm_cpu_pwrctl_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu);
static struct notifier_block __cpuinitdata msm_cpu_pwrctl_cpu_notifier = {
.notifier_call = msm_cpu_pwrctl_cpu_callback,
};
static void __cpuinit msm_cpu_pwrctl_work_cb(struct work_struct *work)
{
unregister_hotcpu_notifier(&msm_cpu_pwrctl_cpu_notifier);
}
static int __cpuinit msm_cpu_pwrctl_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
int cpu = (int) hcpu;
int *pll_clamp;
void *pwrctl_ptr;
unsigned int value;
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_ONLINE:
pll_clamp = &per_cpu(pll_clamp_set, cpu);
if (likely(*pll_clamp))
goto done;
pwrctl_ptr = ioremap_nocache(primary_cpu_pwrctl_phys +
(cpu * MSM_CPU_SECONDARY_CORE_OFFSET), SZ_4K);
if (unlikely(!pwrctl_ptr))
goto done;
value = readl_relaxed(pwrctl_ptr);
value |= 0x100;
writel_relaxed(value, pwrctl_ptr);
*pll_clamp = 1;
iounmap(pwrctl_ptr);
if (++nr_cpus_done == cpumask_weight(cpu_possible_mask))
schedule_work(&msm_cpu_pwrctl_work);
done:
break;
default:
break;
}
return NOTIFY_OK;
}
static int __init msm_cpu_pwrctl_init(void)
{
int cpu = smp_processor_id();
/* We won't get cpu online notification for this CPU,
* so take this opportunity to process this CPU.
*/
msm_cpu_pwrctl_cpu_callback(&msm_cpu_pwrctl_cpu_notifier,
CPU_ONLINE, (void *) cpu);
register_hotcpu_notifier(&msm_cpu_pwrctl_cpu_notifier);
return 0;
}
early_initcall(msm_cpu_pwrctl_init);