aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-04-03 18:15:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-03 18:15:25 -0400
commit4e76c5ccd5ac9bd003467d3bb0f49b18572dd4cd (patch)
tree1c1b58b1964fec04ae7f830b53a47f1693993135 /arch/xtensa/kernel
parentb983471794e568fd71fa767da77a62ba517c3e63 (diff)
parent65127d28e312bb6b38ce84a7bb71d762ef63ad4c (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/czankel/xtensa-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/czankel/xtensa-2.6: (21 commits) xtensa: we don't need to include asm/io.h xtensa: only build platform or variant if they contain a Makefile xtensa: make startup code discardable xtensa: ccount clocksource xtensa: remove platform rtc hooks xtensa: use generic sched_clock() xtensa: platform: s6105 xtensa: let platform override KERNELOFFSET xtensa: s6000 variant xtensa: s6000 variant core definitions xtensa: variant irq set callbacks xtensa: variant-specific code xtensa: nommu support xtensa: add flat support xtensa: enforce slab alignment to maximum register width xtensa: cope with ram beginning at higher addresses xtensa: don't make bootmem bitmap larger than required xtensa: fix init_bootmem_node() argument order xtensa: use correct stack pointer for stack traces xtensa: beat Kconfig into shape ...
Diffstat (limited to 'arch/xtensa/kernel')
-rw-r--r--arch/xtensa/kernel/entry.S3
-rw-r--r--arch/xtensa/kernel/head.S5
-rw-r--r--arch/xtensa/kernel/irq.c14
-rw-r--r--arch/xtensa/kernel/platform.c2
-rw-r--r--arch/xtensa/kernel/setup.c7
-rw-r--r--arch/xtensa/kernel/time.c131
-rw-r--r--arch/xtensa/kernel/traps.c16
-rw-r--r--arch/xtensa/kernel/vectors.S4
-rw-r--r--arch/xtensa/kernel/vmlinux.lds.S3
9 files changed, 67 insertions, 118 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index a51d36a27389..80d24c485fd3 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1463,6 +1463,7 @@ ENTRY(_spill_registers)
1463 callx0 a0 # should not return 1463 callx0 a0 # should not return
14641: j 1b 14641: j 1b
1465 1465
1466#ifdef CONFIG_MMU
1466/* 1467/*
1467 * We should never get here. Bail out! 1468 * We should never get here. Bail out!
1468 */ 1469 */
@@ -1775,7 +1776,7 @@ ENTRY(fast_store_prohibited)
1775 bbsi.l a2, PS_UM_BIT, 1f 1776 bbsi.l a2, PS_UM_BIT, 1f
1776 j _kernel_exception 1777 j _kernel_exception
17771: j _user_exception 17781: j _user_exception
1778 1779#endif /* CONFIG_MMU */
1779 1780
1780/* 1781/*
1781 * System Calls. 1782 * System Calls.
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
index 67e69139520b..0817f9db836e 100644
--- a/arch/xtensa/kernel/head.S
+++ b/arch/xtensa/kernel/head.S
@@ -53,7 +53,7 @@ _start: _j 2f
532: l32r a0, 1b 532: l32r a0, 1b
54 jx a0 54 jx a0
55 55
56 .text 56 .section .init.text, "ax"
57 .align 4 57 .align 4
58_startup: 58_startup:
59 59
@@ -235,8 +235,9 @@ should_never_return:
235 */ 235 */
236 236
237.section ".bss.page_aligned", "w" 237.section ".bss.page_aligned", "w"
238#ifdef CONFIG_MMU
238ENTRY(swapper_pg_dir) 239ENTRY(swapper_pg_dir)
239 .fill PAGE_SIZE, 1, 0 240 .fill PAGE_SIZE, 1, 0
241#endif
240ENTRY(empty_zero_page) 242ENTRY(empty_zero_page)
241 .fill PAGE_SIZE, 1, 0 243 .fill PAGE_SIZE, 1, 0
242
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index f3b66fba5b8f..a36c85edd045 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -132,6 +132,18 @@ static void xtensa_irq_unmask(unsigned int irq)
132 set_sr (cached_irq_mask, INTENABLE); 132 set_sr (cached_irq_mask, INTENABLE);
133} 133}
134 134
135static void xtensa_irq_enable(unsigned int irq)
136{
137 variant_irq_enable(irq);
138 xtensa_irq_unmask(irq);
139}
140
141static void xtensa_irq_disable(unsigned int irq)
142{
143 xtensa_irq_mask(irq);
144 variant_irq_disable(irq);
145}
146
135static void xtensa_irq_ack(unsigned int irq) 147static void xtensa_irq_ack(unsigned int irq)
136{ 148{
137 set_sr(1 << irq, INTCLEAR); 149 set_sr(1 << irq, INTCLEAR);
@@ -146,6 +158,8 @@ static int xtensa_irq_retrigger(unsigned int irq)
146 158
147static struct irq_chip xtensa_irq_chip = { 159static struct irq_chip xtensa_irq_chip = {
148 .name = "xtensa", 160 .name = "xtensa",
161 .enable = xtensa_irq_enable,
162 .disable = xtensa_irq_disable,
149 .mask = xtensa_irq_mask, 163 .mask = xtensa_irq_mask,
150 .unmask = xtensa_irq_unmask, 164 .unmask = xtensa_irq_unmask,
151 .ack = xtensa_irq_ack, 165 .ack = xtensa_irq_ack,
diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c
index 69675f216062..1b91a97f1d84 100644
--- a/arch/xtensa/kernel/platform.c
+++ b/arch/xtensa/kernel/platform.c
@@ -36,8 +36,6 @@ _F(void, power_off, (void), { while(1); });
36_F(void, idle, (void), { __asm__ __volatile__ ("waiti 0" ::: "memory"); }); 36_F(void, idle, (void), { __asm__ __volatile__ ("waiti 0" ::: "memory"); });
37_F(void, heartbeat, (void), { }); 37_F(void, heartbeat, (void), { });
38_F(int, pcibios_fixup, (void), { return 0; }); 38_F(int, pcibios_fixup, (void), { return 0; });
39_F(int, get_rtc_time, (time_t* t), { return 0; });
40_F(int, set_rtc_time, (time_t t), { return 0; });
41 39
42#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT 40#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
43_F(void, calibrate_ccount, (void), 41_F(void, calibrate_ccount, (void),
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 4ec1633c2941..1e5a034fe011 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -84,7 +84,13 @@ sysmem_info_t __initdata sysmem;
84int initrd_is_mapped; 84int initrd_is_mapped;
85#endif 85#endif
86 86
87#ifdef CONFIG_MMU
87extern void init_mmu(void); 88extern void init_mmu(void);
89#else
90static inline void init_mmu(void) { }
91#endif
92
93extern void zones_init(void);
88 94
89/* 95/*
90 * Boot parameter parsing. 96 * Boot parameter parsing.
@@ -286,6 +292,7 @@ void __init setup_arch(char **cmdline_p)
286 292
287 293
288 paging_init(); 294 paging_init();
295 zones_init();
289 296
290#ifdef CONFIG_VT 297#ifdef CONFIG_VT
291# if defined(CONFIG_VGA_CONSOLE) 298# if defined(CONFIG_VGA_CONSOLE)
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index 8df1e842f6d4..8848120d291b 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -14,7 +14,7 @@
14 14
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/time.h> 16#include <linux/time.h>
17#include <linux/timex.h> 17#include <linux/clocksource.h>
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/init.h> 20#include <linux/init.h>
@@ -25,27 +25,31 @@
25#include <asm/timex.h> 25#include <asm/timex.h>
26#include <asm/platform.h> 26#include <asm/platform.h>
27 27
28
29DEFINE_SPINLOCK(rtc_lock);
30EXPORT_SYMBOL(rtc_lock);
31
32
33#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT 28#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
34unsigned long ccount_per_jiffy; /* per 1/HZ */ 29unsigned long ccount_per_jiffy; /* per 1/HZ */
35unsigned long nsec_per_ccount; /* nsec per ccount increment */ 30unsigned long nsec_per_ccount; /* nsec per ccount increment */
36#endif 31#endif
37 32
38static long last_rtc_update = 0; 33static cycle_t ccount_read(void)
39
40/*
41 * Scheduler clock - returns current tim in nanosec units.
42 */
43
44unsigned long long sched_clock(void)
45{ 34{
46 return (unsigned long long)jiffies * (1000000000 / HZ); 35 return (cycle_t)get_ccount();
47} 36}
48 37
38static struct clocksource ccount_clocksource = {
39 .name = "ccount",
40 .rating = 200,
41 .read = ccount_read,
42 .mask = CLOCKSOURCE_MASK(32),
43 /*
44 * With a shift of 22 the lower limit of the cpu clock is
45 * 1MHz, where NSEC_PER_CCOUNT is 1000 or a bit less than
46 * 2^10: Since we have 32 bits and the multiplicator can
47 * already take up as much as 10 bits, this leaves us with
48 * remaining upper 22 bits.
49 */
50 .shift = 22,
51};
52
49static irqreturn_t timer_interrupt(int irq, void *dev_id); 53static irqreturn_t timer_interrupt(int irq, void *dev_id);
50static struct irqaction timer_irqaction = { 54static struct irqaction timer_irqaction = {
51 .handler = timer_interrupt, 55 .handler = timer_interrupt,
@@ -55,11 +59,11 @@ static struct irqaction timer_irqaction = {
55 59
56void __init time_init(void) 60void __init time_init(void)
57{ 61{
58 time_t sec_o, sec_n = 0; 62 xtime.tv_nsec = 0;
63 xtime.tv_sec = read_persistent_clock();
59 64
60 /* The platform must provide a function to calibrate the processor 65 set_normalized_timespec(&wall_to_monotonic,
61 * speed for the CALIBRATE. 66 -xtime.tv_sec, -xtime.tv_nsec);
62 */
63 67
64#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT 68#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
65 printk("Calibrating CPU frequency "); 69 printk("Calibrating CPU frequency ");
@@ -67,19 +71,10 @@ void __init time_init(void)
67 printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ), 71 printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ),
68 (int)(ccount_per_jiffy/(10000/HZ))%100); 72 (int)(ccount_per_jiffy/(10000/HZ))%100);
69#endif 73#endif
70 74 ccount_clocksource.mult =
71 /* Set time from RTC (if provided) */ 75 clocksource_hz2mult(CCOUNT_PER_JIFFY * HZ,
72 76 ccount_clocksource.shift);
73 if (platform_get_rtc_time(&sec_o) == 0) 77 clocksource_register(&ccount_clocksource);
74 while (platform_get_rtc_time(&sec_n))
75 if (sec_o != sec_n)
76 break;
77
78 xtime.tv_nsec = 0;
79 last_rtc_update = xtime.tv_sec = sec_n;
80
81 set_normalized_timespec(&wall_to_monotonic,
82 -xtime.tv_sec, -xtime.tv_nsec);
83 78
84 /* Initialize the linux timer interrupt. */ 79 /* Initialize the linux timer interrupt. */
85 80
@@ -87,69 +82,6 @@ void __init time_init(void)
87 set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY); 82 set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY);
88} 83}
89 84
90
91int do_settimeofday(struct timespec *tv)
92{
93 time_t wtm_sec, sec = tv->tv_sec;
94 long wtm_nsec, nsec = tv->tv_nsec;
95 unsigned long delta;
96
97 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
98 return -EINVAL;
99
100 write_seqlock_irq(&xtime_lock);
101
102 /* This is revolting. We need to set "xtime" correctly. However, the
103 * value in this location is the value at the most recent update of
104 * wall time. Discover what correction gettimeofday() would have
105 * made, and then undo it!
106 */
107
108 delta = CCOUNT_PER_JIFFY;
109 delta += get_ccount() - get_linux_timer();
110 nsec -= delta * NSEC_PER_CCOUNT;
111
112 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
113 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
114
115 set_normalized_timespec(&xtime, sec, nsec);
116 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
117
118 ntp_clear();
119 write_sequnlock_irq(&xtime_lock);
120 return 0;
121}
122
123EXPORT_SYMBOL(do_settimeofday);
124
125
126void do_gettimeofday(struct timeval *tv)
127{
128 unsigned long flags;
129 unsigned long volatile sec, usec, delta, seq;
130
131 do {
132 seq = read_seqbegin_irqsave(&xtime_lock, flags);
133
134 sec = xtime.tv_sec;
135 usec = (xtime.tv_nsec / NSEC_PER_USEC);
136
137 delta = get_linux_timer() - get_ccount();
138
139 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
140
141 usec += (((unsigned long) CCOUNT_PER_JIFFY - delta)
142 * (unsigned long) NSEC_PER_CCOUNT) / NSEC_PER_USEC;
143
144 for (; usec >= 1000000; sec++, usec -= 1000000)
145 ;
146
147 tv->tv_sec = sec;
148 tv->tv_usec = usec;
149}
150
151EXPORT_SYMBOL(do_gettimeofday);
152
153/* 85/*
154 * The timer interrupt is called HZ times per second. 86 * The timer interrupt is called HZ times per second.
155 */ 87 */
@@ -178,16 +110,6 @@ again:
178 next += CCOUNT_PER_JIFFY; 110 next += CCOUNT_PER_JIFFY;
179 set_linux_timer(next); 111 set_linux_timer(next);
180 112
181 if (ntp_synced() &&
182 xtime.tv_sec - last_rtc_update >= 659 &&
183 abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ) {
184
185 if (platform_set_rtc_time(xtime.tv_sec+1) == 0)
186 last_rtc_update = xtime.tv_sec+1;
187 else
188 /* Do it again in 60 s */
189 last_rtc_update += 60;
190 }
191 write_sequnlock(&xtime_lock); 113 write_sequnlock(&xtime_lock);
192 } 114 }
193 115
@@ -213,4 +135,3 @@ void __cpuinit calibrate_delay(void)
213 (loops_per_jiffy/(10000/HZ)) % 100); 135 (loops_per_jiffy/(10000/HZ)) % 100);
214} 136}
215#endif 137#endif
216
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index c44f830b6c7a..9f0b71189e94 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -104,6 +104,7 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = {
104#endif 104#endif
105{ EXCCAUSE_UNALIGNED, KRNL, fast_unaligned }, 105{ EXCCAUSE_UNALIGNED, KRNL, fast_unaligned },
106#endif 106#endif
107#ifdef CONFIG_MMU
107{ EXCCAUSE_ITLB_MISS, 0, do_page_fault }, 108{ EXCCAUSE_ITLB_MISS, 0, do_page_fault },
108{ EXCCAUSE_ITLB_MISS, USER|KRNL, fast_second_level_miss}, 109{ EXCCAUSE_ITLB_MISS, USER|KRNL, fast_second_level_miss},
109{ EXCCAUSE_ITLB_MULTIHIT, 0, do_multihit }, 110{ EXCCAUSE_ITLB_MULTIHIT, 0, do_multihit },
@@ -118,6 +119,7 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = {
118{ EXCCAUSE_STORE_CACHE_ATTRIBUTE, USER|KRNL, fast_store_prohibited }, 119{ EXCCAUSE_STORE_CACHE_ATTRIBUTE, USER|KRNL, fast_store_prohibited },
119{ EXCCAUSE_STORE_CACHE_ATTRIBUTE, 0, do_page_fault }, 120{ EXCCAUSE_STORE_CACHE_ATTRIBUTE, 0, do_page_fault },
120{ EXCCAUSE_LOAD_CACHE_ATTRIBUTE, 0, do_page_fault }, 121{ EXCCAUSE_LOAD_CACHE_ATTRIBUTE, 0, do_page_fault },
122#endif /* CONFIG_MMU */
121/* XCCHAL_EXCCAUSE_FLOATING_POINT unhandled */ 123/* XCCHAL_EXCCAUSE_FLOATING_POINT unhandled */
122#if XTENSA_HAVE_COPROCESSOR(0) 124#if XTENSA_HAVE_COPROCESSOR(0)
123COPROCESSOR(0), 125COPROCESSOR(0),
@@ -372,11 +374,10 @@ void show_trace(struct task_struct *task, unsigned long *sp)
372 unsigned long a0, a1, pc; 374 unsigned long a0, a1, pc;
373 unsigned long sp_start, sp_end; 375 unsigned long sp_start, sp_end;
374 376
375 a1 = (unsigned long)sp; 377 if (sp)
376 378 a1 = (unsigned long)sp;
377 if (a1 == 0) 379 else
378 __asm__ __volatile__ ("mov %0, a1\n" : "=a"(a1)); 380 a1 = task->thread.sp;
379
380 381
381 sp_start = a1 & ~(THREAD_SIZE-1); 382 sp_start = a1 & ~(THREAD_SIZE-1);
382 sp_end = sp_start + THREAD_SIZE; 383 sp_end = sp_start + THREAD_SIZE;
@@ -418,9 +419,8 @@ void show_stack(struct task_struct *task, unsigned long *sp)
418 int i = 0; 419 int i = 0;
419 unsigned long *stack; 420 unsigned long *stack;
420 421
421 if (sp == 0) 422 if (!sp)
422 __asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp)); 423 sp = (unsigned long *)task->thread.sp;
423
424 stack = sp; 424 stack = sp;
425 425
426 printk("\nStack: "); 426 printk("\nStack: ");
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index eb2d7bb69ee0..74a7518faf16 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -309,6 +309,7 @@ ENTRY(_DoubleExceptionVector)
309 * All other exceptions are unexpected and thus unrecoverable! 309 * All other exceptions are unexpected and thus unrecoverable!
310 */ 310 */
311 311
312#ifdef CONFIG_MMU
312 .extern fast_second_level_miss_double_kernel 313 .extern fast_second_level_miss_double_kernel
313 314
314.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */ 315.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */
@@ -319,6 +320,9 @@ ENTRY(_DoubleExceptionVector)
319 bnez a3, .Lunrecoverable 320 bnez a3, .Lunrecoverable
3201: movi a3, fast_second_level_miss_double_kernel 3211: movi a3, fast_second_level_miss_double_kernel
321 jx a3 322 jx a3
323#else
324.equ .Lksp, .Lunrecoverable
325#endif
322 326
323 /* Critical! We can't handle this situation. PANIC! */ 327 /* Critical! We can't handle this situation. PANIC! */
324 328
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index d506774f4b05..c1be9a4a740c 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -17,6 +17,7 @@
17#include <asm-generic/vmlinux.lds.h> 17#include <asm-generic/vmlinux.lds.h>
18 18
19#include <variant/core.h> 19#include <variant/core.h>
20#include <platform/hardware.h>
20OUTPUT_ARCH(xtensa) 21OUTPUT_ARCH(xtensa)
21ENTRY(_start) 22ENTRY(_start)
22 23
@@ -26,7 +27,9 @@ jiffies = jiffies_64 + 4;
26jiffies = jiffies_64; 27jiffies = jiffies_64;
27#endif 28#endif
28 29
30#ifndef KERNELOFFSET
29#define KERNELOFFSET 0xd0001000 31#define KERNELOFFSET 0xd0001000
32#endif
30 33
31/* Note: In the following macros, it would be nice to specify only the 34/* Note: In the following macros, it would be nice to specify only the
32 vector name and section kind and construct "sym" and "section" using 35 vector name and section kind and construct "sym" and "section" using