root/arch/powerpc/boot/util.S

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

/* [<][>][^][v][top][bottom][index][help] */