Root/target/linux/cns3xxx/patches-3.3/460-cns3xxx_fiq_support.patch

1--- a/arch/arm/Kconfig
2+++ b/arch/arm/Kconfig
3@@ -375,6 +375,7 @@ config ARCH_CNS3XXX
4     select PCI_DOMAINS if PCI
5     select HAVE_ARM_TWD
6     select HAVE_SMP
7+ select FIQ
8     help
9       Support for Cavium Networks CNS3XXX platform.
10 
11--- a/arch/arm/kernel/fiq.c
12+++ b/arch/arm/kernel/fiq.c
13@@ -49,6 +49,8 @@
14 
15 static unsigned long no_fiq_insn;
16 
17+unsigned int fiq_number[2] = {0, 0};
18+
19 /* Default reacquire function
20  * - we always relinquish FIQ control
21  * - we always reacquire FIQ control
22@@ -70,9 +72,12 @@ static struct fiq_handler *current_fiq =
23 
24 int show_fiq_list(struct seq_file *p, int prec)
25 {
26- if (current_fiq != &default_owner)
27- seq_printf(p, "%*s: %s\n", prec, "FIQ",
28- current_fiq->name);
29+ if (current_fiq != &default_owner) {
30+ seq_printf(p, "%*s: ", prec, "FIQ");
31+ seq_printf(p, "%10u ", fiq_number[0]);
32+ seq_printf(p, "%10u ", fiq_number[1]);
33+ seq_printf(p, " %s\n", current_fiq->name);
34+ }
35 
36     return 0;
37 }
38--- a/arch/arm/kernel/smp.c
39+++ b/arch/arm/kernel/smp.c
40@@ -400,13 +400,13 @@ void show_ipi_list(struct seq_file *p, i
41     unsigned int cpu, i;
42 
43     for (i = 0; i < NR_IPI; i++) {
44- seq_printf(p, "%*s%u: ", prec - 1, "IPI", i);
45+ seq_printf(p, "%*s%u:", prec - 1, "IPI", i);
46 
47         for_each_present_cpu(cpu)
48             seq_printf(p, "%10u ",
49                    __get_irq_stat(cpu, ipi_irqs[i]));
50 
51- seq_printf(p, " %s\n", ipi_types[i]);
52+ seq_printf(p, " %s\n", ipi_types[i]);
53     }
54 }
55 
56--- a/arch/arm/mach-cns3xxx/Makefile
57+++ b/arch/arm/mach-cns3xxx/Makefile
58@@ -2,6 +2,6 @@ obj-$(CONFIG_ARCH_CNS3XXX) += core.o pm
59 obj-$(CONFIG_PCI) += pcie.o
60 obj-$(CONFIG_MACH_CNS3420VB) += cns3420vb.o
61 obj-$(CONFIG_MACH_GW2388) += laguna.o
62-obj-$(CONFIG_SMP) += platsmp.o headsmp.o
63+obj-$(CONFIG_SMP) += platsmp.o headsmp.o cns3xxx_fiq.o
64 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
65 obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
66--- /dev/null
67+++ b/arch/arm/mach-cns3xxx/cns3xxx_fiq.S
68@@ -0,0 +1,97 @@
69+/*
70+ * linux/arch/arm/lib/floppydma.S
71+ *
72+ * Copyright (C) 1995, 1996 Russell King
73+ *
74+ * This program is free software; you can redistribute it and/or modify
75+ * it under the terms of the GNU General Public License version 2 as
76+ * published by the Free Software Foundation.
77+ */
78+#include <linux/linkage.h>
79+#include <asm/assembler.h>
80+#include <asm/asm-offsets.h>
81+
82+#define D_CACHE_LINE_SIZE 32
83+
84+ .text
85+
86+/*
87+ * R8 - DMA Start Address
88+ * R9 - DMA Length
89+ * R10 - DMA Direction
90+ * R11 - DMA type
91+ * R12 - fiq_buffer Address
92+ * R13 - DMA type Address
93+*/
94+
95+ .global cns3xxx_fiq_end
96+ENTRY(cns3xxx_fiq_start)
97+ mov r8, #0
98+ str r8, [r13]
99+
100+ ldr r9, [r12]
101+ ldr r8, [r9]
102+ add r8, r8, #1
103+ str r8, [r9]
104+
105+ ldmib r12, {r8, r9, r10}
106+ and r11, r10, #0x3000000
107+ and r10, r10, #0xff
108+
109+ teq r11, #0x1000000
110+ beq cns3xxx_dma_map_area
111+ teq r11, #0x2000000
112+ beq cns3xxx_dma_unmap_area
113+ b cns3xxx_dma_flush_range
114+
115+cns3xxx_fiq_exit:
116+ mov r8, #0
117+ str r8, [r12, #12]
118+ mcr p15, 0, r8, c7, c10, 4 @ drain write buffer
119+ subs pc, lr, #4
120+
121+cns3xxx_dma_map_area:
122+ add r9, r9, r8
123+ teq r10, #DMA_FROM_DEVICE
124+ beq cns3xxx_dma_inv_range
125+ b cns3xxx_dma_clean_range
126+
127+cns3xxx_dma_unmap_area:
128+ add r9, r9, r8
129+ teq r10, #DMA_TO_DEVICE
130+ bne cns3xxx_dma_inv_range
131+ b cns3xxx_fiq_exit
132+
133+cns3xxx_dma_flush_range:
134+ bic r8, r8, #D_CACHE_LINE_SIZE - 1
135+1:
136+ mcr p15, 0, r8, c7, c14, 1 @ clean & invalidate D line
137+ add r8, r8, #D_CACHE_LINE_SIZE
138+ cmp r8, r9
139+ blo 1b
140+ b cns3xxx_fiq_exit
141+
142+cns3xxx_dma_clean_range:
143+ bic r8, r8, #D_CACHE_LINE_SIZE - 1
144+1:
145+ mcr p15, 0, r8, c7, c10, 1 @ clean D line
146+ add r8, r8, #D_CACHE_LINE_SIZE
147+ cmp r8, r9
148+ blo 1b
149+ b cns3xxx_fiq_exit
150+
151+cns3xxx_dma_inv_range:
152+ tst r8, #D_CACHE_LINE_SIZE - 1
153+ bic r8, r8, #D_CACHE_LINE_SIZE - 1
154+ mcrne p15, 0, r8, c7, c10, 1 @ clean D line
155+ tst r9, #D_CACHE_LINE_SIZE - 1
156+ bic r9, r9, #D_CACHE_LINE_SIZE - 1
157+ mcrne p15, 0, r9, c7, c14, 1 @ clean & invalidate D line
158+1:
159+ mcr p15, 0, r8, c7, c6, 1 @ invalidate D line
160+ add r8, r8, #D_CACHE_LINE_SIZE
161+ cmp r8, r9
162+ blo 1b
163+ b cns3xxx_fiq_exit
164+
165+cns3xxx_fiq_end:
166--- a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
167+++ b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
168@@ -294,6 +294,7 @@
169 #define MISC_PCIE_INT_MASK(x) MISC_MEM_MAP(0x978 + (x) * 0x100)
170 #define MISC_PCIE_INT_STATUS(x) MISC_MEM_MAP(0x97C + (x) * 0x100)
171 
172+#define MISC_FIQ_CPU(x) MISC_MEM_MAP(0xA58 - (x) * 0x4)
173 /*
174  * Power management and clock control
175  */
176--- a/arch/arm/mach-cns3xxx/include/mach/irqs.h
177+++ b/arch/arm/mach-cns3xxx/include/mach/irqs.h
178@@ -14,6 +14,7 @@
179 #define IRQ_LOCALTIMER 29
180 #define IRQ_LOCALWDOG 30
181 #define IRQ_TC11MP_GIC_START 32
182+#define FIQ_START 0
183 
184 #include <mach/cns3xxx.h>
185 
186--- /dev/null
187+++ b/arch/arm/mach-cns3xxx/include/mach/smp.h
188@@ -0,0 +1,8 @@
189+#ifndef __MACH_SMP_H
190+#define __MACH_SMP_H
191+
192+extern void smp_dma_map_area(const void *, size_t, int);
193+extern void smp_dma_unmap_area(const void *, size_t, int);
194+extern void smp_dma_flush_range(const void *, const void *);
195+
196+#endif
197--- a/arch/arm/mach-cns3xxx/platsmp.c
198+++ b/arch/arm/mach-cns3xxx/platsmp.c
199@@ -24,10 +24,27 @@
200 #include <asm/hardware/gic.h>
201 #include <asm/smp_scu.h>
202 #include <asm/unified.h>
203-
204+#include <asm/fiq.h>
205+#include <mach/smp.h>
206 #include <mach/cns3xxx.h>
207 
208+static struct fiq_handler fh = {
209+ .name = "cns3xxx-fiq"
210+};
211+
212+static unsigned int fiq_buffer[8];
213+
214+#define FIQ_ENABLED 0x80000000
215+#define FIQ_GENERATE 0x00010000
216+#define CNS3XXX_MAP_AREA 0x01000000
217+#define CNS3XXX_UNMAP_AREA 0x02000000
218+#define CNS3XXX_FLUSH_RANGE 0x03000000
219+
220 extern void cns3xxx_secondary_startup(void);
221+extern unsigned char cns3xxx_fiq_start, cns3xxx_fiq_end;
222+extern unsigned int fiq_number[2];
223+extern struct cpu_cache_fns cpu_cache;
224+struct cpu_cache_fns cpu_cache_save;
225 
226 #define SCU_CPU_STATUS 0x08
227 static void __iomem *scu_base;
228@@ -38,12 +55,50 @@ static void __iomem *scu_base;
229  */
230 volatile int __cpuinitdata pen_release = -1;
231 
232+static void __init cns3xxx_set_fiq_regs(void)
233+{
234+ struct pt_regs FIQ_regs;
235+ unsigned int cpu = smp_processor_id();
236+
237+ if (cpu) {
238+ FIQ_regs.ARM_ip = (unsigned int)&fiq_buffer[4];
239+ FIQ_regs.ARM_sp = (unsigned int)MISC_FIQ_CPU(0);
240+ } else {
241+ FIQ_regs.ARM_ip = (unsigned int)&fiq_buffer[0];
242+ FIQ_regs.ARM_sp = (unsigned int)MISC_FIQ_CPU(1);
243+ }
244+ set_fiq_regs(&FIQ_regs);
245+}
246+
247+static void __init cns3xxx_init_fiq(void)
248+{
249+ void *fiqhandler_start;
250+ unsigned int fiqhandler_length;
251+ int ret;
252+
253+ fiqhandler_start = &cns3xxx_fiq_start;
254+ fiqhandler_length = &cns3xxx_fiq_end - &cns3xxx_fiq_start;
255+
256+ ret = claim_fiq(&fh);
257+
258+ if (ret) {
259+ return;
260+ }
261+
262+ set_fiq_handler(fiqhandler_start, fiqhandler_length);
263+ fiq_buffer[0] = (unsigned int)&fiq_number[0];
264+ fiq_buffer[3] = 0;
265+ fiq_buffer[4] = (unsigned int)&fiq_number[1];
266+ fiq_buffer[7] = 0;
267+}
268+
269+
270 /*
271  * Write pen_release in a way that is guaranteed to be visible to all
272  * observers, irrespective of whether they're taking part in coherency
273  * or not. This is necessary for the hotplug code to work reliably.
274  */
275-static void write_pen_release(int val)
276+static void __cpuinit write_pen_release(int val)
277 {
278     pen_release = val;
279     smp_wmb();
280@@ -63,12 +118,25 @@ void __cpuinit platform_secondary_init(u
281     gic_secondary_init(0);
282 
283     /*
284+ * Setup Secondary Core FIQ regs
285+ */
286+ cns3xxx_set_fiq_regs();
287+
288+ /*
289      * let the primary processor know we're out of the
290      * pen, then head off into the C entry point
291      */
292     write_pen_release(-1);
293 
294     /*
295+ * Fixup DMA Operations
296+ *
297+ */
298+ cpu_cache.dma_map_area = (void *)smp_dma_map_area;
299+ cpu_cache.dma_unmap_area = (void *)smp_dma_unmap_area;
300+ cpu_cache.dma_flush_range = (void *)smp_dma_flush_range;
301+
302+ /*
303      * Synchronise with the boot thread.
304      */
305     spin_lock(&boot_lock);
306@@ -171,4 +239,112 @@ void __init platform_smp_prepare_cpus(un
307      */
308     __raw_writel(virt_to_phys(cns3xxx_secondary_startup),
309             (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + 0x0600));
310+
311+ /*
312+ * Setup FIQ's for main cpu
313+ */
314+ cns3xxx_init_fiq();
315+ cns3xxx_set_fiq_regs();
316+ memcpy((void *)&cpu_cache_save, (void *)&cpu_cache, sizeof(struct cpu_cache_fns));
317+}
318+
319+
320+static inline unsigned long cns3xxx_cpu_id(void)
321+{
322+ unsigned long cpu;
323+
324+ asm volatile(
325+ " mrc p15, 0, %0, c0, c0, 5 @ cns3xxx_cpu_id\n"
326+ : "=r" (cpu) : : "memory", "cc");
327+ return (cpu & 0xf);
328+}
329+
330+void smp_dma_map_area(const void *addr, size_t size, int dir)
331+{
332+ unsigned int cpu;
333+ unsigned long flags;
334+ raw_local_irq_save(flags);
335+ cpu = cns3xxx_cpu_id();
336+ if (cpu) {
337+ fiq_buffer[1] = (unsigned int)addr;
338+ fiq_buffer[2] = size;
339+ fiq_buffer[3] = dir | CNS3XXX_MAP_AREA | FIQ_ENABLED;
340+ smp_mb();
341+ __raw_writel(FIQ_GENERATE, MISC_FIQ_CPU(1));
342+
343+ cpu_cache_save.dma_map_area(addr, size, dir);
344+ while ((fiq_buffer[3]) & FIQ_ENABLED) { barrier(); }
345+ } else {
346+
347+ fiq_buffer[5] = (unsigned int)addr;
348+ fiq_buffer[6] = size;
349+ fiq_buffer[7] = dir | CNS3XXX_MAP_AREA | FIQ_ENABLED;
350+ smp_mb();
351+ __raw_writel(FIQ_GENERATE, MISC_FIQ_CPU(0));
352+
353+ cpu_cache_save.dma_map_area(addr, size, dir);
354+ while ((fiq_buffer[7]) & FIQ_ENABLED) { barrier(); }
355+ }
356+ raw_local_irq_restore(flags);
357+}
358+
359+void smp_dma_unmap_area(const void *addr, size_t size, int dir)
360+{
361+ unsigned int cpu;
362+ unsigned long flags;
363+
364+ raw_local_irq_save(flags);
365+ cpu = cns3xxx_cpu_id();
366+ if (cpu) {
367+
368+ fiq_buffer[1] = (unsigned int)addr;
369+ fiq_buffer[2] = size;
370+ fiq_buffer[3] = dir | CNS3XXX_UNMAP_AREA | FIQ_ENABLED;
371+ smp_mb();
372+ __raw_writel(FIQ_GENERATE, MISC_FIQ_CPU(1));
373+
374+ cpu_cache_save.dma_unmap_area(addr, size, dir);
375+ while ((fiq_buffer[3]) & FIQ_ENABLED) { barrier(); }
376+ } else {
377+
378+ fiq_buffer[5] = (unsigned int)addr;
379+ fiq_buffer[6] = size;
380+ fiq_buffer[7] = dir | CNS3XXX_UNMAP_AREA | FIQ_ENABLED;
381+ smp_mb();
382+ __raw_writel(FIQ_GENERATE, MISC_FIQ_CPU(0));
383+
384+ cpu_cache_save.dma_unmap_area(addr, size, dir);
385+ while ((fiq_buffer[7]) & FIQ_ENABLED) { barrier(); }
386+ }
387+ raw_local_irq_restore(flags);
388+}
389+
390+void smp_dma_flush_range(const void *start, const void *end)
391+{
392+ unsigned int cpu;
393+ unsigned long flags;
394+ raw_local_irq_save(flags);
395+ cpu = cns3xxx_cpu_id();
396+ if (cpu) {
397+
398+ fiq_buffer[1] = (unsigned int)start;
399+ fiq_buffer[2] = (unsigned int)end;
400+ fiq_buffer[3] = CNS3XXX_FLUSH_RANGE | FIQ_ENABLED;
401+ smp_mb();
402+ __raw_writel(FIQ_GENERATE, MISC_FIQ_CPU(1));
403+
404+ cpu_cache_save.dma_flush_range(start, end);
405+ while ((fiq_buffer[3]) & FIQ_ENABLED) { barrier(); }
406+ } else {
407+
408+ fiq_buffer[5] = (unsigned int)start;
409+ fiq_buffer[6] = (unsigned int)end;
410+ fiq_buffer[7] = CNS3XXX_FLUSH_RANGE | FIQ_ENABLED;
411+ smp_mb();
412+ __raw_writel(FIQ_GENERATE, MISC_FIQ_CPU(0));
413+
414+ cpu_cache_save.dma_flush_range(start, end);
415+ while ((fiq_buffer[7]) & FIQ_ENABLED) { barrier(); }
416+ }
417+ raw_local_irq_restore(flags);
418 }
419--- a/arch/arm/mm/Kconfig
420+++ b/arch/arm/mm/Kconfig
421@@ -793,7 +793,7 @@ config NEEDS_SYSCALL_FOR_CMPXCHG
422 
423 config DMA_CACHE_RWFO
424     bool "Enable read/write for ownership DMA cache maintenance"
425- depends on CPU_V6K && SMP
426+ depends on CPU_V6K && SMP && !ARCH_CNS3XXX
427     default y
428     help
429       The Snoop Control Unit on ARM11MPCore does not detect the
430

Archive Download this file



interactive