162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copied from <file:arch/powerpc/kernel/misc_32.S> 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This file contains miscellaneous low-level functions. 662306a36Sopenharmony_ci * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) 962306a36Sopenharmony_ci * and Paul Mackerras. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * kexec bits: 1262306a36Sopenharmony_ci * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com> 1362306a36Sopenharmony_ci * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_ci#include "ppc_asm.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define SPRN_PVR 0x11F /* Processor Version Register */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci .text 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* udelay needs to know the period of the 2262306a36Sopenharmony_ci * timebase in nanoseconds. This used to be hardcoded to be 60ns 2362306a36Sopenharmony_ci * (period of 66MHz/4). Now a variable is used that is initialized to 2462306a36Sopenharmony_ci * 60 for backward compatibility, but it can be overridden as necessary 2562306a36Sopenharmony_ci * with code something like this: 2662306a36Sopenharmony_ci * extern unsigned long timebase_period_ns; 2762306a36Sopenharmony_ci * timebase_period_ns = 1000000000 / bd->bi_tbfreq; 2862306a36Sopenharmony_ci */ 2962306a36Sopenharmony_ci .data 3062306a36Sopenharmony_ci .globl timebase_period_ns 3162306a36Sopenharmony_citimebase_period_ns: 3262306a36Sopenharmony_ci .long 60 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci .text 3562306a36Sopenharmony_ci/* 3662306a36Sopenharmony_ci * Delay for a number of microseconds 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci .globl udelay 3962306a36Sopenharmony_ciudelay: 4062306a36Sopenharmony_ci mulli r4,r3,1000 /* nanoseconds */ 4162306a36Sopenharmony_ci /* Change r4 to be the number of ticks using: 4262306a36Sopenharmony_ci * (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns 4362306a36Sopenharmony_ci * timebase_period_ns defaults to 60 (16.6MHz) */ 4462306a36Sopenharmony_ci mflr r5 4562306a36Sopenharmony_ci bcl 20,31,0f 4662306a36Sopenharmony_ci0: mflr r6 4762306a36Sopenharmony_ci mtlr r5 4862306a36Sopenharmony_ci addis r5,r6,(timebase_period_ns-0b)@ha 4962306a36Sopenharmony_ci lwz r5,(timebase_period_ns-0b)@l(r5) 5062306a36Sopenharmony_ci add r4,r4,r5 5162306a36Sopenharmony_ci addi r4,r4,-1 5262306a36Sopenharmony_ci divw r4,r4,r5 /* BUS ticks */ 5362306a36Sopenharmony_ci1: MFTBU(r5) 5462306a36Sopenharmony_ci MFTBL(r6) 5562306a36Sopenharmony_ci MFTBU(r7) 5662306a36Sopenharmony_ci cmpw 0,r5,r7 5762306a36Sopenharmony_ci bne 1b /* Get [synced] base time */ 5862306a36Sopenharmony_ci addc r9,r6,r4 /* Compute end time */ 5962306a36Sopenharmony_ci addze r8,r5 6062306a36Sopenharmony_ci2: MFTBU(r5) 6162306a36Sopenharmony_ci cmpw 0,r5,r8 6262306a36Sopenharmony_ci blt 2b 6362306a36Sopenharmony_ci bgt 3f 6462306a36Sopenharmony_ci MFTBL(r6) 6562306a36Sopenharmony_ci cmpw 0,r6,r9 6662306a36Sopenharmony_ci blt 2b 6762306a36Sopenharmony_ci3: blr 68