xref: /openbmc/u-boot/arch/arm/cpu/pxa/start.S (revision 5a75e121)
1/*
2 *  armboot - Startup Code for XScale
3 *
4 *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
5 *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
6 *  Copyright (C) 2000	Wolfgang Denk <wd@denx.de>
7 *  Copyright (C) 2001	Alex Zuepke <azu@sysgo.de>
8 *  Copyright (C) 2002	Kyle Harris <kharris@nexus-tech.net>
9 *  Copyright (C) 2003	Robert Schwebel <r.schwebel@pengutronix.de>
10 *  Copyright (C) 2003	Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>
11 *
12 * See file CREDITS for list of people who contributed to this
13 * project.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 * MA 02111-1307 USA
29 */
30
31#include <config.h>
32#include <version.h>
33#include <asm/arch/pxa-regs.h>
34
35.globl _start
36_start: b	reset
37#ifdef CONFIG_PRELOADER
38	ldr	pc, _hang
39	ldr	pc, _hang
40	ldr	pc, _hang
41	ldr	pc, _hang
42	ldr	pc, _hang
43	ldr	pc, _hang
44	ldr	pc, _hang
45
46_hang:
47	.word	do_hang
48	.word	0x12345678
49	.word	0x12345678
50	.word	0x12345678
51	.word	0x12345678
52	.word	0x12345678
53	.word	0x12345678
54	.word	0x12345678	/* now 16*4=64 */
55#else
56	ldr	pc, _undefined_instruction
57	ldr	pc, _software_interrupt
58	ldr	pc, _prefetch_abort
59	ldr	pc, _data_abort
60	ldr	pc, _not_used
61	ldr	pc, _irq
62	ldr	pc, _fiq
63
64_undefined_instruction: .word undefined_instruction
65_software_interrupt:	.word software_interrupt
66_prefetch_abort:	.word prefetch_abort
67_data_abort:		.word data_abort
68_not_used:		.word not_used
69_irq:			.word irq
70_fiq:			.word fiq
71#endif	/* CONFIG_PRELOADER */
72
73	.balignl 16,0xdeadbeef
74
75
76/*
77 * Startup Code (reset vector)
78 *
79 * do important init only if we don't start from RAM!
80 * - relocate armboot to RAM
81 * - setup stack
82 * - jump to second stage
83 */
84
85.globl _TEXT_BASE
86_TEXT_BASE:
87	.word	CONFIG_SYS_TEXT_BASE
88
89#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
90.globl _armboot_start
91_armboot_start:
92	.word _start
93#endif
94
95/*
96 * These are defined in the board-specific linker script.
97 */
98.globl _bss_start
99_bss_start:
100	.word __bss_start
101
102.globl _bss_end
103_bss_end:
104	.word _end
105
106#ifdef CONFIG_USE_IRQ
107/* IRQ stack memory (calculated at run-time) */
108.globl IRQ_STACK_START
109IRQ_STACK_START:
110	.word	0x0badc0de
111
112/* IRQ stack memory (calculated at run-time) */
113.globl FIQ_STACK_START
114FIQ_STACK_START:
115	.word 0x0badc0de
116#endif /* CONFIG_USE_IRQ */
117
118#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
119/* IRQ stack memory (calculated at run-time) + 8 bytes */
120.globl IRQ_STACK_START_IN
121IRQ_STACK_START_IN:
122	.word	0x0badc0de
123
124.globl _datarel_start
125_datarel_start:
126	.word __datarel_start
127
128.globl _datarelrolocal_start
129_datarelrolocal_start:
130	.word __datarelrolocal_start
131
132.globl _datarellocal_start
133_datarellocal_start:
134	.word __datarellocal_start
135
136.globl _datarelro_start
137_datarelro_start:
138	.word __datarelro_start
139
140.globl _got_start
141_got_start:
142	.word __got_start
143
144.globl _got_end
145_got_end:
146	.word __got_end
147
148/*
149 * the actual reset code
150 */
151
152reset:
153	/*
154	 * set the cpu to SVC32 mode
155	 */
156	mrs	r0,cpsr
157	bic	r0,r0,#0x1f
158	orr	r0,r0,#0xd3
159	msr	cpsr,r0
160
161	/*
162	 * we do sys-critical inits only at reboot,
163	 * not when booting from ram!
164	 */
165#ifndef CONFIG_SKIP_LOWLEVEL_INIT
166	bl	cpu_init_crit
167#endif
168
169/* Set stackpointer in internal RAM to call board_init_f */
170call_board_init_f:
171	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
172	ldr	r0,=0x00000000
173	bl	board_init_f
174
175/*------------------------------------------------------------------------------*/
176
177/*
178 * void relocate_code (addr_sp, gd, addr_moni)
179 *
180 * This "function" does not return, instead it continues in RAM
181 * after relocating the monitor code.
182 *
183 */
184	.globl	relocate_code
185relocate_code:
186	mov	r4, r0	/* save addr_sp */
187	mov	r5, r1	/* save addr of gd */
188	mov	r6, r2	/* save addr of destination */
189	mov	r7, r2	/* save addr of destination */
190
191	/* Set up the stack						    */
192stack_setup:
193	mov	sp, r4
194
195	adr	r0, _start
196	ldr	r2, _TEXT_BASE
197	ldr	r3, _bss_start
198	sub	r2, r3, r2		/* r2 <- size of armboot	    */
199	add	r2, r0, r2		/* r2 <- source end address	    */
200	cmp	r0, r6
201	beq	clear_bss
202
203#ifndef CONFIG_SKIP_RELOCATE_UBOOT
204copy_loop:
205	ldmia	r0!, {r9-r10}		/* copy from source address [r0]    */
206	stmia	r6!, {r9-r10}		/* copy to   target address [r1]    */
207	cmp	r0, r2			/* until source end address [r2]    */
208	blo	copy_loop
209
210#ifndef CONFIG_PRELOADER
211	/* fix got entries */
212	ldr	r1, _TEXT_BASE		/* Text base */
213	mov	r0, r7			/* reloc addr */
214	ldr	r2, _got_start		/* addr in Flash */
215	ldr	r3, _got_end		/* addr in Flash */
216	sub	r3, r3, r1
217	add	r3, r3, r0
218	sub	r2, r2, r1
219	add	r2, r2, r0
220
221fixloop:
222	ldr	r4, [r2]
223	sub	r4, r4, r1
224	add	r4, r4, r0
225	str	r4, [r2]
226	add	r2, r2, #4
227	cmp	r2, r3
228	bne	fixloop
229#endif
230#endif	/* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
231
232clear_bss:
233#ifndef CONFIG_PRELOADER
234	ldr	r0, _bss_start
235	ldr	r1, _bss_end
236	ldr	r3, _TEXT_BASE		/* Text base */
237	mov	r4, r7			/* reloc addr */
238	sub	r0, r0, r3
239	add	r0, r0, r4
240	sub	r1, r1, r3
241	add	r1, r1, r4
242	mov	r2, #0x00000000		/* clear			    */
243
244clbss_l:str	r2, [r0]		/* clear loop...		    */
245	add	r0, r0, #4
246	cmp	r0, r1
247	bne	clbss_l
248#endif
249
250/*
251 * We are done. Do not return, instead branch to second part of board
252 * initialization, now running from RAM.
253 */
254#ifdef CONFIG_ONENAND_IPL
255	ldr     pc, _start_oneboot
256
257_start_oneboot: .word start_oneboot
258#else
259	ldr	r0, _TEXT_BASE
260	ldr	r2, _board_init_r
261	sub	r2, r2, r0
262	add	r2, r2, r7	/* position from board_init_r in RAM */
263	/* setup parameters for board_init_r */
264	mov	r0, r5		/* gd_t */
265	mov	r1, r7		/* dest_addr */
266	/* jump to it ... */
267	mov	lr, r2
268	mov	pc, lr
269
270_board_init_r: .word board_init_r
271#endif
272
273#else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
274
275/****************************************************************************/
276/*									    */
277/* the actual reset code						    */
278/*									    */
279/****************************************************************************/
280
281reset:
282	mrs	r0,cpsr			/* set the CPU to SVC32 mode	    */
283	bic	r0,r0,#0x1f		/* (superviser mode, M=10011)	    */
284	orr	r0,r0,#0x13
285	msr	cpsr,r0
286
287	/*
288	 * we do sys-critical inits only at reboot,
289	 * not when booting from RAM!
290	 */
291#ifndef CONFIG_SKIP_LOWLEVEL_INIT
292	bl	cpu_init_crit		/* we do sys-critical inits	    */
293#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
294
295#ifndef CONFIG_SKIP_RELOCATE_UBOOT
296relocate:				/* relocate U-Boot to RAM	    */
297	adr	r0, _start		/* r0 <- current position of code   */
298	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
299#ifndef	CONFIG_PRELOADER
300	cmp	r0, r1			/* don't reloc during debug	    */
301	beq	stack_setup
302#endif
303
304	ldr	r2, _armboot_start
305	ldr	r3, _bss_start
306	sub	r2, r3, r2		/* r2 <- size of armboot	    */
307	add	r2, r0, r2		/* r2 <- source end address	    */
308
309copy_loop:
310	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
311	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
312	cmp	r0, r2			/* until source end address [r2]    */
313	blo	copy_loop
314#endif /* !CONFIG_SKIP_RELOCATE_UBOOT */
315
316	/* Set up the stack						    */
317stack_setup:
318	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
319#ifdef CONFIG_PRELOADER
320	sub	sp, r0, #128		/* leave 32 words for abort-stack   */
321#else
322	sub	r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area		    */
323	sub	r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo		    */
324#ifdef CONFIG_USE_IRQ
325	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
326#endif /* CONFIG_USE_IRQ */
327	sub	sp, r0, #12		/* leave 3 words for abort-stack    */
328	bic	sp, sp, #7		/* 8-byte alignment for ABI compliance */
329#endif
330
331clear_bss:
332	ldr	r0, _bss_start		/* find start of bss segment	    */
333	ldr	r1, _bss_end		/* stop here			    */
334	mov	r2, #0x00000000		/* clear			    */
335
336#ifndef CONFIG_PRELOADER
337clbss_l:str	r2, [r0]		/* clear loop...		    */
338	add	r0, r0, #4
339	cmp	r0, r1
340	blo	clbss_l
341#endif
342
343	ldr	pc, _start_armboot
344
345#ifdef CONFIG_ONENAND_IPL
346_start_armboot: .word start_oneboot
347#else
348_start_armboot: .word start_armboot
349#endif
350#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
351
352/****************************************************************************/
353/*									    */
354/* CPU_init_critical registers						    */
355/*									    */
356/* - setup important registers						    */
357/* - setup memory timing						    */
358/*									    */
359/****************************************************************************/
360/* mk@tbd: Fix this! */
361#undef RCSR
362#undef ICMR
363#undef OSMR3
364#undef OSCR
365#undef OWER
366#undef OIER
367#undef CCCR
368
369/* Interrupt-Controller base address					    */
370IC_BASE:	   .word	   0x40d00000
371#define ICMR	0x04
372
373/* Reset-Controller */
374RST_BASE:	.word	0x40f00030
375#define RCSR	0x00
376
377/* Operating System Timer */
378OSTIMER_BASE:	.word	0x40a00000
379#define OSMR3	0x0C
380#define OSCR	0x10
381#define OWER	0x18
382#define OIER	0x1C
383
384/* Clock Manager Registers						    */
385#ifdef CONFIG_CPU_MONAHANS
386# ifndef CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO
387#  error "You have to define CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO!!"
388# endif /* !CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO */
389# ifndef CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO
390#  define CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 0x1
391# endif /* !CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO */
392#else /* !CONFIG_CPU_MONAHANS */
393#ifdef CONFIG_SYS_CPUSPEED
394CC_BASE:	.word	0x41300000
395#define CCCR	0x00
396cpuspeed:	.word	CONFIG_SYS_CPUSPEED
397#else /* !CONFIG_SYS_CPUSPEED */
398#error "You have to define CONFIG_SYS_CPUSPEED!!"
399#endif /* CONFIG_SYS_CPUSPEED */
400#endif /* CONFIG_CPU_MONAHANS */
401
402	/* takes care the CP15 update has taken place */
403	.macro CPWAIT reg
404	mrc  p15,0,\reg,c2,c0,0
405	mov  \reg,\reg
406	sub  pc,pc,#4
407	.endm
408
409cpu_init_crit:
410
411	/* mask all IRQs						    */
412#ifndef CONFIG_CPU_MONAHANS
413	ldr	r0, IC_BASE
414	mov	r1, #0x00
415	str	r1, [r0, #ICMR]
416#else /* CONFIG_CPU_MONAHANS */
417	/* Step 1 - Enable CP6 permission */
418	mrc	p15, 0, r1, c15, c1, 0	@ read CPAR
419	orr	r1, r1, #0x40
420		mcr	p15, 0, r1, c15, c1, 0
421	CPWAIT	r1
422
423	/* Step 2 - Mask ICMR & ICMR2 */
424	mov	r1, #0
425	mcr	p6, 0, r1, c1, c0, 0	@ ICMR
426	mcr	p6, 0, r1, c7, c0, 0	@ ICMR2
427
428	/* turn off all clocks but the ones we will definitly require */
429	ldr	r1, =CKENA
430	ldr	r2, =(CKENA_22_FFUART | CKENA_10_SRAM | CKENA_9_SMC | CKENA_8_DMC)
431	str	r2, [r1]
432	ldr	r1, =CKENB
433	ldr	r2, =(CKENB_6_IRQ)
434	str	r2, [r1]
435#endif /* !CONFIG_CPU_MONAHANS */
436
437	/* set clock speed */
438#ifdef CONFIG_CPU_MONAHANS
439	ldr	r0, =ACCR
440	ldr	r1, =(((CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO<<8) & ACCR_XN_MASK) | (CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO & ACCR_XL_MASK))
441	str	r1, [r0]
442#else /* !CONFIG_CPU_MONAHANS */
443#ifdef CONFIG_SYS_CPUSPEED
444	ldr	r0, CC_BASE
445	ldr	r1, cpuspeed
446	str	r1, [r0, #CCCR]
447	mov	r0, #2
448	mcr	p14, 0, r0, c6, c0, 0
449
450setspeed_done:
451
452#endif /* CONFIG_SYS_CPUSPEED */
453#endif /* CONFIG_CPU_MONAHANS */
454
455	/*
456	 * before relocating, we have to setup RAM timing
457	 * because memory timing is board-dependend, you will
458	 * find a lowlevel_init.S in your board directory.
459	 */
460	mov	ip,	lr
461	bl	lowlevel_init
462	mov	lr,	ip
463
464	/* Memory interfaces are working. Disable MMU and enable I-cache.   */
465	/* mk: hmm, this is not in the monahans docs, leave it now but
466	 *     check here if it doesn't work :-) */
467
468	ldr	r0, =0x2001		/* enable access to all coproc.	    */
469	mcr	p15, 0, r0, c15, c1, 0
470	CPWAIT r0
471
472	mcr	p15, 0, r0, c7, c10, 4	/* drain the write & fill buffers   */
473	CPWAIT r0
474
475	mcr	p15, 0, r0, c7, c7, 0	/* flush Icache, Dcache and BTB	    */
476	CPWAIT r0
477
478	mcr	p15, 0, r0, c8, c7, 0	/* flush instuction and data TLBs   */
479	CPWAIT r0
480
481	/* Enable the Icache						    */
482/*
483	mrc	p15, 0, r0, c1, c0, 0
484	orr	r0, r0, #0x1800
485	mcr	p15, 0, r0, c1, c0, 0
486	CPWAIT
487*/
488	mov	pc, lr
489
490#ifndef CONFIG_PRELOADER
491/****************************************************************************/
492/*									    */
493/* Interrupt handling							    */
494/*									    */
495/****************************************************************************/
496
497/* IRQ stack frame							    */
498
499#define S_FRAME_SIZE	72
500
501#define S_OLD_R0	68
502#define S_PSR		64
503#define S_PC		60
504#define S_LR		56
505#define S_SP		52
506
507#define S_IP		48
508#define S_FP		44
509#define S_R10		40
510#define S_R9		36
511#define S_R8		32
512#define S_R7		28
513#define S_R6		24
514#define S_R5		20
515#define S_R4		16
516#define S_R3		12
517#define S_R2		8
518#define S_R1		4
519#define S_R0		0
520
521#define MODE_SVC 0x13
522
523	/* use bad_save_user_regs for abort/prefetch/undef/swi ...	    */
524
525	.macro	bad_save_user_regs
526	sub	sp, sp, #S_FRAME_SIZE
527	stmia	sp, {r0 - r12}			/* Calling r0-r12	    */
528	add	r8, sp, #S_PC
529
530#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
531	ldr	r2, _armboot_start
532	sub	r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
533	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)	@ set base 2 words into abort stack
534#else
535	ldr	r2, IRQ_STACK_START_IN
536#endif
537	ldmia	r2, {r2 - r4}			/* get pc, cpsr, old_r0	    */
538	add	r0, sp, #S_FRAME_SIZE		/* restore sp_SVC	    */
539
540	add	r5, sp, #S_SP
541	mov	r1, lr
542	stmia	r5, {r0 - r4}			/* save sp_SVC, lr_SVC, pc, cpsr, old_r */
543	mov	r0, sp
544	.endm
545
546
547	/* use irq_save_user_regs / irq_restore_user_regs for		     */
548	/* IRQ/FIQ handling						     */
549
550	.macro	irq_save_user_regs
551	sub	sp, sp, #S_FRAME_SIZE
552	stmia	sp, {r0 - r12}			/* Calling r0-r12	     */
553	add	r8, sp, #S_PC
554	stmdb	r8, {sp, lr}^			/* Calling SP, LR	     */
555	str	lr, [r8, #0]			/* Save calling PC	     */
556	mrs	r6, spsr
557	str	r6, [r8, #4]			/* Save CPSR		     */
558	str	r0, [r8, #8]			/* Save OLD_R0		     */
559	mov	r0, sp
560	.endm
561
562	.macro	irq_restore_user_regs
563	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
564	mov	r0, r0
565	ldr	lr, [sp, #S_PC]			@ Get PC
566	add	sp, sp, #S_FRAME_SIZE
567	subs	pc, lr, #4			@ return & move spsr_svc into cpsr
568	.endm
569
570	.macro get_bad_stack
571#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
572	ldr	r13, _armboot_start		@ setup our mode stack
573	sub	r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
574	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
575#else
576	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
577#endif
578
579	str	lr, [r13]			@ save caller lr / spsr
580	mrs	lr, spsr
581	str	lr, [r13, #4]
582
583	mov	r13, #MODE_SVC			@ prepare SVC-Mode
584	msr	spsr_c, r13
585	mov	lr, pc
586	movs	pc, lr
587	.endm
588
589	.macro get_irq_stack			@ setup IRQ stack
590	ldr	sp, IRQ_STACK_START
591	.endm
592
593	.macro get_fiq_stack			@ setup FIQ stack
594	ldr	sp, FIQ_STACK_START
595	.endm
596#endif	/* CONFIG_PRELOADER */
597
598
599/****************************************************************************/
600/*									    */
601/* exception handlers							    */
602/*									    */
603/****************************************************************************/
604
605#ifdef CONFIG_PRELOADER
606	.align	5
607do_hang:
608	ldr	sp, _TEXT_BASE			/* use 32 words abort stack */
609	bl	hang				/* hang and never return */
610#else	/* !CONFIG_PRELOADER */
611	.align	5
612undefined_instruction:
613	get_bad_stack
614	bad_save_user_regs
615	bl	do_undefined_instruction
616
617	.align	5
618software_interrupt:
619	get_bad_stack
620	bad_save_user_regs
621	bl	do_software_interrupt
622
623	.align	5
624prefetch_abort:
625	get_bad_stack
626	bad_save_user_regs
627	bl	do_prefetch_abort
628
629	.align	5
630data_abort:
631	get_bad_stack
632	bad_save_user_regs
633	bl	do_data_abort
634
635	.align	5
636not_used:
637	get_bad_stack
638	bad_save_user_regs
639	bl	do_not_used
640
641#ifdef CONFIG_USE_IRQ
642
643	.align	5
644irq:
645	get_irq_stack
646	irq_save_user_regs
647	bl	do_irq
648	irq_restore_user_regs
649
650	.align	5
651fiq:
652	get_fiq_stack
653	irq_save_user_regs		/* someone ought to write a more    */
654	bl	do_fiq			/* effiction fiq_save_user_regs	    */
655	irq_restore_user_regs
656
657#else /* !CONFIG_USE_IRQ */
658
659	.align	5
660irq:
661	get_bad_stack
662	bad_save_user_regs
663	bl	do_irq
664
665	.align	5
666fiq:
667	get_bad_stack
668	bad_save_user_regs
669	bl	do_fiq
670#endif	/* CONFIG_PRELOADER */
671#endif /* CONFIG_USE_IRQ */
672
673/****************************************************************************/
674/*									    */
675/* Reset function: the PXA250 doesn't have a reset function, so we have to  */
676/* perform a watchdog timeout for a soft reset.				    */
677/*									    */
678/****************************************************************************/
679
680	.align	5
681.globl reset_cpu
682
683	/* FIXME: this code is PXA250 specific. How is this handled on	    */
684	/*	  other XScale processors?				    */
685
686reset_cpu:
687
688	/* We set OWE:WME (watchdog enable) and wait until timeout happens  */
689
690	ldr	r0, OSTIMER_BASE
691	ldr	r1, [r0, #OWER]
692	orr	r1, r1, #0x0001			/* bit0: WME		    */
693	str	r1, [r0, #OWER]
694
695	/* OS timer does only wrap every 1165 seconds, so we have to set    */
696	/* the match register as well.					    */
697
698	ldr	r1, [r0, #OSCR]			/* read OS timer	    */
699	add	r1, r1, #0x800			/* let OSMR3 match after    */
700	add	r1, r1, #0x800			/* 4096*(1/3.6864MHz)=1ms   */
701	str	r1, [r0, #OSMR3]
702
703reset_endless:
704
705	b	reset_endless
706