aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorKonrad Eisele <konrad@gaisler.com>2009-08-16 20:13:29 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-17 21:32:09 -0400
commit5213a780295895630530aebacdd19217a5379c9a (patch)
tree7bb6534312da2a4d99b97e0bb15b4dd4f4ec1909 /arch/sparc
parent8abf9196008a7f06841b10769d1aed3f28c1d314 (diff)
sparc,leon: CONFIG_SPARC_LEON option and leon specific files.
The macro CONFIG_SPARC_LEON will shield, if undefined, the sun-sparc code from LEON specific code. In particular include/asm/leon.h will get empty through #ifdef and leon_kernel.c and leon_mm.c will not be compiled. Signed-off-by: Konrad Eisele <konrad@gaisler.com> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/Kconfig11
-rw-r--r--arch/sparc/include/asm/leon.h362
-rw-r--r--arch/sparc/include/asm/leon_amba.h263
-rw-r--r--arch/sparc/kernel/leon_kernel.c203
-rw-r--r--arch/sparc/mm/leon_mm.c260
5 files changed, 1099 insertions, 0 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 3f8b6a92eab..b847f880eec 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -437,6 +437,17 @@ config SERIAL_CONSOLE
437 437
438 If unsure, say N. 438 If unsure, say N.
439 439
440config SPARC_LEON
441 bool "Sparc Leon processor family"
442 depends on SPARC32
443 ---help---
444 If you say Y here if you are running on a SPARC-LEON processor.
445 The LEON processor is a synthesizable VHDL model of the
446 SPARC-v8 standard. LEON is part of the GRLIB collection of
447 IP cores that are distributed under GPL. GRLIB can be downloaded
448 from www.gaisler.com. You can download a sparc-linux cross-compilation
449 toolchain at www.gaisler.com.
450
440endmenu 451endmenu
441 452
442menu "Bus options (PCI etc.)" 453menu "Bus options (PCI etc.)"
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
new file mode 100644
index 00000000000..28a42b73f64
--- /dev/null
+++ b/arch/sparc/include/asm/leon.h
@@ -0,0 +1,362 @@
1/*
2 * Copyright (C) 2004 Konrad Eisele (eiselekd@web.de,konrad@gaisler.com) Gaisler Research
3 * Copyright (C) 2004 Stefan Holst (mail@s-holst.de) Uni-Stuttgart
4 * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
5 * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
6 */
7
8#ifndef LEON_H_INCLUDE
9#define LEON_H_INCLUDE
10
11#ifdef CONFIG_SPARC_LEON
12
13#define ASI_LEON_NOCACHE 0x01
14
15#define ASI_LEON_DCACHE_MISS 0x1
16
17#define ASI_LEON_CACHEREGS 0x02
18#define ASI_LEON_IFLUSH 0x10
19#define ASI_LEON_DFLUSH 0x11
20
21#define ASI_LEON_MMUFLUSH 0x18
22#define ASI_LEON_MMUREGS 0x19
23#define ASI_LEON_BYPASS 0x1c
24#define ASI_LEON_FLUSH_PAGE 0x10
25
26/* mmu register access, ASI_LEON_MMUREGS */
27#define LEON_CNR_CTRL 0x000
28#define LEON_CNR_CTXP 0x100
29#define LEON_CNR_CTX 0x200
30#define LEON_CNR_F 0x300
31#define LEON_CNR_FADDR 0x400
32
33#define LEON_CNR_CTX_NCTX 256 /*number of MMU ctx */
34
35#define LEON_CNR_CTRL_TLBDIS 0x80000000
36
37#define LEON_MMUTLB_ENT_MAX 64
38
39/*
40 * diagnostic access from mmutlb.vhd:
41 * 0: pte address
42 * 4: pte
43 * 8: additional flags
44 */
45#define LEON_DIAGF_LVL 0x3
46#define LEON_DIAGF_WR 0x8
47#define LEON_DIAGF_WR_SHIFT 3
48#define LEON_DIAGF_HIT 0x10
49#define LEON_DIAGF_HIT_SHIFT 4
50#define LEON_DIAGF_CTX 0x1fe0
51#define LEON_DIAGF_CTX_SHIFT 5
52#define LEON_DIAGF_VALID 0x2000
53#define LEON_DIAGF_VALID_SHIFT 13
54
55/*
56 * Interrupt Sources
57 *
58 * The interrupt source numbers directly map to the trap type and to
59 * the bits used in the Interrupt Clear, Interrupt Force, Interrupt Mask,
60 * and the Interrupt Pending Registers.
61 */
62#define LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR 1
63#define LEON_INTERRUPT_UART_1_RX_TX 2
64#define LEON_INTERRUPT_UART_0_RX_TX 3
65#define LEON_INTERRUPT_EXTERNAL_0 4
66#define LEON_INTERRUPT_EXTERNAL_1 5
67#define LEON_INTERRUPT_EXTERNAL_2 6
68#define LEON_INTERRUPT_EXTERNAL_3 7
69#define LEON_INTERRUPT_TIMER1 8
70#define LEON_INTERRUPT_TIMER2 9
71#define LEON_INTERRUPT_EMPTY1 10
72#define LEON_INTERRUPT_EMPTY2 11
73#define LEON_INTERRUPT_OPEN_ETH 12
74#define LEON_INTERRUPT_EMPTY4 13
75#define LEON_INTERRUPT_EMPTY5 14
76#define LEON_INTERRUPT_EMPTY6 15
77
78/* irq masks */
79#define LEON_HARD_INT(x) (1 << (x)) /* irq 0-15 */
80#define LEON_IRQMASK_R 0x0000fffe /* bit 15- 1 of lregs.irqmask */
81#define LEON_IRQPRIO_R 0xfffe0000 /* bit 31-17 of lregs.irqmask */
82
83/* leon uart register definitions */
84#define LEON_OFF_UDATA 0x0
85#define LEON_OFF_USTAT 0x4
86#define LEON_OFF_UCTRL 0x8
87#define LEON_OFF_USCAL 0xc
88
89#define LEON_UCTRL_RE 0x01
90#define LEON_UCTRL_TE 0x02
91#define LEON_UCTRL_RI 0x04
92#define LEON_UCTRL_TI 0x08
93#define LEON_UCTRL_PS 0x10
94#define LEON_UCTRL_PE 0x20
95#define LEON_UCTRL_FL 0x40
96#define LEON_UCTRL_LB 0x80
97
98#define LEON_USTAT_DR 0x01
99#define LEON_USTAT_TS 0x02
100#define LEON_USTAT_TH 0x04
101#define LEON_USTAT_BR 0x08
102#define LEON_USTAT_OV 0x10
103#define LEON_USTAT_PE 0x20
104#define LEON_USTAT_FE 0x40
105
106#define LEON_MCFG2_SRAMDIS 0x00002000
107#define LEON_MCFG2_SDRAMEN 0x00004000
108#define LEON_MCFG2_SRAMBANKSZ 0x00001e00 /* [12-9] */
109#define LEON_MCFG2_SRAMBANKSZ_SHIFT 9
110#define LEON_MCFG2_SDRAMBANKSZ 0x03800000 /* [25-23] */
111#define LEON_MCFG2_SDRAMBANKSZ_SHIFT 23
112
113#define LEON_TCNT0_MASK 0x7fffff
114
115#define LEON_USTAT_ERROR (LEON_USTAT_OV | LEON_USTAT_PE | LEON_USTAT_FE)
116/* no break yet */
117
118#define ASI_LEON3_SYSCTRL 0x02
119#define ASI_LEON3_SYSCTRL_ICFG 0x08
120#define ASI_LEON3_SYSCTRL_DCFG 0x0c
121#define ASI_LEON3_SYSCTRL_CFG_SNOOPING (1 << 27)
122#define ASI_LEON3_SYSCTRL_CFG_SSIZE(c) (1 << ((c >> 20) & 0xf))
123
124#ifndef __ASSEMBLY__
125
126/* do a virtual address read without cache */
127static inline unsigned long leon_readnobuffer_reg(unsigned long paddr)
128{
129 unsigned long retval;
130 __asm__ __volatile__("lda [%1] %2, %0\n\t" :
131 "=r"(retval) : "r"(paddr), "i"(ASI_LEON_NOCACHE));
132 return retval;
133}
134
135/* do a physical address bypass write, i.e. for 0x80000000 */
136static inline void leon_store_reg(unsigned long paddr, unsigned long value)
137{
138 __asm__ __volatile__("sta %0, [%1] %2\n\t" : : "r"(value), "r"(paddr),
139 "i"(ASI_LEON_BYPASS) : "memory");
140}
141
142/* do a physical address bypass load, i.e. for 0x80000000 */
143static inline unsigned long leon_load_reg(unsigned long paddr)
144{
145 unsigned long retval;
146 __asm__ __volatile__("lda [%1] %2, %0\n\t" :
147 "=r"(retval) : "r"(paddr), "i"(ASI_LEON_BYPASS));
148 return retval;
149}
150
151extern inline void leon_srmmu_disabletlb(void)
152{
153 unsigned int retval;
154 __asm__ __volatile__("lda [%%g0] %2, %0\n\t" : "=r"(retval) : "r"(0),
155 "i"(ASI_LEON_MMUREGS));
156 retval |= LEON_CNR_CTRL_TLBDIS;
157 __asm__ __volatile__("sta %0, [%%g0] %2\n\t" : : "r"(retval), "r"(0),
158 "i"(ASI_LEON_MMUREGS) : "memory");
159}
160
161extern inline void leon_srmmu_enabletlb(void)
162{
163 unsigned int retval;
164 __asm__ __volatile__("lda [%%g0] %2, %0\n\t" : "=r"(retval) : "r"(0),
165 "i"(ASI_LEON_MMUREGS));
166 retval = retval & ~LEON_CNR_CTRL_TLBDIS;
167 __asm__ __volatile__("sta %0, [%%g0] %2\n\t" : : "r"(retval), "r"(0),
168 "i"(ASI_LEON_MMUREGS) : "memory");
169}
170
171/* macro access for leon_load_reg() and leon_store_reg() */
172#define LEON3_BYPASS_LOAD_PA(x) (leon_load_reg((unsigned long)(x)))
173#define LEON3_BYPASS_STORE_PA(x, v) (leon_store_reg((unsigned long)(x), (unsigned long)(v)))
174#define LEON3_BYPASS_ANDIN_PA(x, v) LEON3_BYPASS_STORE_PA(x, LEON3_BYPASS_LOAD_PA(x) & v)
175#define LEON3_BYPASS_ORIN_PA(x, v) LEON3_BYPASS_STORE_PA(x, LEON3_BYPASS_LOAD_PA(x) | v)
176#define LEON_BYPASS_LOAD_PA(x) leon_load_reg((unsigned long)(x))
177#define LEON_BYPASS_STORE_PA(x, v) leon_store_reg((unsigned long)(x), (unsigned long)(v))
178#define LEON_REGLOAD_PA(x) leon_load_reg((unsigned long)(x)+LEON_PREGS)
179#define LEON_REGSTORE_PA(x, v) leon_store_reg((unsigned long)(x)+LEON_PREGS, (unsigned long)(v))
180#define LEON_REGSTORE_OR_PA(x, v) LEON_REGSTORE_PA(x, LEON_REGLOAD_PA(x) | (unsigned long)(v))
181#define LEON_REGSTORE_AND_PA(x, v) LEON_REGSTORE_PA(x, LEON_REGLOAD_PA(x) & (unsigned long)(v))
182
183/* macro access for leon_readnobuffer_reg() */
184#define LEON_BYPASSCACHE_LOAD_VA(x) leon_readnobuffer_reg((unsigned long)(x))
185
186extern void sparc_leon_eirq_register(int eirq);
187extern void leon_init(void);
188extern void leon_switch_mm(void);
189extern void leon_init_IRQ(void);
190
191extern unsigned long last_valid_pfn;
192
193extern inline unsigned long sparc_leon3_get_dcachecfg(void)
194{
195 unsigned int retval;
196 __asm__ __volatile__("lda [%1] %2, %0\n\t" :
197 "=r"(retval) :
198 "r"(ASI_LEON3_SYSCTRL_DCFG),
199 "i"(ASI_LEON3_SYSCTRL));
200 return retval;
201}
202
203/* enable snooping */
204extern inline void sparc_leon3_enable_snooping(void)
205{
206 __asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t"
207 "set 0x800000, %%l2\n\t"
208 "or %%l2, %%l1, %%l2\n\t"
209 "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
210};
211
212extern inline void sparc_leon3_disable_cache(void)
213{
214 __asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t"
215 "set 0x00000f, %%l2\n\t"
216 "andn %%l2, %%l1, %%l2\n\t"
217 "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
218};
219
220#endif /*!__ASSEMBLY__*/
221
222#ifdef CONFIG_SMP
223# define LEON3_IRQ_RESCHEDULE 13
224# define LEON3_IRQ_TICKER (leon_percpu_timer_dev[0].irq)
225# define LEON3_IRQ_CROSS_CALL 15
226#endif
227
228#if defined(PAGE_SIZE_LEON_8K)
229#define LEON_PAGE_SIZE_LEON 1
230#elif defined(PAGE_SIZE_LEON_16K)
231#define LEON_PAGE_SIZE_LEON 2)
232#else
233#define LEON_PAGE_SIZE_LEON 0
234#endif
235
236#if LEON_PAGE_SIZE_LEON == 0
237/* [ 8, 6, 6 ] + 12 */
238#define LEON_PGD_SH 24
239#define LEON_PGD_M 0xff
240#define LEON_PMD_SH 18
241#define LEON_PMD_SH_V (LEON_PGD_SH-2)
242#define LEON_PMD_M 0x3f
243#define LEON_PTE_SH 12
244#define LEON_PTE_M 0x3f
245#elif LEON_PAGE_SIZE_LEON == 1
246/* [ 7, 6, 6 ] + 13 */
247#define LEON_PGD_SH 25
248#define LEON_PGD_M 0x7f
249#define LEON_PMD_SH 19
250#define LEON_PMD_SH_V (LEON_PGD_SH-1)
251#define LEON_PMD_M 0x3f
252#define LEON_PTE_SH 13
253#define LEON_PTE_M 0x3f
254#elif LEON_PAGE_SIZE_LEON == 2
255/* [ 6, 6, 6 ] + 14 */
256#define LEON_PGD_SH 26
257#define LEON_PGD_M 0x3f
258#define LEON_PMD_SH 20
259#define LEON_PMD_SH_V (LEON_PGD_SH-0)
260#define LEON_PMD_M 0x3f
261#define LEON_PTE_SH 14
262#define LEON_PTE_M 0x3f
263#elif LEON_PAGE_SIZE_LEON == 3
264/* [ 4, 7, 6 ] + 15 */
265#define LEON_PGD_SH 28
266#define LEON_PGD_M 0x0f
267#define LEON_PMD_SH 21
268#define LEON_PMD_SH_V (LEON_PGD_SH-0)
269#define LEON_PMD_M 0x7f
270#define LEON_PTE_SH 15
271#define LEON_PTE_M 0x3f
272#else
273#error cannot determine LEON_PAGE_SIZE_LEON
274#endif
275
276#define PAGE_MIN_SHIFT (12)
277#define PAGE_MIN_SIZE (1UL << PAGE_MIN_SHIFT)
278
279#define LEON3_XCCR_SETS_MASK 0x07000000UL
280#define LEON3_XCCR_SSIZE_MASK 0x00f00000UL
281
282#define LEON2_CCR_DSETS_MASK 0x03000000UL
283#define LEON2_CFG_SSIZE_MASK 0x00007000UL
284
285#ifndef __ASSEMBLY__
286extern unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr);
287extern void leon_flush_icache_all(void);
288extern void leon_flush_dcache_all(void);
289extern void leon_flush_cache_all(void);
290extern void leon_flush_tlb_all(void);
291extern int leon_flush_during_switch;
292extern int leon_flush_needed(void);
293
294struct vm_area_struct;
295extern void leon_flush_icache_all(void);
296extern void leon_flush_dcache_all(void);
297extern void leon_flush_pcache_all(struct vm_area_struct *vma, unsigned long page);
298extern void leon_flush_cache_all(void);
299extern void leon_flush_tlb_all(void);
300extern int leon_flush_during_switch;
301extern int leon_flush_needed(void);
302extern void leon_flush_pcache_all(struct vm_area_struct *vma, unsigned long page);
303
304/* struct that hold LEON3 cache configuration registers */
305struct leon3_cacheregs {
306 unsigned long ccr; /* 0x00 - Cache Control Register */
307 unsigned long iccr; /* 0x08 - Instruction Cache Configuration Register */
308 unsigned long dccr; /* 0x0c - Data Cache Configuration Register */
309};
310
311/* struct that hold LEON2 cache configuration register
312 * & configuration register
313 */
314struct leon2_cacheregs {
315 unsigned long ccr, cfg;
316};
317
318#ifdef __KERNEL__
319
320#include <linux/interrupt.h>
321
322struct device_node;
323extern int sparc_leon_eirq_get(int eirq, int cpu);
324extern irqreturn_t sparc_leon_eirq_isr(int dummy, void *dev_id);
325extern void sparc_leon_eirq_register(int eirq);
326extern void leon_clear_clock_irq(void);
327extern void leon_load_profile_irq(int cpu, unsigned int limit);
328extern void leon_init_timers(irq_handler_t counter_fn);
329extern void leon_clear_clock_irq(void);
330extern void leon_load_profile_irq(int cpu, unsigned int limit);
331extern void leon_trans_init(struct device_node *dp);
332extern void leon_node_init(struct device_node *dp, struct device_node ***nextp);
333extern void leon_init_IRQ(void);
334extern void leon_init(void);
335extern unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr);
336extern void init_leon(void);
337extern void poke_leonsparc(void);
338extern void leon3_getCacheRegs(struct leon3_cacheregs *regs);
339extern int leon_flush_needed(void);
340extern void leon_switch_mm(void);
341extern int srmmu_swprobe_trace;
342
343#endif /* __KERNEL__ */
344
345#endif /* __ASSEMBLY__ */
346
347/* macros used in leon_mm.c */
348#define PFN(x) ((x) >> PAGE_SHIFT)
349#define _pfn_valid(pfn) ((pfn < last_valid_pfn) && (pfn >= PFN(phys_base)))
350#define _SRMMU_PTE_PMASK_LEON 0xffffffff
351
352#else /* defined(CONFIG_SPARC_LEON) */
353
354/* nop definitions for !LEON case */
355#define leon_init() do {} while (0)
356#define leon_switch_mm() do {} while (0)
357#define leon_init_IRQ() do {} while (0)
358#define init_leon() do {} while (0)
359
360#endif /* !defined(CONFIG_SPARC_LEON) */
361
362#endif
diff --git a/arch/sparc/include/asm/leon_amba.h b/arch/sparc/include/asm/leon_amba.h
new file mode 100644
index 00000000000..618e8882179
--- /dev/null
+++ b/arch/sparc/include/asm/leon_amba.h
@@ -0,0 +1,263 @@
1/*
2*Copyright (C) 2004 Konrad Eisele (eiselekd@web.de,konrad@gaisler.com), Gaisler Research
3*Copyright (C) 2004 Stefan Holst (mail@s-holst.de), Uni-Stuttgart
4*Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com),Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
5*/
6
7#ifndef LEON_AMBA_H_INCLUDE
8#define LEON_AMBA_H_INCLUDE
9
10#ifndef __ASSEMBLY__
11
12struct amba_prom_registers {
13 unsigned int phys_addr; /* The physical address of this register */
14 unsigned int reg_size; /* How many bytes does this register take up? */
15};
16
17#endif
18
19/*
20 * The following defines the bits in the LEON UART Status Registers.
21 */
22
23#define LEON_REG_UART_STATUS_DR 0x00000001 /* Data Ready */
24#define LEON_REG_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */
25#define LEON_REG_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */
26#define LEON_REG_UART_STATUS_BR 0x00000008 /* Break Error */
27#define LEON_REG_UART_STATUS_OE 0x00000010 /* RX Overrun Error */
28#define LEON_REG_UART_STATUS_PE 0x00000020 /* RX Parity Error */
29#define LEON_REG_UART_STATUS_FE 0x00000040 /* RX Framing Error */
30#define LEON_REG_UART_STATUS_ERR 0x00000078 /* Error Mask */
31
32/*
33 * The following defines the bits in the LEON UART Ctrl Registers.
34 */
35
36#define LEON_REG_UART_CTRL_RE 0x00000001 /* Receiver enable */
37#define LEON_REG_UART_CTRL_TE 0x00000002 /* Transmitter enable */
38#define LEON_REG_UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */
39#define LEON_REG_UART_CTRL_TI 0x00000008 /* Transmitter irq */
40#define LEON_REG_UART_CTRL_PS 0x00000010 /* Parity select */
41#define LEON_REG_UART_CTRL_PE 0x00000020 /* Parity enable */
42#define LEON_REG_UART_CTRL_FL 0x00000040 /* Flow control enable */
43#define LEON_REG_UART_CTRL_LB 0x00000080 /* Loop Back enable */
44
45#define LEON3_GPTIMER_EN 1
46#define LEON3_GPTIMER_RL 2
47#define LEON3_GPTIMER_LD 4
48#define LEON3_GPTIMER_IRQEN 8
49#define LEON3_GPTIMER_SEPIRQ 8
50
51#define LEON23_REG_TIMER_CONTROL_EN 0x00000001 /* 1 = enable counting */
52/* 0 = hold scalar and counter */
53#define LEON23_REG_TIMER_CONTROL_RL 0x00000002 /* 1 = reload at 0 */
54 /* 0 = stop at 0 */
55#define LEON23_REG_TIMER_CONTROL_LD 0x00000004 /* 1 = load counter */
56 /* 0 = no function */
57#define LEON23_REG_TIMER_CONTROL_IQ 0x00000008 /* 1 = irq enable */
58 /* 0 = no function */
59
60/*
61 * The following defines the bits in the LEON PS/2 Status Registers.
62 */
63
64#define LEON_REG_PS2_STATUS_DR 0x00000001 /* Data Ready */
65#define LEON_REG_PS2_STATUS_PE 0x00000002 /* Parity error */
66#define LEON_REG_PS2_STATUS_FE 0x00000004 /* Framing error */
67#define LEON_REG_PS2_STATUS_KI 0x00000008 /* Keyboard inhibit */
68#define LEON_REG_PS2_STATUS_RF 0x00000010 /* RX buffer full */
69#define LEON_REG_PS2_STATUS_TF 0x00000020 /* TX buffer full */
70
71/*
72 * The following defines the bits in the LEON PS/2 Ctrl Registers.
73 */
74
75#define LEON_REG_PS2_CTRL_RE 0x00000001 /* Receiver enable */
76#define LEON_REG_PS2_CTRL_TE 0x00000002 /* Transmitter enable */
77#define LEON_REG_PS2_CTRL_RI 0x00000004 /* Keyboard receive irq */
78#define LEON_REG_PS2_CTRL_TI 0x00000008 /* Keyboard transmit irq */
79
80#define LEON3_IRQMPSTATUS_CPUNR 28
81#define LEON3_IRQMPSTATUS_BROADCAST 27
82
83#define GPTIMER_CONFIG_IRQNT(a) (((a) >> 3) & 0x1f)
84#define GPTIMER_CONFIG_ISSEP(a) ((a) & (1 << 8))
85#define GPTIMER_CONFIG_NTIMERS(a) ((a) & (0x7))
86#define LEON3_GPTIMER_CTRL_PENDING 0x10
87#define LEON3_GPTIMER_CONFIG_NRTIMERS(c) ((c)->config & 0x7)
88#define LEON3_GPTIMER_CTRL_ISPENDING(r) (((r)&LEON3_GPTIMER_CTRL_PENDING) ? 1 : 0)
89
90#ifdef CONFIG_SPARC_LEON
91
92#ifndef __ASSEMBLY__
93
94struct leon3_irqctrl_regs_map {
95 u32 ilevel;
96 u32 ipend;
97 u32 iforce;
98 u32 iclear;
99 u32 mpstatus;
100 u32 mpbroadcast;
101 u32 notused02;
102 u32 notused03;
103 u32 notused10;
104 u32 notused11;
105 u32 notused12;
106 u32 notused13;
107 u32 notused20;
108 u32 notused21;
109 u32 notused22;
110 u32 notused23;
111 u32 mask[16];
112 u32 force[16];
113 /* Extended IRQ registers */
114 u32 intid[16]; /* 0xc0 */
115};
116
117struct leon3_apbuart_regs_map {
118 u32 data;
119 u32 status;
120 u32 ctrl;
121 u32 scaler;
122};
123
124struct leon3_gptimerelem_regs_map {
125 u32 val;
126 u32 rld;
127 u32 ctrl;
128 u32 unused;
129};
130
131struct leon3_gptimer_regs_map {
132 u32 scalar;
133 u32 scalar_reload;
134 u32 config;
135 u32 unused;
136 struct leon3_gptimerelem_regs_map e[8];
137};
138
139/*
140 * Types and structure used for AMBA Plug & Play bus scanning
141 */
142
143#define AMBA_MAXAPB_DEVS 64
144#define AMBA_MAXAPB_DEVS_PERBUS 16
145
146struct amba_device_table {
147 int devnr; /* number of devices on AHB or APB bus */
148 unsigned int *addr[16]; /* addresses to the devices configuration tables */
149 unsigned int allocbits[1]; /* 0=unallocated, 1=allocated driver */
150};
151
152struct amba_apbslv_device_table {
153 int devnr; /* number of devices on AHB or APB bus */
154 unsigned int *addr[AMBA_MAXAPB_DEVS]; /* addresses to the devices configuration tables */
155 unsigned int apbmst[AMBA_MAXAPB_DEVS]; /* apb master if a entry is a apb slave */
156 unsigned int apbmstidx[AMBA_MAXAPB_DEVS]; /* apb master idx if a entry is a apb slave */
157 unsigned int allocbits[4]; /* 0=unallocated, 1=allocated driver */
158};
159
160struct amba_confarea_type {
161 struct amba_confarea_type *next;/* next bus in chain */
162 struct amba_device_table ahbmst;
163 struct amba_device_table ahbslv;
164 struct amba_apbslv_device_table apbslv;
165 unsigned int apbmst;
166};
167
168/* collect apb slaves */
169struct amba_apb_device {
170 unsigned int start, irq, bus_id;
171 struct amba_confarea_type *bus;
172};
173
174/* collect ahb slaves */
175struct amba_ahb_device {
176 unsigned int start[4], irq, bus_id;
177 struct amba_confarea_type *bus;
178};
179
180struct device_node;
181void _amba_init(struct device_node *dp, struct device_node ***nextp);
182
183extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs;
184extern struct leon3_gptimer_regs_map *leon3_gptimer_regs;
185extern struct amba_apb_device leon_percpu_timer_dev[16];
186extern int leondebug_irq_disable;
187extern int leon_debug_irqout;
188extern unsigned long leon3_gptimer_irq;
189extern unsigned int sparc_leon_eirq;
190
191#endif /* __ASSEMBLY__ */
192
193#define LEON3_IO_AREA 0xfff00000
194#define LEON3_CONF_AREA 0xff000
195#define LEON3_AHB_SLAVE_CONF_AREA (1 << 11)
196
197#define LEON3_AHB_CONF_WORDS 8
198#define LEON3_APB_CONF_WORDS 2
199#define LEON3_AHB_MASTERS 16
200#define LEON3_AHB_SLAVES 16
201#define LEON3_APB_SLAVES 16
202#define LEON3_APBUARTS 8
203
204/* Vendor codes */
205#define VENDOR_GAISLER 1
206#define VENDOR_PENDER 2
207#define VENDOR_ESA 4
208#define VENDOR_OPENCORES 8
209
210/* Gaisler Research device id's */
211#define GAISLER_LEON3 0x003
212#define GAISLER_LEON3DSU 0x004
213#define GAISLER_ETHAHB 0x005
214#define GAISLER_APBMST 0x006
215#define GAISLER_AHBUART 0x007
216#define GAISLER_SRCTRL 0x008
217#define GAISLER_SDCTRL 0x009
218#define GAISLER_APBUART 0x00C
219#define GAISLER_IRQMP 0x00D
220#define GAISLER_AHBRAM 0x00E
221#define GAISLER_GPTIMER 0x011
222#define GAISLER_PCITRG 0x012
223#define GAISLER_PCISBRG 0x013
224#define GAISLER_PCIFBRG 0x014
225#define GAISLER_PCITRACE 0x015
226#define GAISLER_PCIDMA 0x016
227#define GAISLER_AHBTRACE 0x017
228#define GAISLER_ETHDSU 0x018
229#define GAISLER_PIOPORT 0x01A
230#define GAISLER_GRGPIO 0x01A
231#define GAISLER_AHBJTAG 0x01c
232#define GAISLER_ETHMAC 0x01D
233#define GAISLER_AHB2AHB 0x020
234#define GAISLER_USBDC 0x021
235#define GAISLER_ATACTRL 0x024
236#define GAISLER_DDRSPA 0x025
237#define GAISLER_USBEHC 0x026
238#define GAISLER_USBUHC 0x027
239#define GAISLER_I2CMST 0x028
240#define GAISLER_SPICTRL 0x02D
241#define GAISLER_DDR2SPA 0x02E
242#define GAISLER_SPIMCTRL 0x045
243#define GAISLER_LEON4 0x048
244#define GAISLER_LEON4DSU 0x049
245#define GAISLER_AHBSTAT 0x052
246#define GAISLER_FTMCTRL 0x054
247#define GAISLER_KBD 0x060
248#define GAISLER_VGA 0x061
249#define GAISLER_SVGA 0x063
250#define GAISLER_GRSYSMON 0x066
251#define GAISLER_GRACECTRL 0x067
252
253#define GAISLER_L2TIME 0xffd /* internal device: leon2 timer */
254#define GAISLER_L2C 0xffe /* internal device: leon2compat */
255#define GAISLER_PLUGPLAY 0xfff /* internal device: plug & play configarea */
256
257#define amba_vendor(x) (((x) >> 24) & 0xff)
258
259#define amba_device(x) (((x) >> 12) & 0xfff)
260
261#endif /* !defined(CONFIG_SPARC_LEON) */
262
263#endif
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
new file mode 100644
index 00000000000..54d8a5bd482
--- /dev/null
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -0,0 +1,203 @@
1/*
2 * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
3 * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
4 */
5
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/errno.h>
9#include <linux/mutex.h>
10#include <linux/slab.h>
11#include <linux/of.h>
12#include <linux/of_platform.h>
13#include <linux/interrupt.h>
14#include <linux/of_device.h>
15#include <asm/oplib.h>
16#include <asm/timer.h>
17#include <asm/prom.h>
18#include <asm/leon.h>
19#include <asm/leon_amba.h>
20
21#include "prom.h"
22#include "irq.h"
23
24struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */
25struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */
26struct amba_apb_device leon_percpu_timer_dev[16];
27
28int leondebug_irq_disable;
29int leon_debug_irqout;
30static int dummy_master_l10_counter;
31
32unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */
33unsigned int sparc_leon_eirq;
34#define LEON_IMASK ((&leon3_irqctrl_regs->mask[0]))
35
36/* Return the IRQ of the pending IRQ on the extended IRQ controller */
37int sparc_leon_eirq_get(int eirq, int cpu)
38{
39 return LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->intid[cpu]) & 0x1f;
40}
41
42irqreturn_t sparc_leon_eirq_isr(int dummy, void *dev_id)
43{
44 printk(KERN_ERR "sparc_leon_eirq_isr: ERROR EXTENDED IRQ\n");
45 return IRQ_HANDLED;
46}
47
48/* The extended IRQ controller has been found, this function registers it */
49void sparc_leon_eirq_register(int eirq)
50{
51 int irq;
52
53 /* Register a "BAD" handler for this interrupt, it should never happen */
54 irq = request_irq(eirq, sparc_leon_eirq_isr,
55 (IRQF_DISABLED | SA_STATIC_ALLOC), "extirq", NULL);
56
57 if (irq) {
58 printk(KERN_ERR
59 "sparc_leon_eirq_register: unable to attach IRQ%d\n",
60 eirq);
61 } else {
62 sparc_leon_eirq = eirq;
63 }
64
65}
66
67static inline unsigned long get_irqmask(unsigned int irq)
68{
69 unsigned long mask;
70
71 if (!irq || ((irq > 0xf) && !sparc_leon_eirq)
72 || ((irq > 0x1f) && sparc_leon_eirq)) {
73 printk(KERN_ERR
74 "leon_get_irqmask: false irq number: %d\n", irq);
75 mask = 0;
76 } else {
77 mask = LEON_HARD_INT(irq);
78 }
79 return mask;
80}
81
82static void leon_enable_irq(unsigned int irq_nr)
83{
84 unsigned long mask, flags;
85 mask = get_irqmask(irq_nr);
86 local_irq_save(flags);
87 LEON3_BYPASS_STORE_PA(LEON_IMASK,
88 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) | (mask)));
89 local_irq_restore(flags);
90}
91
92static void leon_disable_irq(unsigned int irq_nr)
93{
94 unsigned long mask, flags;
95 mask = get_irqmask(irq_nr);
96 local_irq_save(flags);
97 LEON3_BYPASS_STORE_PA(LEON_IMASK,
98 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) & ~(mask)));
99 local_irq_restore(flags);
100
101}
102
103void __init leon_init_timers(irq_handler_t counter_fn)
104{
105 int irq;
106
107 leondebug_irq_disable = 0;
108 leon_debug_irqout = 0;
109 master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
110 dummy_master_l10_counter = 0;
111
112 if (leon3_gptimer_regs && leon3_irqctrl_regs) {
113 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0);
114 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld,
115 (((1000000 / 100) - 1)));
116 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0);
117
118 } else {
119 printk(KERN_ERR "No Timer/irqctrl found\n");
120 BUG();
121 }
122
123 irq = request_irq(leon3_gptimer_irq,
124 counter_fn,
125 (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
126
127 if (irq) {
128 printk(KERN_ERR "leon_time_init: unable to attach IRQ%d\n",
129 LEON_INTERRUPT_TIMER1);
130 prom_halt();
131 }
132
133 if (leon3_gptimer_regs) {
134 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl,
135 LEON3_GPTIMER_EN |
136 LEON3_GPTIMER_RL |
137 LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
138 }
139}
140
141void leon_clear_clock_irq(void)
142{
143}
144
145void leon_load_profile_irq(int cpu, unsigned int limit)
146{
147 BUG();
148}
149
150
151
152
153void __init leon_trans_init(struct device_node *dp)
154{
155 if (strcmp(dp->type, "cpu") == 0 && strcmp(dp->name, "<NULL>") == 0) {
156 struct property *p;
157 p = of_find_property(dp, "mid", (void *)0);
158 if (p) {
159 int mid;
160 dp->name = prom_early_alloc(5 + 1);
161 memcpy(&mid, p->value, p->length);
162 sprintf((char *)dp->name, "cpu%.2d", mid);
163 }
164 }
165}
166
167void __initdata (*prom_amba_init)(struct device_node *dp, struct device_node ***nextp) = 0;
168
169void __init leon_node_init(struct device_node *dp, struct device_node ***nextp)
170{
171 if (prom_amba_init &&
172 strcmp(dp->type, "ambapp") == 0 &&
173 strcmp(dp->name, "ambapp0") == 0) {
174 prom_amba_init(dp, nextp);
175 }
176}
177
178void __init leon_init_IRQ(void)
179{
180 sparc_init_timers = leon_init_timers;
181
182 BTFIXUPSET_CALL(enable_irq, leon_enable_irq, BTFIXUPCALL_NORM);
183 BTFIXUPSET_CALL(disable_irq, leon_disable_irq, BTFIXUPCALL_NORM);
184 BTFIXUPSET_CALL(enable_pil_irq, leon_enable_irq, BTFIXUPCALL_NORM);
185 BTFIXUPSET_CALL(disable_pil_irq, leon_disable_irq, BTFIXUPCALL_NORM);
186
187 BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq,
188 BTFIXUPCALL_NORM);
189 BTFIXUPSET_CALL(load_profile_irq, leon_load_profile_irq,
190 BTFIXUPCALL_NOP);
191
192#ifdef CONFIG_SMP
193 BTFIXUPSET_CALL(set_cpu_int, leon_set_cpu_int, BTFIXUPCALL_NORM);
194 BTFIXUPSET_CALL(clear_cpu_int, leon_clear_ipi, BTFIXUPCALL_NORM);
195 BTFIXUPSET_CALL(set_irq_udt, leon_set_udt, BTFIXUPCALL_NORM);
196#endif
197
198}
199
200void __init leon_init(void)
201{
202 prom_build_more = &leon_node_init;
203}
diff --git a/arch/sparc/mm/leon_mm.c b/arch/sparc/mm/leon_mm.c
new file mode 100644
index 00000000000..c0e01297e64
--- /dev/null
+++ b/arch/sparc/mm/leon_mm.c
@@ -0,0 +1,260 @@
1/*
2 * linux/arch/sparc/mm/leon_m.c
3 *
4 * Copyright (C) 2004 Konrad Eisele (eiselekd@web.de, konrad@gaisler.com) Gaisler Research
5 * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
6 * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
7 *
8 * do srmmu probe in software
9 *
10 */
11
12#include <linux/kernel.h>
13#include <linux/mm.h>
14#include <asm/asi.h>
15#include <asm/leon.h>
16#include <asm/tlbflush.h>
17
18int leon_flush_during_switch = 1;
19int srmmu_swprobe_trace;
20
21unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr)
22{
23
24 unsigned int ctxtbl;
25 unsigned int pgd, pmd, ped;
26 unsigned int ptr;
27 unsigned int lvl, pte, paddrbase;
28 unsigned int ctx;
29 unsigned int paddr_calc;
30
31 paddrbase = 0;
32
33 if (srmmu_swprobe_trace)
34 printk(KERN_INFO "swprobe: trace on\n");
35
36 ctxtbl = srmmu_get_ctable_ptr();
37 if (!(ctxtbl)) {
38 if (srmmu_swprobe_trace)
39 printk(KERN_INFO "swprobe: srmmu_get_ctable_ptr returned 0=>0\n");
40 return 0;
41 }
42 if (!_pfn_valid(PFN(ctxtbl))) {
43 if (srmmu_swprobe_trace)
44 printk(KERN_INFO
45 "swprobe: !_pfn_valid(%x)=>0\n",
46 PFN(ctxtbl));
47 return 0;
48 }
49
50 ctx = srmmu_get_context();
51 if (srmmu_swprobe_trace)
52 printk(KERN_INFO "swprobe: --- ctx (%x) ---\n", ctx);
53
54 pgd = LEON_BYPASS_LOAD_PA(ctxtbl + (ctx * 4));
55
56 if (((pgd & SRMMU_ET_MASK) == SRMMU_ET_PTE)) {
57 if (srmmu_swprobe_trace)
58 printk(KERN_INFO "swprobe: pgd is entry level 3\n");
59 lvl = 3;
60 pte = pgd;
61 paddrbase = pgd & _SRMMU_PTE_PMASK_LEON;
62 goto ready;
63 }
64 if (((pgd & SRMMU_ET_MASK) != SRMMU_ET_PTD)) {
65 if (srmmu_swprobe_trace)
66 printk(KERN_INFO "swprobe: pgd is invalid => 0\n");
67 return 0;
68 }
69
70 if (srmmu_swprobe_trace)
71 printk(KERN_INFO "swprobe: --- pgd (%x) ---\n", pgd);
72
73 ptr = (pgd & SRMMU_PTD_PMASK) << 4;
74 ptr += ((((vaddr) >> LEON_PGD_SH) & LEON_PGD_M) * 4);
75 if (!_pfn_valid(PFN(ptr)))
76 return 0;
77
78 pmd = LEON_BYPASS_LOAD_PA(ptr);
79 if (((pmd & SRMMU_ET_MASK) == SRMMU_ET_PTE)) {
80 if (srmmu_swprobe_trace)
81 printk(KERN_INFO "swprobe: pmd is entry level 2\n");
82 lvl = 2;
83 pte = pmd;
84 paddrbase = pmd & _SRMMU_PTE_PMASK_LEON;
85 goto ready;
86 }
87 if (((pmd & SRMMU_ET_MASK) != SRMMU_ET_PTD)) {
88 if (srmmu_swprobe_trace)
89 printk(KERN_INFO "swprobe: pmd is invalid => 0\n");
90 return 0;
91 }
92
93 if (srmmu_swprobe_trace)
94 printk(KERN_INFO "swprobe: --- pmd (%x) ---\n", pmd);
95
96 ptr = (pmd & SRMMU_PTD_PMASK) << 4;
97 ptr += (((vaddr >> LEON_PMD_SH) & LEON_PMD_M) * 4);
98 if (!_pfn_valid(PFN(ptr))) {
99 if (srmmu_swprobe_trace)
100 printk(KERN_INFO "swprobe: !_pfn_valid(%x)=>0\n",
101 PFN(ptr));
102 return 0;
103 }
104
105 ped = LEON_BYPASS_LOAD_PA(ptr);
106
107 if (((ped & SRMMU_ET_MASK) == SRMMU_ET_PTE)) {
108 if (srmmu_swprobe_trace)
109 printk(KERN_INFO "swprobe: ped is entry level 1\n");
110 lvl = 1;
111 pte = ped;
112 paddrbase = ped & _SRMMU_PTE_PMASK_LEON;
113 goto ready;
114 }
115 if (((ped & SRMMU_ET_MASK) != SRMMU_ET_PTD)) {
116 if (srmmu_swprobe_trace)
117 printk(KERN_INFO "swprobe: ped is invalid => 0\n");
118 return 0;
119 }
120
121 if (srmmu_swprobe_trace)
122 printk(KERN_INFO "swprobe: --- ped (%x) ---\n", ped);
123
124 ptr = (ped & SRMMU_PTD_PMASK) << 4;
125 ptr += (((vaddr >> LEON_PTE_SH) & LEON_PTE_M) * 4);
126 if (!_pfn_valid(PFN(ptr)))
127 return 0;
128
129 ptr = LEON_BYPASS_LOAD_PA(ptr);
130 if (((ptr & SRMMU_ET_MASK) == SRMMU_ET_PTE)) {
131 if (srmmu_swprobe_trace)
132 printk(KERN_INFO "swprobe: ptr is entry level 0\n");
133 lvl = 0;
134 pte = ptr;
135 paddrbase = ptr & _SRMMU_PTE_PMASK_LEON;
136 goto ready;
137 }
138 if (srmmu_swprobe_trace)
139 printk(KERN_INFO "swprobe: ptr is invalid => 0\n");
140 return 0;
141
142ready:
143 switch (lvl) {
144 case 0:
145 paddr_calc =
146 (vaddr & ~(-1 << LEON_PTE_SH)) | ((pte & ~0xff) << 4);
147 break;
148 case 1:
149 paddr_calc =
150 (vaddr & ~(-1 << LEON_PMD_SH)) | ((pte & ~0xff) << 4);
151 break;
152 case 2:
153 paddr_calc =
154 (vaddr & ~(-1 << LEON_PGD_SH)) | ((pte & ~0xff) << 4);
155 break;
156 default:
157 case 3:
158 paddr_calc = vaddr;
159 break;
160 }
161 if (srmmu_swprobe_trace)
162 printk(KERN_INFO "swprobe: padde %x\n", paddr_calc);
163 if (paddr)
164 *paddr = paddr_calc;
165 return paddrbase;
166}
167
168void leon_flush_icache_all(void)
169{
170 __asm__ __volatile__(" flush "); /*iflush*/
171}
172
173void leon_flush_dcache_all(void)
174{
175 __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : :
176 "i"(ASI_LEON_DFLUSH) : "memory");
177}
178
179void leon_flush_pcache_all(struct vm_area_struct *vma, unsigned long page)
180{
181 if (vma->vm_flags & VM_EXEC)
182 leon_flush_icache_all();
183 leon_flush_dcache_all();
184}
185
186void leon_flush_cache_all(void)
187{
188 __asm__ __volatile__(" flush "); /*iflush*/
189 __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : :
190 "i"(ASI_LEON_DFLUSH) : "memory");
191}
192
193void leon_flush_tlb_all(void)
194{
195 leon_flush_cache_all();
196 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : "r"(0x400),
197 "i"(ASI_LEON_MMUFLUSH) : "memory");
198}
199
200/* get all cache regs */
201void leon3_getCacheRegs(struct leon3_cacheregs *regs)
202{
203 unsigned long ccr, iccr, dccr;
204
205 if (!regs)
206 return;
207 /* Get Cache regs from "Cache ASI" address 0x0, 0x8 and 0xC */
208 __asm__ __volatile__("lda [%%g0] %3, %0\n\t"
209 "mov 0x08, %%g1\n\t"
210 "lda [%%g1] %3, %1\n\t"
211 "mov 0x0c, %%g1\n\t"
212 "lda [%%g1] %3, %2\n\t"
213 : "=r"(ccr), "=r"(iccr), "=r"(dccr)
214 /* output */
215 : "i"(ASI_LEON_CACHEREGS) /* input */
216 : "g1" /* clobber list */
217 );
218 regs->ccr = ccr;
219 regs->iccr = iccr;
220 regs->dccr = dccr;
221}
222
223/* Due to virtual cache we need to check cache configuration if
224 * it is possible to skip flushing in some cases.
225 *
226 * Leon2 and Leon3 differ in their way of telling cache information
227 *
228 */
229int leon_flush_needed(void)
230{
231 int flush_needed = -1;
232 unsigned int ssize, sets;
233 char *setStr[4] =
234 { "direct mapped", "2-way associative", "3-way associative",
235 "4-way associative"
236 };
237 /* leon 3 */
238 struct leon3_cacheregs cregs;
239 leon3_getCacheRegs(&cregs);
240 sets = (cregs.dccr & LEON3_XCCR_SETS_MASK) >> 24;
241 /* (ssize=>realsize) 0=>1k, 1=>2k, 2=>4k, 3=>8k ... */
242 ssize = 1 << ((cregs.dccr & LEON3_XCCR_SSIZE_MASK) >> 20);
243
244 printk(KERN_INFO "CACHE: %s cache, set size %dk\n",
245 sets > 3 ? "unknown" : setStr[sets], ssize);
246 if ((ssize <= (PAGE_SIZE / 1024)) && (sets == 0)) {
247 /* Set Size <= Page size ==>
248 flush on every context switch not needed. */
249 flush_needed = 0;
250 printk(KERN_INFO "CACHE: not flushing on every context switch\n");
251 }
252 return flush_needed;
253}
254
255void leon_switch_mm(void)
256{
257 flush_tlb_mm((void *)0);
258 if (leon_flush_during_switch)
259 leon_flush_cache_all();
260}