Linux Audio

Check our new training course

Loading...
v6.13.7
 1// SPDX-License-Identifier: GPL-2.0
 2/*
 3 *    Precise Delay Loops for S390
 4 *
 5 *    Copyright IBM Corp. 1999, 2008
 6 *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
 
 7 */
 8
 9#include <linux/processor.h>
10#include <linux/delay.h>
 
 
 
 
11#include <asm/div64.h>
12#include <asm/timex.h>
13
14void __delay(unsigned long loops)
15{
16	/*
17	 * Loop 'loops' times. Callers must not assume a specific
18	 * amount of time passes before this function returns.
19	 */
 
 
 
20	asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
21}
22EXPORT_SYMBOL(__delay);
23
24static void delay_loop(unsigned long delta)
25{
26	unsigned long end;
 
27
28	end = get_tod_clock_monotonic() + delta;
29	while (!tod_after(get_tod_clock_monotonic(), end))
30		cpu_relax();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31}
32
33void __udelay(unsigned long usecs)
 
 
 
34{
35	delay_loop(usecs << 12);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36}
37EXPORT_SYMBOL(__udelay);
38
39void __ndelay(unsigned long nsecs)
 
 
 
 
 
 
 
 
 
 
 
 
 
40{
 
 
41	nsecs <<= 9;
42	do_div(nsecs, 125);
43	delay_loop(nsecs);
 
 
 
 
44}
45EXPORT_SYMBOL(__ndelay);
v3.5.6
 
  1/*
  2 *    Precise Delay Loops for S390
  3 *
  4 *    Copyright IBM Corp. 1999,2008
  5 *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
  6 *		 Heiko Carstens <heiko.carstens@de.ibm.com>,
  7 */
  8
  9#include <linux/sched.h>
 10#include <linux/delay.h>
 11#include <linux/timex.h>
 12#include <linux/module.h>
 13#include <linux/irqflags.h>
 14#include <linux/interrupt.h>
 15#include <asm/div64.h>
 16#include <asm/timer.h>
 17
 18void __delay(unsigned long loops)
 19{
 20        /*
 21         * To end the bloody studid and useless discussion about the
 22         * BogoMips number I took the liberty to define the __delay
 23         * function in a way that that resulting BogoMips number will
 24         * yield the megahertz number of the cpu. The important function
 25         * is udelay and that is done using the tod clock. -- martin.
 26         */
 27	asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
 28}
 
 29
 30static void __udelay_disabled(unsigned long long usecs)
 31{
 32	unsigned long cr0, cr6, new;
 33	u64 clock_saved, end;
 34
 35	end = get_clock() + (usecs << 12);
 36	clock_saved = local_tick_disable();
 37	__ctl_store(cr0, 0, 0);
 38	__ctl_store(cr6, 6, 6);
 39	new = (cr0 &  0xffff00e0) | 0x00000800;
 40	__ctl_load(new , 0, 0);
 41	new = 0;
 42	__ctl_load(new, 6, 6);
 43	lockdep_off();
 44	do {
 45		set_clock_comparator(end);
 46		vtime_stop_cpu();
 47		local_irq_disable();
 48	} while (get_clock() < end);
 49	lockdep_on();
 50	__ctl_load(cr0, 0, 0);
 51	__ctl_load(cr6, 6, 6);
 52	local_tick_enable(clock_saved);
 53}
 54
 55static void __udelay_enabled(unsigned long long usecs)
 56{
 57	u64 clock_saved, end;
 58
 59	end = get_clock() + (usecs << 12);
 60	do {
 61		clock_saved = 0;
 62		if (end < S390_lowcore.clock_comparator) {
 63			clock_saved = local_tick_disable();
 64			set_clock_comparator(end);
 65		}
 66		vtime_stop_cpu();
 67		local_irq_disable();
 68		if (clock_saved)
 69			local_tick_enable(clock_saved);
 70	} while (get_clock() < end);
 71}
 72
 73/*
 74 * Waits for 'usecs' microseconds using the TOD clock comparator.
 75 */
 76void __udelay(unsigned long long usecs)
 77{
 78	unsigned long flags;
 79
 80	preempt_disable();
 81	local_irq_save(flags);
 82	if (in_irq()) {
 83		__udelay_disabled(usecs);
 84		goto out;
 85	}
 86	if (in_softirq()) {
 87		if (raw_irqs_disabled_flags(flags))
 88			__udelay_disabled(usecs);
 89		else
 90			__udelay_enabled(usecs);
 91		goto out;
 92	}
 93	if (raw_irqs_disabled_flags(flags)) {
 94		local_bh_disable();
 95		__udelay_disabled(usecs);
 96		_local_bh_enable();
 97		goto out;
 98	}
 99	__udelay_enabled(usecs);
100out:
101	local_irq_restore(flags);
102	preempt_enable();
103}
104EXPORT_SYMBOL(__udelay);
105
106/*
107 * Simple udelay variant. To be used on startup and reboot
108 * when the interrupt handler isn't working.
109 */
110void udelay_simple(unsigned long long usecs)
111{
112	u64 end;
113
114	end = get_clock() + (usecs << 12);
115	while (get_clock() < end)
116		cpu_relax();
117}
118
119void __ndelay(unsigned long long nsecs)
120{
121	u64 end;
122
123	nsecs <<= 9;
124	do_div(nsecs, 125);
125	end = get_clock() + nsecs;
126	if (nsecs & ~0xfffUL)
127		__udelay(nsecs >> 12);
128	while (get_clock() < end)
129		barrier();
130}
131EXPORT_SYMBOL(__ndelay);