aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-common/dpmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/mach-common/dpmc.c')
-rw-r--r--arch/blackfin/mach-common/dpmc.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/arch/blackfin/mach-common/dpmc.c b/arch/blackfin/mach-common/dpmc.c
index 02c7efd1bcf4..382099fd5561 100644
--- a/arch/blackfin/mach-common/dpmc.c
+++ b/arch/blackfin/mach-common/dpmc.c
@@ -61,17 +61,63 @@ err_out:
61} 61}
62 62
63#ifdef CONFIG_CPU_FREQ 63#ifdef CONFIG_CPU_FREQ
64# ifdef CONFIG_SMP
65static void bfin_idle_this_cpu(void *info)
66{
67 unsigned long flags = 0;
68 unsigned long iwr0, iwr1, iwr2;
69 unsigned int cpu = smp_processor_id();
70
71 local_irq_save_hw(flags);
72 bfin_iwr_set_sup0(&iwr0, &iwr1, &iwr2);
73
74 platform_clear_ipi(cpu, IRQ_SUPPLE_0);
75 SSYNC();
76 asm("IDLE;");
77 bfin_iwr_restore(iwr0, iwr1, iwr2);
78
79 local_irq_restore_hw(flags);
80}
81
82static void bfin_idle_cpu(void)
83{
84 smp_call_function(bfin_idle_this_cpu, NULL, 0);
85}
86
87static void bfin_wakeup_cpu(void)
88{
89 unsigned int cpu;
90 unsigned int this_cpu = smp_processor_id();
91 cpumask_t mask = cpu_online_map;
92
93 cpu_clear(this_cpu, mask);
94 for_each_cpu_mask(cpu, mask)
95 platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
96}
97
98# else
99static void bfin_idle_cpu(void) {}
100static void bfin_wakeup_cpu(void) {}
101# endif
102
64static int 103static int
65vreg_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) 104vreg_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
66{ 105{
67 struct cpufreq_freqs *freq = data; 106 struct cpufreq_freqs *freq = data;
68 107
108 if (freq->cpu != CPUFREQ_CPU)
109 return 0;
110
69 if (val == CPUFREQ_PRECHANGE && freq->old < freq->new) { 111 if (val == CPUFREQ_PRECHANGE && freq->old < freq->new) {
112 bfin_idle_cpu();
70 bfin_set_vlev(bfin_get_vlev(freq->new)); 113 bfin_set_vlev(bfin_get_vlev(freq->new));
71 udelay(pdata->vr_settling_time); /* Wait until Volatge settled */ 114 udelay(pdata->vr_settling_time); /* Wait until Volatge settled */
72 115 bfin_wakeup_cpu();
73 } else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) 116 } else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) {
117 bfin_idle_cpu();
74 bfin_set_vlev(bfin_get_vlev(freq->new)); 118 bfin_set_vlev(bfin_get_vlev(freq->new));
119 bfin_wakeup_cpu();
120 }
75 121
76 return 0; 122 return 0;
77} 123}