Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
d54853ef | 2 | * arch/s390/lib/delay.c |
1da177e4 LT |
3 | * Precise Delay Loops for S390 |
4 | * | |
5 | * S390 version | |
6 | * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation | |
7 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), | |
8 | * | |
9 | * Derived from "arch/i386/lib/delay.c" | |
10 | * Copyright (C) 1993 Linus Torvalds | |
11 | * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> | |
12 | */ | |
13 | ||
1da177e4 LT |
14 | #include <linux/sched.h> |
15 | #include <linux/delay.h> | |
d54853ef MS |
16 | #include <linux/timex.h> |
17 | #include <linux/irqflags.h> | |
1da177e4 LT |
18 | |
19 | void __delay(unsigned long loops) | |
20 | { | |
21 | /* | |
22 | * To end the bloody studid and useless discussion about the | |
23 | * BogoMips number I took the liberty to define the __delay | |
24 | * function in a way that that resulting BogoMips number will | |
25 | * yield the megahertz number of the cpu. The important function | |
26 | * is udelay and that is done using the tod clock. -- martin. | |
27 | */ | |
94c12cc7 | 28 | asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1)); |
1da177e4 LT |
29 | } |
30 | ||
31 | /* | |
d54853ef | 32 | * Waits for 'usecs' microseconds using the TOD clock comparator. |
1da177e4 LT |
33 | */ |
34 | void __udelay(unsigned long usecs) | |
35 | { | |
d54853ef MS |
36 | u64 end, time, jiffy_timer = 0; |
37 | unsigned long flags, cr0, mask, dummy; | |
38 | ||
39 | local_irq_save(flags); | |
40 | if (raw_irqs_disabled_flags(flags)) { | |
41 | jiffy_timer = S390_lowcore.jiffy_timer; | |
42 | S390_lowcore.jiffy_timer = -1ULL - (4096 << 12); | |
43 | __ctl_store(cr0, 0, 0); | |
44 | dummy = (cr0 & 0xffff00e0) | 0x00000800; | |
45 | __ctl_load(dummy , 0, 0); | |
46 | mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; | |
47 | } else | |
48 | mask = psw_kernel_bits | PSW_MASK_WAIT | | |
49 | PSW_MASK_EXT | PSW_MASK_IO; | |
50 | ||
51 | end = get_clock() + ((u64) usecs << 12); | |
52 | do { | |
53 | time = end < S390_lowcore.jiffy_timer ? | |
54 | end : S390_lowcore.jiffy_timer; | |
55 | set_clock_comparator(time); | |
56 | trace_hardirqs_on(); | |
57 | __load_psw_mask(mask); | |
58 | local_irq_disable(); | |
59 | } while (get_clock() < end); | |
1da177e4 | 60 | |
d54853ef MS |
61 | if (raw_irqs_disabled_flags(flags)) { |
62 | __ctl_load(cr0, 0, 0); | |
63 | S390_lowcore.jiffy_timer = jiffy_timer; | |
64 | } | |
65 | set_clock_comparator(S390_lowcore.jiffy_timer); | |
66 | local_irq_restore(flags); | |
1da177e4 | 67 | } |