summaryrefslogtreecommitdiffstats
path: root/arch/blackfin/include/asm/system.h
blob: 581fd42397dacce5d6d10cfaf8462da0589e01c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/*
 * barebox - system.h
 *
 * Copyright (c) 2005 blackfin.uclinux.org
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#ifndef _BLACKFIN_SYSTEM_H
#define _BLACKFIN_SYSTEM_H

#include <asm/linkage.h>
#include <asm/blackfin.h>
#include <asm/segment.h>
#include <asm/entry.h>

#define prepare_to_switch()	do { } while(0)

/*
 * switch_to(n) should switch tasks to task ptr, first checking that
 * ptr isn't the current task, in which case it does nothing.  This
 * also clears the TS-flag if the task we switched to has used the
 * math co-processor latest.
 *
 * 05/25/01 - Tony Kou (tonyko@lineo.ca)
 *
 * Adapted for BlackFin (ADI) by Ted Ma, Metrowerks, and Motorola GSG
 * Copyright (c) 2002 Arcturus Networks Inc. (www.arcturusnetworks.com)
 * Copyright (c) 2003 Metrowerks (www.metrowerks.com)
 */

asmlinkage void resume(void);

#define switch_to(prev,next,last)	{					\
	void *_last;								\
	__asm__ __volatile__(							\
  			"r0 = %1;\n\t"						\
			"r1 = %2;\n\t"						\
			"call resume;\n\t" 					\
			"%0 = r0;\n\t"						\
			: "=d" (_last)						\
			: "d" (prev),						\
			"d" (next)						\
			: "CC", "R0", "R1", "R2", "R3", "R4", "R5", "P0", "P1");\
			(last) = _last;						\
}

/* Force kerenl switch to user mode -- Steven Chen */
#define switch_to_user_mode()	{						\
	__asm__ __volatile__(							\
			"call kernel_to_user_mode;\n\t"				\
			::							\
			: "CC", "R0", "R1", "R2", "R3", "R4", "R5", "P0", "P1");\
}

/*
 * Interrupt configuring macros.
 */

extern int irq_flags;

#define __sti()	{			\
	__asm__ __volatile__ (		\
		"r3 = %0;"		\
		"sti r3;"		\
		::"m"(irq_flags):"R3");	\
}

#define __cli()	{			\
	__asm__ __volatile__ (		\
		"cli r3;"		\
		:::"R3");		\
}

#define __save_flags(x)	{		\
	__asm__ __volatile__ (		\
		"cli r3;"		\
		"%0 = r3;"		\
		"sti r3;"		\
		::"m"(x):"R3");		\
}

#define __save_and_cli(x)	{	\
	__asm__ __volatile__ (          \
		"cli r3;"		\
		"%0 = r3;"		\
		::"m"(x):"R3");		\
}

#define __restore_flags(x) {		\
	__asm__ __volatile__ (		\
		"r3 = %0;"		\
		"sti r3;"		\
		::"m"(x):"R3");		\
}

/* For spinlocks etc */
#define local_irq_save(x)	__save_and_cli(x)
#define local_irq_restore(x)	__restore_flags(x)
#define local_irq_disable()	__cli()
#define local_irq_enable()	__sti()

#define cli()			__cli()
#define sti()			__sti()
#define save_flags(x)		__save_flags(x)
#define restore_flags(x)	__restore_flags(x)
#define save_and_cli(x)		__save_and_cli(x)

/*
 * Force strict CPU ordering.
 */
#define nop()			asm volatile ("nop;\n\t"::)
#define mb()			asm volatile (""   : : :"memory")
#define rmb()			asm volatile (""   : : :"memory")
#define wmb()			asm volatile (""   : : :"memory")
#define set_rmb(var, value)	do { xchg(&var, value); } while (0)
#define set_mb(var, value)	set_rmb(var, value)
#define set_wmb(var, value)	do { var = value; wmb(); } while (0)

#ifdef CONFIG_SMP
#define smp_mb()		mb()
#define smp_rmb()		rmb()
#define smp_wmb()		wmb()
#else
#define smp_mb()		barrier()
#define smp_rmb()		barrier()
#define smp_wmb()		barrier()
#endif

#define xchg(ptr,x)		((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
#define tas(ptr)		(xchg((ptr),1))

struct __xchg_dummy {
	unsigned long a[100];
};
#define __xg(x)			((volatile struct __xchg_dummy *)(x))

static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
				   int size)
{
	unsigned long tmp;
	unsigned long flags = 0;

	save_and_cli(flags);

	switch (size) {
	case 1:
	      __asm__ __volatile__("%0 = %2;\n\t" "%2 = %1;\n\t": "=&d"(tmp): "d"(x), "m"(*__xg(ptr)):"memory");
		break;
	case 2:
	      __asm__ __volatile__("%0 = %2;\n\t" "%2 = %1;\n\t": "=&d"(tmp): "d"(x), "m"(*__xg(ptr)):"memory");
		break;
	case 4:
	      __asm__ __volatile__("%0 = %2;\n\t" "%2 = %1;\n\t": "=&d"(tmp): "d"(x), "m"(*__xg(ptr)):"memory");
		break;
	}
	restore_flags(flags);
	return tmp;
}

/* Depend on whether Blackfin has hard reset function */
/* YES it does, but it is tricky to implement - FIXME later ...MaTed--- */
#define HARD_RESET_NOW() ({})

#endif	/* _BLACKFIN_SYSTEM_H */