Diff
Modified: trunk/arch/blackfin/include/asm/kgdb.h (9051 => 9052)
--- trunk/arch/blackfin/include/asm/kgdb.h 2010-08-05 07:34:28 UTC (rev 9051)
+++ trunk/arch/blackfin/include/asm/kgdb.h 2010-08-05 07:49:26 UTC (rev 9052)
@@ -103,7 +103,11 @@
asm("EXCPT 2;");
}
#define BREAK_INSTR_SIZE 2
-#define CACHE_FLUSH_IS_SAFE 1
+#ifdef CONFIG_SMP
+# define CACHE_FLUSH_IS_SAFE 0
+#else
+# define CACHE_FLUSH_IS_SAFE 1
+#endif
#define GDB_ADJUSTS_BREAK_OFFSET
#define GDB_SKIP_HW_WATCH_TEST
#define HW_INST_WATCHPOINT_NUM 6
Modified: trunk/arch/blackfin/include/asm/smp.h (9051 => 9052)
--- trunk/arch/blackfin/include/asm/smp.h 2010-08-05 07:34:28 UTC (rev 9051)
+++ trunk/arch/blackfin/include/asm/smp.h 2010-08-05 07:49:26 UTC (rev 9052)
@@ -18,7 +18,14 @@
#define raw_smp_processor_id() blackfin_core_id()
extern char coreb_trampoline_start, coreb_trampoline_end;
+extern void bfin_relocate_coreb_l1_mem(void);
+#if ANOMALY_05000491
+asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr);
+extern unsigned long blackfin_iflush_l1_entry[NR_CPUS];
+#endif
+
+
struct corelock_slot {
int lock;
};
Modified: trunk/arch/blackfin/kernel/setup.c (9051 => 9052)
--- trunk/arch/blackfin/kernel/setup.c 2010-08-05 07:34:28 UTC (rev 9051)
+++ trunk/arch/blackfin/kernel/setup.c 2010-08-05 07:49:26 UTC (rev 9052)
@@ -215,11 +215,43 @@
early_dma_memcpy_done();
+#if defined(CONFIG_SMP) && ANOMALY_05000491
+ blackfin_iflush_l1_entry[0] = (unsigned long)blackfin_icache_flush_range_l1;
+#endif
/* if necessary, copy L2 text/data to L2 SRAM */
if (L2_LENGTH && l2_len)
memcpy(_stext_l2, _l2_lma, l2_len);
}
+#ifdef CONFIG_SMP
+void __init bfin_relocate_coreb_l1_mem(void)
+{
+ unsigned long text_l1_len = (unsigned long)_text_l1_len;
+ unsigned long data_l1_len = (unsigned long)_data_l1_len;
+ unsigned long data_b_l1_len = (unsigned long)_data_b_l1_len;
+
+ /* if necessary, copy L1 text to L1 instruction SRAM */
+ if (L1_CODE_LENGTH && text_l1_len)
+ early_dma_memcpy((void *)COREB_L1_CODE_START, _text_l1_lma,
+ text_l1_len);
+
+ /* if necessary, copy L1 data to L1 data bank A SRAM */
+ if (L1_DATA_A_LENGTH && data_l1_len)
+ early_dma_memcpy((void *)COREB_L1_DATA_A_START, _data_l1_lma,
+ data_l1_len);
+
+ /* if necessary, copy L1 data B to L1 data bank B SRAM */
+ if (L1_DATA_B_LENGTH && data_b_l1_len)
+ early_dma_memcpy((void *)COREB_L1_DATA_B_START, _data_b_l1_lma,
+ data_b_l1_len);
+
+#if ANOMALY_05000491
+ blackfin_iflush_l1_entry[1] = (unsigned long)blackfin_icache_flush_range_l1 -
+ (unsigned long)_stext_l1 + COREB_L1_CODE_START;
+#endif
+#endif
+}
+
#ifdef CONFIG_ROMKERNEL
void __init bfin_relocate_xip_data(void)
{
Modified: trunk/arch/blackfin/mach-bf561/smp.c (9051 => 9052)
--- trunk/arch/blackfin/mach-bf561/smp.c 2010-08-05 07:34:28 UTC (rev 9051)
+++ trunk/arch/blackfin/mach-bf561/smp.c 2010-08-05 07:49:26 UTC (rev 9052)
@@ -106,6 +106,9 @@
if (cpu_online(cpu)) {
/* release the lock and let coreb run */
spin_unlock(&boot_lock);
+
+ bfin_relocate_coreb_l1_mem();
+
return 0;
} else
panic("CPU%u: processor failed to boot\n", cpu);
Modified: trunk/arch/blackfin/mach-common/Makefile (9051 => 9052)
--- trunk/arch/blackfin/mach-common/Makefile 2010-08-05 07:34:28 UTC (rev 9051)
+++ trunk/arch/blackfin/mach-common/Makefile 2010-08-05 07:49:26 UTC (rev 9052)
@@ -9,6 +9,6 @@
obj-$(CONFIG_PM) += pm.o dpmc_modes.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o
-obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_SMP) += smp.o smp_iflush_l1.o
obj-$(CONFIG_BFIN_KERNEL_CLOCK) += clocks-init.o
obj-$(CONFIG_DEBUG_ICACHE_CHECK) += irqpanic.o
Modified: trunk/arch/blackfin/mach-common/arch_checks.c (9051 => 9052)
--- trunk/arch/blackfin/mach-common/arch_checks.c 2010-08-05 07:34:28 UTC (rev 9051)
+++ trunk/arch/blackfin/mach-common/arch_checks.c 2010-08-05 07:49:26 UTC (rev 9052)
@@ -60,7 +60,3 @@
(defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK))
# error "Anomaly 05000220 does not allow you to use Write Back cache with L2 or External Memory"
#endif
-
-#if ANOMALY_05000491 && !defined(CONFIG_CACHE_FLUSH_L1)
-# error You need IFLUSH in L1 inst while Anomaly 05000491 applies
-#endif
Modified: trunk/arch/blackfin/mach-common/cache.S (9051 => 9052)
--- trunk/arch/blackfin/mach-common/cache.S 2010-08-05 07:34:28 UTC (rev 9051)
+++ trunk/arch/blackfin/mach-common/cache.S 2010-08-05 07:49:26 UTC (rev 9052)
@@ -11,7 +11,8 @@
#include <asm/cache.h>
#include <asm/page.h>
-#ifdef CONFIG_CACHE_FLUSH_L1
+/* 05000491 - IFLUSH needs to reside in L1 memory */
+#if defined(CONFIG_CACHE_FLUSH_L1) || (!defined(CONFIG_SMP) && ANOMALY_05000491)
.section .l1.text
#else
.text
@@ -68,7 +69,22 @@
/* Invalidate all instruction cache lines assocoiated with this memory area */
ENTRY(_blackfin_icache_flush_range)
+#if defined(CONFIG_SMP) && ANOMALY_05000491
+ p0.L = LO(DSPID);
+ p0.H = HI(DSPID);
+ r2 = 0xff;
+ r3 = [p0];
+ r3 = r3 & r2;
+ r3 <<= 2;
+ p1 = r3;
+ p0.L = _blackfin_iflush_l1_entry;
+ p0.H = _blackfin_iflush_l1_entry;
+ p0 = p0 + p1;
+ p1 = [p0];
+ jump (p1);
+#else
do_flush IFLUSH
+#endif
ENDPROC(_blackfin_icache_flush_range)
/* Throw away all D-cached data in specified region without any obligation to
Modified: trunk/arch/blackfin/mach-common/smp.c (9051 => 9052)
--- trunk/arch/blackfin/mach-common/smp.c 2010-08-05 07:34:28 UTC (rev 9051)
+++ trunk/arch/blackfin/mach-common/smp.c 2010-08-05 07:49:26 UTC (rev 9052)
@@ -40,6 +40,10 @@
*/
struct corelock_slot corelock __attribute__ ((__section__(".l2.bss")));
+#if ANOMALY_05000491
+unsigned long blackfin_iflush_l1_entry[NR_CPUS];
+#endif
+
void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb,
*init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb,
*init_saved_dcplb_fault_addr_coreb;
Added: trunk/arch/blackfin/mach-common/smp_iflush_l1.S (0 => 9052)
--- trunk/arch/blackfin/mach-common/smp_iflush_l1.S (rev 0)
+++ trunk/arch/blackfin/mach-common/smp_iflush_l1.S 2010-08-05 07:49:26 UTC (rev 9052)
@@ -0,0 +1,53 @@
+/*
+ * Blackfin SMP kernel icache flush anomaly walk around code in L1 SRAM
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#include <asm/cache.h>
+#include <asm/page.h>
+
+/* 05000491 - IFLUSH needs to reside in L1 memory */
+#if ANOMALY_05000491
+
+.section .l1.text
+
+/* Invalidate all instruction cache lines assocoiated with this memory area */
+ENTRY(_blackfin_icache_flush_range_l1)
+ P0 = R0;
+
+ R2 = -L1_CACHE_BYTES;
+
+ /* start = (start & -L1_CACHE_BYTES) */
+ R0 = R0 & R2;
+
+ /* end = ((end - 1) & -L1_CACHE_BYTES) + L1_CACHE_BYTES; */
+ R1 += -1;
+ R1 = R1 & R2;
+ R1 += L1_CACHE_BYTES;
+
+ /* count = (end - start) >> L1_CACHE_SHIFT */
+ R2 = R1 - R0;
+ R2 >>= L1_CACHE_SHIFT;
+ P1 = R2;
+
+ P0 = R0;
+
+ LSETUP (1f, 2f) LC1 = P1;
+1:
+/* 05000443 - IFLUSH cannot be last instruction in hardware loop */
+#if ANOMALY_05000443
+ IFLUSH [P0++];
+2: nop;
+#else
+2: IFLUSH [P0++];
+#endif
+
+ RTS;
+ENDPROC(_blackfin_icache_flush_range_l1)
+
+#endif