Merge branch 'linus' into genirq
[linux-2.6] / arch / powerpc / boot / util.S
1 /*
2  * Copied from <file:arch/powerpc/kernel/misc_32.S>
3  *
4  * This file contains miscellaneous low-level functions.
5  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6  *
7  * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
8  * and Paul Mackerras.
9  *
10  * kexec bits:
11  * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
12  * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version
17  * 2 of the License, or (at your option) any later version.
18  *
19  */
20 #include "ppc_asm.h"
21
22 #define SPRN_PVR        0x11F   /* Processor Version Register */
23
24         .text
25
26 /* udelay (on non-601 processors) needs to know the period of the
27  * timebase in nanoseconds.  This used to be hardcoded to be 60ns
28  * (period of 66MHz/4).  Now a variable is used that is initialized to
29  * 60 for backward compatibility, but it can be overridden as necessary
30  * with code something like this:
31  *    extern unsigned long timebase_period_ns;
32  *    timebase_period_ns = 1000000000 / bd->bi_tbfreq;
33  */
34         .data
35         .globl timebase_period_ns
36 timebase_period_ns:
37         .long   60
38
39         .text
40 /*
41  * Delay for a number of microseconds
42  */
43         .globl  udelay
44 udelay:
45         mfspr   r4,SPRN_PVR
46         srwi    r4,r4,16
47         cmpwi   0,r4,1          /* 601 ? */
48         bne     .udelay_not_601
49 00:     li      r0,86   /* Instructions / microsecond? */
50         mtctr   r0
51 10:     addi    r0,r0,0 /* NOP */
52         bdnz    10b
53         subic.  r3,r3,1
54         bne     00b
55         blr
56
57 .udelay_not_601:
58         mulli   r4,r3,1000      /* nanoseconds */
59         /*  Change r4 to be the number of ticks using:
60          *      (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
61          *  timebase_period_ns defaults to 60 (16.6MHz) */
62         mflr    r5
63         bl      0f
64 0:      mflr    r6
65         mtlr    r5
66         lis     r5,0b@ha
67         addi    r5,r5,0b@l
68         subf    r5,r5,r6        /* In case we're relocated */
69         addis   r5,r5,timebase_period_ns@ha
70         lwz     r5,timebase_period_ns@l(r5)
71         add     r4,r4,r5
72         addi    r4,r4,-1
73         divw    r4,r4,r5        /* BUS ticks */
74 1:      mftbu   r5
75         mftb    r6
76         mftbu   r7
77         cmpw    0,r5,r7
78         bne     1b              /* Get [synced] base time */
79         addc    r9,r6,r4        /* Compute end time */
80         addze   r8,r5
81 2:      mftbu   r5
82         cmpw    0,r5,r8
83         blt     2b
84         bgt     3f
85         mftb    r6
86         cmpw    0,r6,r9
87         blt     2b
88 3:      blr