Title: [8250] trunk/arch/blackfin: [!no_src_qa!]Task [#5433], implement cpu_freq with cpuvoltage, and merge with hotplug_cpu

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;
 }
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to