Diff
Modified: trunk/arch/blackfin/include/asm/cdef_misc.h (8249 => 8250)
--- trunk/arch/blackfin/include/asm/cdef_misc.h 2010-01-28 09:58:21 UTC (rev 8249)
+++ trunk/arch/blackfin/include/asm/cdef_misc.h 2010-01-28 10:46:55 UTC (rev 8250)
@@ -33,58 +33,78 @@
#ifndef __ASSEMBLY__
#include <asm/irq.h>
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+
+#define SUPPLE_0_WAKEUP ((IRQ_SUPPLE_0 - (IRQ_CORETMR + 1)) % 32)
+
+static __inline__ void bfin_iwr_set_pll(unsigned long *iwr0,
+ unsigned long *iwr1, unsigned long *iwr2,
+ unsigned long off)
{
- unsigned long flags = 0;
#ifdef SIC_IWR0
- unsigned long iwr0;
+ *iwr0 = bfin_read32(SIC_IWR0 + off);
#ifdef SIC_IWR1
- unsigned long iwr1;
+ *iwr1 = bfin_read32(SIC_IWR1 + off);
#ifdef SIC_IWR2
- unsigned long iwr2;
+ *iwr2 = bfin_read32(SIC_IWR2);
+ bfin_write32(SIC_IWR2, 0);
#endif
+ bfin_write32(SIC_IWR1 + off, 0);
#endif
+ bfin_write32(SIC_IWR0 + off, IWR_ENABLE(0));
#else
- unsigned long iwr;
+ *iwr0 = bfin_read32(SIC_IWR);
+ bfin_write32(SIC_IWR, IWR_ENABLE(0));
#endif
+}
- if (val == bfin_read_PLL_CTL())
- return;
+#if defined(CONFIG_HOTPLUG_CPU) || \
+ (defined(CONFIG_CPU_VOLTAGE) && defined(CONFIG_SMP))
+static __inline__ void bfin_iwr_set_sup0(unsigned long *iwr0,
+ unsigned long *iwr1, unsigned long *iwr2,
+ unsigned long off)
+{
+ *iwr0 = bfin_read32(SIC_IWR0 + off);
+ *iwr1 = bfin_read32(SIC_IWR1 + off);
+ bfin_write32(SIC_IWR0 + off, 0);
+ bfin_write32(SIC_IWR1 + off, IWR_ENABLE(SUPPLE_0_WAKEUP));
+}
+#endif
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
+static __inline__ void bfin_iwr_restore(unsigned long iwr0,
+ unsigned long iwr1, unsigned long iwr2,
+ unsigned long off)
+{
#ifdef SIC_IWR0
- iwr0 = bfin_read32(SIC_IWR0);
+ bfin_write32(SIC_IWR0 + off, iwr0);
#ifdef SIC_IWR1
- iwr1 = bfin_read32(SIC_IWR1);
+ bfin_write32(SIC_IWR1 + off, iwr1);
#ifdef SIC_IWR2
- iwr2 = bfin_read32(SIC_IWR2);
- bfin_write32(SIC_IWR2, 0);
+ bfin_write32(SIC_IWR2, iwr2);
#endif
- bfin_write32(SIC_IWR1, 0);
#endif
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
#else
- iwr = bfin_read32(SIC_IWR);
+ bfin_write32(SIC_IWR, iwr0);
#endif
+}
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags = 0;
+ unsigned long iwr0, iwr1, iwr2;
+ unsigned long off = (bfin_read_DSPID() & 0xff) ? 0x1000 : 0;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ bfin_iwr_set_pll(&iwr0, &iwr1, &iwr2, off);
+
bfin_write16(PLL_CTL, val);
SSYNC();
asm("IDLE;");
-#ifdef SIC_IWR0
- bfin_write32(SIC_IWR0, iwr0);
-#ifdef SIC_IWR1
- bfin_write32(SIC_IWR1, iwr1);
-#ifdef SIC_IWR2
- bfin_write32(SIC_IWR2, iwr2);
-#endif
-#endif
-#else
- bfin_write32(SIC_IWR, iwr);
-#endif
+ bfin_iwr_restore(iwr0, iwr1, iwr2, off);
local_irq_restore_hw(flags);
}
@@ -92,55 +112,20 @@
static __inline__ void bfin_write_VR_CTL(unsigned int val)
{
unsigned long flags = 0;
-#ifdef SIC_IWR0
- unsigned long iwr0;
-#ifdef SIC_IWR1
- unsigned long iwr1;
-#ifdef SIC_IWR2
- unsigned long iwr2;
-#endif
-#endif
-#else
- unsigned long iwr;
-#endif
+ unsigned long iwr0, iwr1, iwr2;
+ unsigned long off = (bfin_read_DSPID() & 0xff) ? 0x1000 : 0;
if (val == bfin_read_VR_CTL())
return;
local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
-#ifdef SIC_IWR0
- iwr0 = bfin_read32(SIC_IWR0);
-#ifdef SIC_IWR1
- iwr1 = bfin_read32(SIC_IWR1);
-#ifdef SIC_IWR2
- iwr2 = bfin_read32(SIC_IWR2);
- bfin_write32(SIC_IWR2, 0);
-#endif
- bfin_write32(SIC_IWR1, 0);
-#endif
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-#else
- iwr = bfin_read32(SIC_IWR);
- bfin_write32(SIC_IWR, IWR_ENABLE(0));
-#endif
+ bfin_iwr_set_pll(&iwr0, &iwr1, &iwr2, off);
bfin_write16(VR_CTL, val);
SSYNC();
asm("IDLE;");
-#ifdef SIC_IWR0
- bfin_write32(SIC_IWR0, iwr0);
-#ifdef SIC_IWR1
- bfin_write32(SIC_IWR1, iwr1);
-#ifdef SIC_IWR2
- bfin_write32(SIC_IWR2, iwr2);
-#endif
-#endif
-#else
- bfin_write32(SIC_IWR, iwr);
-#endif
+ bfin_iwr_restore(iwr0, iwr1, iwr2, off);
local_irq_restore_hw(flags);
}
Modified: trunk/arch/blackfin/include/asm/dpmc.h (8249 => 8250)
--- trunk/arch/blackfin/include/asm/dpmc.h 2010-01-28 09:58:21 UTC (rev 8249)
+++ trunk/arch/blackfin/include/asm/dpmc.h 2010-01-28 10:46:55 UTC (rev 8250)
@@ -123,6 +123,9 @@
#define VRPAIR(vlev, freq) (((vlev) << 16) | ((freq) >> 16))
+#ifdef CONFIG_CPU_FREQ
+#define CPUFREQ_CPU 0
+#endif
struct bfin_dpmc_platform_data {
const unsigned int *tuple_tab;
unsigned short tabsize;
Modified: trunk/arch/blackfin/include/asm/smp.h (8249 => 8250)
--- trunk/arch/blackfin/include/asm/smp.h 2010-01-28 09:58:21 UTC (rev 8249)
+++ trunk/arch/blackfin/include/asm/smp.h 2010-01-28 10:46:55 UTC (rev 8250)
@@ -27,7 +27,7 @@
void smp_icache_flush_range_others(unsigned long start,
unsigned long end);
#ifdef CONFIG_HOTPLUG_CPU
-void coreb_sleep(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
+void coreb_die(void);
void cpu_die(void);
void platform_cpu_die(void);
int __cpu_disable(void);
Modified: trunk/arch/blackfin/mach-bf561/hotplug.c (8249 => 8250)
--- trunk/arch/blackfin/mach-bf561/hotplug.c 2010-01-28 09:58:21 UTC (rev 8249)
+++ trunk/arch/blackfin/mach-bf561/hotplug.c 2010-01-28 10:46:55 UTC (rev 8250)
@@ -5,28 +5,27 @@
* Licensed under the GPL-2 or later.
*/
+#include <linux/smp.h>
#include <asm/blackfin.h>
-#include <asm/smp.h>
-#define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1))
int hotplug_coreb;
void platform_cpu_die(void)
{
- unsigned long iwr[2] = {0, 0};
- unsigned long bank = SIC_SYSIRQ(IRQ_SUPPLE_0) / 32;
- unsigned long bit = 1 << (SIC_SYSIRQ(IRQ_SUPPLE_0) % 32);
-
+ unsigned long iwr;
+ unsigned long off = smp_processor_id() ? 0x1000 : 0;
hotplug_coreb = 1;
- iwr[bank] = bit;
-
/* disable core timer */
bfin_write_TCNTL(0);
- /* clear ipi interrupt IRQ_SUPPLE_0 */
+ /* clear ipi interrupt IRQ_SUPPLE_0 of CoreB */
bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + 1)));
SSYNC();
- coreb_sleep(iwr[0], iwr[1], 0);
+ /* set CoreB wakeup by ipi0, iwr will be discarded */
+ bfin_iwr_set_sup0(&iwr, &iwr, &iwr, off);
+ SSYNC();
+
+ coreb_die();
}
Modified: trunk/arch/blackfin/mach-bf561/secondary.S (8249 => 8250)
--- trunk/arch/blackfin/mach-bf561/secondary.S 2010-01-28 09:58:21 UTC (rev 8249)
+++ trunk/arch/blackfin/mach-bf561/secondary.S 2010-01-28 10:46:55 UTC (rev 8250)
@@ -162,6 +162,7 @@
ENDPROC(_coreb_trampoline_start)
ENTRY(_coreb_trampoline_end)
+#ifdef CONFIG_HOTPLUG_CPU
.section ".text"
ENTRY(_set_sicb_iwr)
P0.H = hi(SICB_IWR0);
@@ -174,14 +175,12 @@
RTS;
ENDPROC(_set_sicb_iwr)
-ENTRY(_coreb_sleep)
+ENTRY(_coreb_die)
sp.l = lo(INITIAL_STACK);
sp.h = hi(INITIAL_STACK);
fp = sp;
usp = sp;
- call _set_sicb_iwr;
-
CLI R2;
SSYNC;
IDLE;
@@ -194,7 +193,8 @@
p0.h = hi(COREB_L1_CODE_START);
p0.l = lo(COREB_L1_CODE_START);
jump (p0);
-ENDPROC(_coreb_sleep)
+ENDPROC(_coreb_die)
+#endif
__CPUINIT
ENTRY(_coreb_start)
Modified: trunk/arch/blackfin/mach-common/cpufreq.c (8249 => 8250)
--- trunk/arch/blackfin/mach-common/cpufreq.c 2010-01-28 09:58:21 UTC (rev 8249)
+++ trunk/arch/blackfin/mach-common/cpufreq.c 2010-01-28 10:46:55 UTC (rev 8250)
@@ -15,8 +15,6 @@
#include <asm/time.h>
#include <asm/dpmc.h>
-#define CPUFREQ_CPU 0
-
/* this is the table of CCLK frequencies, in Hz */
/* .index is the entry in the auxillary dpm_state_table[] */
static struct cpufreq_frequency_table bfin_freq_table[] = {
Modified: trunk/arch/blackfin/mach-common/dpmc.c (8249 => 8250)
--- trunk/arch/blackfin/mach-common/dpmc.c 2010-01-28 09:58:21 UTC (rev 8249)
+++ trunk/arch/blackfin/mach-common/dpmc.c 2010-01-28 10:46:55 UTC (rev 8250)
@@ -61,17 +61,48 @@
}
#ifdef CONFIG_CPU_FREQ
+static void bfin_core_idle(void *info)
+{
+ unsigned long flags = 0;
+ unsigned long iwr0, iwr1, iwr2;
+ unsigned int cpu = smp_processor_id();
+ unsigned long off = cpu ? 0x1000 : 0;
+
+ local_irq_save_hw(flags);
+ bfin_iwr_set_sup0(&iwr0, &iwr1, &iwr2, off);
+
+ platform_clear_ipi(cpu, IRQ_SUPPLE_0);
+ SSYNC();
+ asm("IDLE;");
+ bfin_iwr_restore(iwr0, iwr1, iwr2, off);
+
+ local_irq_restore_hw(flags);
+}
+
static int
vreg_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
{
struct cpufreq_freqs *freq = data;
+ unsigned int cpu;
+ unsigned int this_cpu = smp_processor_id();
+ cpumask_t mask = cpu_online_map;
+ cpu_clear(this_cpu, mask);
+ if (((struct cpufreq_freqs *)data)->cpu != CPUFREQ_CPU)
+ return 0;
+
if (val == CPUFREQ_PRECHANGE && freq->old < freq->new) {
+ smp_call_function(bfin_core_idle, NULL, 0);
bfin_set_vlev(bfin_get_vlev(freq->new));
udelay(pdata->vr_settling_time); /* Wait until Volatge settled */
-
- } else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)
+ for_each_cpu_mask(cpu, mask)
+ platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
+ } else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) {
+ smp_call_function(bfin_core_idle, NULL, 0);
bfin_set_vlev(bfin_get_vlev(freq->new));
+ for_each_cpu_mask(cpu, mask)
+ platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
+ }
return 0;
}