diff options
author | Nitin Kumbhar <nkumbhar@nvidia.com> | 2010-12-23 14:58:35 +0530 |
---|---|---|
committer | Nitin Kumbhar <nkumbhar@nvidia.com> | 2010-12-23 14:58:35 +0530 |
commit | 96a476b53360de76f20774122111f031be9ac9c2 (patch) | |
tree | e603fb33cb93cac7bbcc750bbaea8010a22dcea7 /arch/arm | |
parent | 8302d262e4801d44fa1b1952e15666256692b7b6 (diff) | |
parent | 3f29a8834975956ed5590959bfced00cb9bd03ed (diff) |
merging android-tegra-2.6.36 into git-master/linux-2.6/android-tegra-2.6.36
Conflicts:
arch/arm/mach-tegra/board-ventana-power.c
drivers/mfd/tps6586x.c
Change-Id: Ic8c46d4251d6e71fa2900b7e876f87e256299bc4
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/include/asm/assembler.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/kgdb.h | 5 | ||||
-rw-r--r-- | arch/arm/kernel/kgdb.c | 2 | ||||
-rw-r--r-- | arch/arm/lib/findbit.S | 6 | ||||
-rw-r--r-- | arch/arm/mach-cns3xxx/include/mach/debug-macro.S | 2 | ||||
-rw-r--r-- | arch/arm/mach-cns3xxx/pcie.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/Kconfig | 7 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cpu-tegra.c | 263 | ||||
-rw-r--r-- | arch/arm/mm/fault-armv.c | 28 | ||||
-rw-r--r-- | arch/arm/plat-omap/dma.c | 50 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/dma.h | 4 |
11 files changed, 224 insertions, 147 deletions
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 6e8f05c8a1c8..d7575554e407 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -215,7 +215,7 @@ @ Slightly optimised to avoid incrementing the pointer twice usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort .if \rept == 2 - usraccoff \instr, \reg, \ptr, \inc, 4, \cond, \abort + usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort .endif add\cond \ptr, #\rept * \inc diff --git a/arch/arm/include/asm/kgdb.h b/arch/arm/include/asm/kgdb.h index 08265993227f..48066ce9ea34 100644 --- a/arch/arm/include/asm/kgdb.h +++ b/arch/arm/include/asm/kgdb.h @@ -70,7 +70,8 @@ extern int kgdb_fault_expected; #define _GP_REGS 16 #define _FP_REGS 8 #define _EXTRA_REGS 2 -#define DBG_MAX_REG_NUM (_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS) +#define GDB_MAX_REGS (_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS) +#define DBG_MAX_REG_NUM (_GP_REGS + _FP_REGS + _EXTRA_REGS) #define KGDB_MAX_NO_CPUS 1 #define BUFMAX 400 @@ -93,7 +94,7 @@ extern int kgdb_fault_expected; #define _SPT 13 #define _LR 14 #define _PC 15 -#define _CPSR (DBG_MAX_REG_NUM - 1) +#define _CPSR (GDB_MAX_REGS - 1) /* * So that we can denote the end of a frame for tracing, diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index d6e8b4d2e60d..778c2f7024ff 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c @@ -79,7 +79,7 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task) return; /* Initialize to zero */ - for (regno = 0; regno < DBG_MAX_REG_NUM; regno++) + for (regno = 0; regno < GDB_MAX_REGS; regno++) gdb_regs[regno] = 0; /* Otherwise, we have only some registers from switch_to() */ diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S index 1e4cbd4e7be9..64f6bc1a9132 100644 --- a/arch/arm/lib/findbit.S +++ b/arch/arm/lib/findbit.S @@ -174,8 +174,8 @@ ENDPROC(_find_next_bit_be) */ .L_found: #if __LINUX_ARM_ARCH__ >= 5 - rsb r1, r3, #0 - and r3, r3, r1 + rsb r0, r3, #0 + and r3, r3, r0 clz r3, r3 rsb r3, r3, #31 add r0, r2, r3 @@ -190,5 +190,7 @@ ENDPROC(_find_next_bit_be) addeq r2, r2, #1 mov r0, r2 #endif + cmp r1, r0 @ Clamp to maxbit + movlo r0, r1 mov pc, lr diff --git a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S index d16ce7eb00e9..9b50442d4b9b 100644 --- a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S +++ b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S @@ -10,7 +10,7 @@ * published by the Free Software Foundation. */ - .macro addruart,rx + .macro addruart,rx,rtmp mrc p15, 0, \rx, c1, c0 tst \rx, #1 @ MMU enabled? moveq \rx, #0x10000000 diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c index 38088c36936c..78defd71a829 100644 --- a/arch/arm/mach-cns3xxx/pcie.c +++ b/arch/arm/mach-cns3xxx/pcie.c @@ -369,7 +369,7 @@ static int __init cns3xxx_pcie_init(void) { int i; - hook_fault_code(16 + 6, cns3xxx_pcie_abort_handler, SIGBUS, + hook_fault_code(16 + 6, cns3xxx_pcie_abort_handler, SIGBUS, 0, "imprecise external abort"); for (i = 0; i < ARRAY_SIZE(cns3xxx_pcie); i++) { diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 1412df271021..f38f4ed94b5b 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -108,3 +108,10 @@ config TEGRA_IOVMM config TEGRA_ARB_SEMAPHORE bool + +config TEGRA_THERMAL_THROTTLE + bool "Enable throttling of CPU speed on overtemp" + depends on CPU_FREQ + default y + help + Also requires enabling a temperature sensor such as NCT1008. diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index d8c103e8964c..a878545d2740 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c @@ -50,27 +50,131 @@ static struct cpufreq_frequency_table freq_table[] = { { 8, CPUFREQ_TABLE_END }, }; -/* CPU frequency is gradually lowered when throttling is enabled */ -#define THROTTLE_START_INDEX 2 -#define THROTTLE_END_INDEX 6 -#define THROTTLE_DELAY msecs_to_jiffies(2000) -#define NO_DELAY msecs_to_jiffies(0) - #define NUM_CPUS 2 static struct clk *cpu_clk; static struct clk *emc_clk; -static struct workqueue_struct *workqueue; - static unsigned long target_cpu_speed[NUM_CPUS]; static DEFINE_MUTEX(tegra_cpu_lock); static bool is_suspended; +unsigned int tegra_getspeed(unsigned int cpu); +static int tegra_update_cpu_speed(unsigned long rate); + +/* CPU frequency is gradually lowered when throttling is enabled */ +#define THROTTLE_START_INDEX 2 +#define THROTTLE_END_INDEX 6 + +#ifdef CONFIG_TEGRA_THERMAL_THROTTLE +#define THROTTLE_DELAY msecs_to_jiffies(2000) +#define NO_DELAY msecs_to_jiffies(0) + static DEFINE_MUTEX(throttling_lock); static bool is_throttling; static struct delayed_work throttle_work; +static struct workqueue_struct *workqueue; + +#define tegra_cpu_is_throttling() (is_throttling) + +static bool tegra_throttling_needed(unsigned long *rate) +{ + unsigned int current_freq = tegra_getspeed(0); + int i; + + for (i = THROTTLE_END_INDEX; i >= THROTTLE_START_INDEX; i--) { + if (freq_table[i].frequency < current_freq) { + *rate = freq_table[i].frequency; + return true; + } + } + + return false; +} + +static void tegra_throttle_work_func(struct work_struct *work) +{ + unsigned long rate; + + mutex_lock(&tegra_cpu_lock); + + if (tegra_throttling_needed(&rate) && tegra_update_cpu_speed(rate) == 0) { + queue_delayed_work(workqueue, &throttle_work, THROTTLE_DELAY); + } + + mutex_unlock(&tegra_cpu_lock); +} + +/* + * tegra_throttling_enable + * This function may sleep + */ +void tegra_throttling_enable(bool enable) +{ + mutex_lock(&throttling_lock); + + if (enable && !is_throttling) { + is_throttling = true; + queue_delayed_work(workqueue, &throttle_work, NO_DELAY); + } else if (!enable && is_throttling) { + cancel_delayed_work_sync(&throttle_work); + is_throttling = false; + } + + mutex_unlock(&throttling_lock); +} +EXPORT_SYMBOL_GPL(tegra_throttling_enable); + +#ifdef CONFIG_DEBUG_FS +static int throttle_debug_set(void *data, u64 val) +{ + tegra_throttling_enable(val); + return 0; +} +static int throttle_debug_get(void *data, u64 *val) +{ + *val = (u64) is_throttling; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(throttle_fops, throttle_debug_get, throttle_debug_set, "%llu\n"); + +static struct dentry *cpu_tegra_debugfs_root; + +static int __init tegra_cpu_debug_init(void) +{ + cpu_tegra_debugfs_root = debugfs_create_dir("cpu-tegra", 0); + + if (!cpu_tegra_debugfs_root) + return -ENOMEM; + + if (!debugfs_create_file("throttle", 0644, cpu_tegra_debugfs_root, NULL, &throttle_fops)) + goto err_out; + + return 0; + +err_out: + debugfs_remove_recursive(cpu_tegra_debugfs_root); + return -ENOMEM; + +} + +static void __exit tegra_cpu_debug_exit(void) +{ + debugfs_remove_recursive(cpu_tegra_debugfs_root); +} + +late_initcall(tegra_cpu_debug_init); +module_exit(tegra_cpu_debug_exit); +#endif /* CONFIG_DEBUG_FS */ + +#else /* CONFIG_TEGRA_THERMAL_THROTTLE */ +#define tegra_cpu_is_throttling() (0) +void tegra_throttling_enable(bool enable) +{ +} +#endif /* CONFIG_TEGRA_THERMAL_THROTTLE */ int tegra_verify_speed(struct cpufreq_policy *policy) { @@ -169,8 +273,7 @@ static int tegra_target(struct cpufreq_policy *policy, { int idx; unsigned int freq; - unsigned int highest_speed; - unsigned int limit_when_throttling; + unsigned int new_speed; int ret = 0; mutex_lock(&tegra_cpu_lock); @@ -187,136 +290,30 @@ static int tegra_target(struct cpufreq_policy *policy, target_cpu_speed[policy->cpu] = freq; - highest_speed = tegra_cpu_highest_speed(); + new_speed = tegra_cpu_highest_speed(); /* Do not go above this frequency when throttling */ - limit_when_throttling = freq_table[THROTTLE_START_INDEX].frequency; - - if (is_throttling && highest_speed > limit_when_throttling) { - if (tegra_getspeed(0) < limit_when_throttling) { - ret = tegra_update_cpu_speed(limit_when_throttling); - goto out; - } else { - ret = -EBUSY; - goto out; + + if (tegra_cpu_is_throttling()) { + unsigned int throttle_limit = + freq_table[THROTTLE_START_INDEX].frequency; + + if (new_speed > throttle_limit) { + if (tegra_getspeed(0) < throttle_limit) { + new_speed = throttle_limit; + } else { + ret = -EBUSY; + goto out; + } } } - ret = tegra_update_cpu_speed(highest_speed); + ret = tegra_update_cpu_speed(new_speed); out: mutex_unlock(&tegra_cpu_lock); return ret; } -static bool tegra_throttling_needed(unsigned long *rate) -{ - unsigned int current_freq = tegra_getspeed(0); - int i; - - for (i = THROTTLE_END_INDEX; i >= THROTTLE_START_INDEX; i--) { - if (freq_table[i].frequency < current_freq) { - *rate = freq_table[i].frequency; - return true; - } - } - - return false; -} - -static void tegra_throttle_work_func(struct work_struct *work) -{ - unsigned long rate; - - mutex_lock(&tegra_cpu_lock); - - if (tegra_throttling_needed(&rate) && tegra_update_cpu_speed(rate) == 0) { - queue_delayed_work(workqueue, &throttle_work, THROTTLE_DELAY); - } - - mutex_unlock(&tegra_cpu_lock); -} - -/** - * tegra_throttling_enable - * This functions may sleep - */ -void tegra_throttling_enable(void) -{ - mutex_lock(&throttling_lock); - - if (!is_throttling) { - is_throttling = true; - queue_delayed_work(workqueue, &throttle_work, NO_DELAY); - } - - mutex_unlock(&throttling_lock); -} -EXPORT_SYMBOL_GPL(tegra_throttling_enable); - -/** - * tegra_throttling_disable - * This functions may sleep - */ -void tegra_throttling_disable(void) -{ - mutex_lock(&throttling_lock); - - if (is_throttling) { - cancel_delayed_work_sync(&throttle_work); - is_throttling = false; - } - - mutex_unlock(&throttling_lock); -} -EXPORT_SYMBOL_GPL(tegra_throttling_disable); - -#ifdef CONFIG_DEBUG_FS -static int throttle_debug_set(void *data, u64 val) -{ - if (val) { - tegra_throttling_enable(); - } else { - tegra_throttling_disable(); - } - - return 0; -} -static int throttle_debug_get(void *data, u64 *val) -{ - *val = (u64) is_throttling; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(throttle_fops, throttle_debug_get, throttle_debug_set, "%llu\n"); - -static struct dentry *cpu_tegra_debugfs_root; - -static int __init tegra_cpu_debug_init(void) -{ - cpu_tegra_debugfs_root = debugfs_create_dir("cpu-tegra", 0); - - if (!cpu_tegra_debugfs_root) - return -ENOMEM; - - if (!debugfs_create_file("throttle", 0644, cpu_tegra_debugfs_root, NULL, &throttle_fops)) - goto err_out; - - return 0; - -err_out: - debugfs_remove_recursive(cpu_tegra_debugfs_root); - return -ENOMEM; - -} - -static void __exit tegra_cpu_debug_exit(void) -{ - debugfs_remove_recursive(cpu_tegra_debugfs_root); -} - -late_initcall(tegra_cpu_debug_init); -module_exit(tegra_cpu_debug_exit); -#endif static int tegra_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) @@ -367,7 +364,6 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) cpumask_copy(policy->related_cpus, cpu_possible_mask); if (policy->cpu == 0) { - INIT_DELAYED_WORK(&throttle_work, tegra_throttle_work_func); register_pm_notifier(&tegra_cpu_pm_notifier); } @@ -400,15 +396,20 @@ static struct cpufreq_driver tegra_cpufreq_driver = { static int __init tegra_cpufreq_init(void) { +#ifdef CONFIG_TEGRA_THERMAL_THROTTLE workqueue = create_singlethread_workqueue("cpu-tegra"); if (!workqueue) return -ENOMEM; + INIT_DELAYED_WORK(&throttle_work, tegra_throttle_work_func); +#endif return cpufreq_register_driver(&tegra_cpufreq_driver); } static void __exit tegra_cpufreq_exit(void) { +#ifdef CONFIG_TEGRA_THERMAL_THROTTLE destroy_workqueue(workqueue); +#endif cpufreq_unregister_driver(&tegra_cpufreq_driver); } diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 030f1dab88f7..33486f952d63 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -66,6 +66,30 @@ static int do_adjust_pte(struct vm_area_struct *vma, unsigned long address, return ret; } +#if USE_SPLIT_PTLOCKS +/* + * If we are using split PTE locks, then we need to take the page + * lock here. Otherwise we are using shared mm->page_table_lock + * which is already locked, thus cannot take it. + */ +static inline void do_pte_lock(spinlock_t *ptl) +{ + /* + * Use nested version here to indicate that we are already + * holding one similar spinlock. + */ + spin_lock_nested(ptl, SINGLE_DEPTH_NESTING); +} + +static inline void do_pte_unlock(spinlock_t *ptl) +{ + spin_unlock(ptl); +} +#else /* !USE_SPLIT_PTLOCKS */ +static inline void do_pte_lock(spinlock_t *ptl) {} +static inline void do_pte_unlock(spinlock_t *ptl) {} +#endif /* USE_SPLIT_PTLOCKS */ + static int adjust_pte(struct vm_area_struct *vma, unsigned long address, unsigned long pfn) { @@ -90,11 +114,11 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address, */ ptl = pte_lockptr(vma->vm_mm, pmd); pte = pte_offset_map_nested(pmd, address); - spin_lock(ptl); + do_pte_lock(ptl); ret = do_adjust_pte(vma, address, pfn, pte); - spin_unlock(ptl); + do_pte_unlock(ptl); pte_unmap_nested(pte); return ret; diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index ec7eddf9e525..f5c5b8da9a87 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -30,6 +30,7 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/delay.h> #include <asm/system.h> #include <mach/hardware.h> @@ -996,11 +997,17 @@ void omap_start_dma(int lch) l = dma_read(CCR(lch)); /* - * Errata: On ES2.0 BUFFERING disable must be set. - * This will always fail on ES1.0 + * Errata: Inter Frame DMA buffering issue (All OMAP2420 and + * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and + * bursting is enabled. This might result in data gets stalled in + * FIFO at the end of the block. + * Workaround: DMA channels must have BUFFERING_DISABLED bit set to + * guarantee no data will stay in the DMA FIFO in case inter frame + * buffering occurs. */ - if (cpu_is_omap24xx()) - l |= OMAP_DMA_CCR_EN; + if (cpu_is_omap2420() || + (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0))) + l |= OMAP_DMA_CCR_BUFFERING_DISABLE; l |= OMAP_DMA_CCR_EN; dma_write(l, CCR(lch)); @@ -1018,8 +1025,39 @@ void omap_stop_dma(int lch) dma_write(0, CICR(lch)); l = dma_read(CCR(lch)); - l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR(lch)); + /* OMAP3 Errata i541: sDMA FIFO draining does not finish */ + if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { + int i = 0; + u32 sys_cf; + + /* Configure No-Standby */ + l = dma_read(OCP_SYSCONFIG); + sys_cf = l; + l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK; + l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); + dma_write(l , OCP_SYSCONFIG); + + l = dma_read(CCR(lch)); + l &= ~OMAP_DMA_CCR_EN; + dma_write(l, CCR(lch)); + + /* Wait for sDMA FIFO drain */ + l = dma_read(CCR(lch)); + while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE | + OMAP_DMA_CCR_WR_ACTIVE))) { + udelay(5); + i++; + l = dma_read(CCR(lch)); + } + if (i >= 100) + printk(KERN_ERR "DMA drain did not complete on " + "lch %d\n", lch); + /* Restore OCP_SYSCONFIG */ + dma_write(sys_cf, OCP_SYSCONFIG); + } else { + l &= ~OMAP_DMA_CCR_EN; + dma_write(l, CCR(lch)); + } if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { int next_lch, cur_lch = lch; diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index af3a03941add..cf66f85a011c 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -335,6 +335,10 @@ #define OMAP2_DMA_MISALIGNED_ERR_IRQ (1 << 11) #define OMAP_DMA_CCR_EN (1 << 7) +#define OMAP_DMA_CCR_RD_ACTIVE (1 << 9) +#define OMAP_DMA_CCR_WR_ACTIVE (1 << 10) +#define OMAP_DMA_CCR_SEL_SRC_DST_SYNC (1 << 24) +#define OMAP_DMA_CCR_BUFFERING_DISABLE (1 << 25) #define OMAP_DMA_DATA_TYPE_S8 0x00 #define OMAP_DMA_DATA_TYPE_S16 0x01 |