mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 05:41:55 +00:00
beb2dc0a7a
Some CPUs (such as e500v1/v2) don't implement mftb and will take a trap. mfspr should work on everything that has a timebase, and is the preferred instruction according to ISA v2.06. Currently we get away with mftb on 85xx because the assembler converts it to mfspr due to -Wa,-me500. However, that flag has other effects that are undesireable for certain targets (e.g. lwsync is converted to sync), and is hostile to multiplatform kernels. Thus we would like to stop setting it for all e500-family builds. mftb/mftbu instances which are in 85xx code or common code are converted. Instances which will never run on 85xx are left alone. Signed-off-by: Scott Wood <scottwood@freescale.com>
89 lines
2.2 KiB
ArmAsm
89 lines
2.2 KiB
ArmAsm
/*
|
|
* Copied from <file:arch/powerpc/kernel/misc_32.S>
|
|
*
|
|
* This file contains miscellaneous low-level functions.
|
|
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
|
*
|
|
* Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
|
|
* and Paul Mackerras.
|
|
*
|
|
* kexec bits:
|
|
* Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
|
|
* GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*
|
|
*/
|
|
#include "ppc_asm.h"
|
|
|
|
#define SPRN_PVR 0x11F /* Processor Version Register */
|
|
|
|
.text
|
|
|
|
/* udelay (on non-601 processors) needs to know the period of the
|
|
* timebase in nanoseconds. This used to be hardcoded to be 60ns
|
|
* (period of 66MHz/4). Now a variable is used that is initialized to
|
|
* 60 for backward compatibility, but it can be overridden as necessary
|
|
* with code something like this:
|
|
* extern unsigned long timebase_period_ns;
|
|
* timebase_period_ns = 1000000000 / bd->bi_tbfreq;
|
|
*/
|
|
.data
|
|
.globl timebase_period_ns
|
|
timebase_period_ns:
|
|
.long 60
|
|
|
|
.text
|
|
/*
|
|
* Delay for a number of microseconds
|
|
*/
|
|
.globl udelay
|
|
udelay:
|
|
mfspr r4,SPRN_PVR
|
|
srwi r4,r4,16
|
|
cmpwi 0,r4,1 /* 601 ? */
|
|
bne .udelay_not_601
|
|
00: li r0,86 /* Instructions / microsecond? */
|
|
mtctr r0
|
|
10: addi r0,r0,0 /* NOP */
|
|
bdnz 10b
|
|
subic. r3,r3,1
|
|
bne 00b
|
|
blr
|
|
|
|
.udelay_not_601:
|
|
mulli r4,r3,1000 /* nanoseconds */
|
|
/* Change r4 to be the number of ticks using:
|
|
* (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
|
|
* timebase_period_ns defaults to 60 (16.6MHz) */
|
|
mflr r5
|
|
bl 0f
|
|
0: mflr r6
|
|
mtlr r5
|
|
lis r5,0b@ha
|
|
addi r5,r5,0b@l
|
|
subf r5,r5,r6 /* In case we're relocated */
|
|
addis r5,r5,timebase_period_ns@ha
|
|
lwz r5,timebase_period_ns@l(r5)
|
|
add r4,r4,r5
|
|
addi r4,r4,-1
|
|
divw r4,r4,r5 /* BUS ticks */
|
|
1: mfspr r5, SPRN_TBRU
|
|
mfspr r6, SPRN_TBRL
|
|
mfspr r7, SPRN_TBRU
|
|
cmpw 0,r5,r7
|
|
bne 1b /* Get [synced] base time */
|
|
addc r9,r6,r4 /* Compute end time */
|
|
addze r8,r5
|
|
2: mfspr r5, SPRN_TBRU
|
|
cmpw 0,r5,r8
|
|
blt 2b
|
|
bgt 3f
|
|
mfspr r6, SPRN_TBRL
|
|
cmpw 0,r6,r9
|
|
blt 2b
|
|
3: blr
|