1*4726dd60SMichal Simek /* SPDX-License-Identifier: GPL-2.0 */ 2216f0348SMichal Simek /* 3216f0348SMichal Simek * Copyright (C) 2008 Michal Simek 4216f0348SMichal Simek * Copyright (C) 2007 John Williams 5216f0348SMichal Simek * Copyright (C) 2006 Atmark Techno, Inc. 6216f0348SMichal Simek */ 7216f0348SMichal Simek 8216f0348SMichal Simek #ifndef _ASM_MICROBLAZE_DELAY_H 9216f0348SMichal Simek #define _ASM_MICROBLAZE_DELAY_H 10216f0348SMichal Simek 11ac1566ecSMichal Simek #include <linux/param.h> 12ac1566ecSMichal Simek 13b6db0a56SMichal Simek static inline void __delay(unsigned long loops) 14216f0348SMichal Simek { 15216f0348SMichal Simek asm volatile ("# __delay \n\t" \ 16216f0348SMichal Simek "1: addi %0, %0, -1\t\n" \ 17216f0348SMichal Simek "bneid %0, 1b \t\n" \ 18216f0348SMichal Simek "nop \t\n" 19216f0348SMichal Simek : "=r" (loops) 20216f0348SMichal Simek : "0" (loops)); 21216f0348SMichal Simek } 22216f0348SMichal Simek 23216f0348SMichal Simek /* 24216f0348SMichal Simek * Note that 19 * 226 == 4294 ==~ 2^32 / 10^6, so 25216f0348SMichal Simek * loops = (4294 * usecs * loops_per_jiffy * HZ) / 2^32. 26216f0348SMichal Simek * 27216f0348SMichal Simek * The mul instruction gives us loops = (a * b) / 2^32. 28216f0348SMichal Simek * We choose a = usecs * 19 * HZ and b = loops_per_jiffy * 226 29216f0348SMichal Simek * because this lets us support a wide range of HZ and 30216f0348SMichal Simek * loops_per_jiffy values without either a or b overflowing 2^32. 31216f0348SMichal Simek * Thus we need usecs * HZ <= (2^32 - 1) / 19 = 226050910 and 32216f0348SMichal Simek * loops_per_jiffy <= (2^32 - 1) / 226 = 19004280 33216f0348SMichal Simek * (which corresponds to ~3800 bogomips at HZ = 100). 34216f0348SMichal Simek * -- paulus 35216f0348SMichal Simek */ 36216f0348SMichal Simek #define __MAX_UDELAY (226050910UL/HZ) /* maximum udelay argument */ 37216f0348SMichal Simek #define __MAX_NDELAY (4294967295UL/HZ) /* maximum ndelay argument */ 38216f0348SMichal Simek 39216f0348SMichal Simek extern unsigned long loops_per_jiffy; 40216f0348SMichal Simek 41b6db0a56SMichal Simek static inline void __udelay(unsigned int x) 42216f0348SMichal Simek { 43216f0348SMichal Simek 44216f0348SMichal Simek unsigned long long tmp = 45216f0348SMichal Simek (unsigned long long)x * (unsigned long long)loops_per_jiffy \ 46216f0348SMichal Simek * 226LL; 47216f0348SMichal Simek unsigned loops = tmp >> 32; 48216f0348SMichal Simek 49216f0348SMichal Simek /* 50216f0348SMichal Simek __asm__("mulxuu %0,%1,%2" : "=r" (loops) : 51216f0348SMichal Simek "r" (x), "r" (loops_per_jiffy * 226)); 52216f0348SMichal Simek */ 53216f0348SMichal Simek __delay(loops); 54216f0348SMichal Simek } 55216f0348SMichal Simek 56216f0348SMichal Simek extern void __bad_udelay(void); /* deliberately undefined */ 57216f0348SMichal Simek extern void __bad_ndelay(void); /* deliberately undefined */ 58216f0348SMichal Simek 59ad1d4358SMichal Simek #define udelay(n) \ 60ad1d4358SMichal Simek ({ \ 61ad1d4358SMichal Simek if (__builtin_constant_p(n)) { \ 62ad1d4358SMichal Simek if ((n) / __MAX_UDELAY >= 1) \ 63ad1d4358SMichal Simek __bad_udelay(); \ 64ad1d4358SMichal Simek else \ 65ad1d4358SMichal Simek __udelay((n) * (19 * HZ)); \ 66ad1d4358SMichal Simek } else { \ 67ad1d4358SMichal Simek __udelay((n) * (19 * HZ)); \ 68ad1d4358SMichal Simek } \ 69ad1d4358SMichal Simek }) 70216f0348SMichal Simek 71ad1d4358SMichal Simek #define ndelay(n) \ 72ad1d4358SMichal Simek ({ \ 73ad1d4358SMichal Simek if (__builtin_constant_p(n)) { \ 74ad1d4358SMichal Simek if ((n) / __MAX_NDELAY >= 1) \ 75ad1d4358SMichal Simek __bad_ndelay(); \ 76ad1d4358SMichal Simek else \ 77ad1d4358SMichal Simek __udelay((n) * HZ); \ 78ad1d4358SMichal Simek } else { \ 79ad1d4358SMichal Simek __udelay((n) * HZ); \ 80ad1d4358SMichal Simek } \ 81ad1d4358SMichal Simek }) 82216f0348SMichal Simek 83216f0348SMichal Simek #define muldiv(a, b, c) (((a)*(b))/(c)) 84216f0348SMichal Simek 85216f0348SMichal Simek #endif /* _ASM_MICROBLAZE_DELAY_H */ 86