move new files out from platform support patch
[lede.git] / target / linux / ubicom32 / files / arch / ubicom32 / include / asm / ldsr.h
1 /*
2  * arch/ubicom32/include/asm/ldsr.h
3  *   Ubicom32 LDSR interface definitions.
4  *
5  * (C) Copyright 2009, Ubicom, Inc.
6  *
7  * This file is part of the Ubicom32 Linux Kernel Port.
8  *
9  * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10  * it and/or modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation, either version 2 of the
12  * License, or (at your option) any later version.
13  *
14  * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  * the GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with the Ubicom32 Linux Kernel Port.  If not,
21  * see <http://www.gnu.org/licenses/>.
22  *
23  * Ubicom32 implementation derived from (with many thanks):
24  *   arch/m68knommu
25  *   arch/blackfin
26  *   arch/parisc
27  */
28 #ifndef _ASM_UBICOM32_LDSR_H
29 #define _ASM_UBICOM32_LDSR_H
30
31 #include <asm/ubicom32-common.h>
32 #include <asm/types.h>
33 #include <asm/thread.h>
34
35 extern unsigned int ldsr_soft_irq_mask;
36
37 /*
38  * ldsr_local_irq_is_disabled()
39  *      Test if interrupts are disabled for this thread?
40  */
41 static inline int ldsr_local_irq_is_disabled(void)
42 {
43         int ret;
44         thread_t self = thread_get_self();
45         unsigned int mask = (1 << self);
46
47         asm volatile (
48         "       and.4   %0, scratchpad1, %1     \n\t"
49                 : "=r" (ret)
50                 : "d" (mask)
51                 : "cc"
52         );
53
54         /*
55          *  We return a simple 1 == disabled, 0 == enabled
56          *  losing which tid this is for, because Linux
57          *  can restore interrupts on a different thread.
58          */
59         return ret >> self;
60 }
61
62 /*
63  * ldsr_local_irq_save()
64  *      Get the current interrupt state and disable interrupts.
65  */
66 static inline unsigned int ldsr_local_irq_save(void)
67 {
68         int ret;
69         thread_t self = thread_get_self();
70         unsigned int mask = (1 << self);
71
72         /*
73          * Ensure the compiler can not optimize out the code
74          * (volatile) and that it does not "cache" values around
75          * the interrupt state change (memory).  This ensures
76          * that interrupt changes are treated as a critical
77          * section.
78          */
79         asm volatile (
80         "       and.4   %0, scratchpad1, %1             \n\t"
81         "       or.4    scratchpad1, scratchpad1, %1    \n\t"
82                 : "=&r" (ret)
83                 : "d" (mask)
84                 : "cc", "memory"
85         );
86
87         /*
88          *  We return a simple 1 == disabled, 0 == enabled
89          *  losing which tid this is for, because Linux
90          *  can restore interrupts on a different thread.
91          */
92         return ret >> self;
93 }
94
95 /*
96  * ldsr_local_irq_restore()
97  *      Restore this cpu's interrupt enable/disable state.
98  *
99  * Note: flags is either 0 or 1.
100  */
101 static inline void ldsr_local_irq_restore(unsigned int flags)
102 {
103         unsigned int temp;
104         thread_t self = thread_get_self();
105         unsigned int mask = (1 << self);
106         flags = (flags << self);
107
108         /*
109          * Ensure the compiler can not optimize out the code
110          * (volatile) and that it does not "cache" values around
111          * the interrupt state change (memory).  This ensures
112          * that interrupt changes are treated as a critical
113          * section.
114          *
115          * Atomic change to our bit in scratchpad1 without
116          * causing any temporary glitch in the value and
117          * without effecting other values.  Also this uses
118          * no branches so no penalties.
119          */
120         asm volatile (
121         "       xor.4   %0, scratchpad1, %1             \n\t"
122         "       and.4   %0, %2, %0                      \n\t"
123         "       xor.4   scratchpad1, scratchpad1, %0    \n\t"
124         "       move.4  int_set0, %3                    \n\t"
125                 : "=&d"(temp)
126                 : "d"(flags), "r"(mask), "r"(ldsr_soft_irq_mask)
127                 : "cc", "memory"
128         );
129 }
130
131 /*
132  * ldsr_local_irq_disable_interrupt()
133  *      Disable ints for this thread.
134  */
135 static inline void ldsr_local_irq_disable(void)
136 {
137         unsigned int mask = (1 << thread_get_self());
138
139         /*
140          * Ensure the compiler can not optimize out the code
141          * (volatile) and that it does not "cache" values around
142          * the interrupt state change (memory).  This ensures
143          * that interrupt changes are treated as a critical
144          * section.
145          */
146         asm  volatile (
147         "       or.4    scratchpad1, scratchpad1, %0    \n\t"
148                 :
149                 : "d" (mask)
150                 : "cc", "memory"
151         );
152 }
153
154 /*
155  * ldsr_local_irq_enable_interrupt
156  *      Enable ints for this thread.
157  */
158 static inline void ldsr_local_irq_enable(void)
159 {
160         unsigned int mask = (1 << thread_get_self());
161
162         /*
163          * Ensure the compiler can not optimize out the code
164          * (volatile) and that it does not "cache" values around
165          * the interrupt state change (memory).  This ensures
166          * that interrupt changes are treated as a critical
167          * section.
168          */
169         asm volatile (
170         "       and.4   scratchpad1, scratchpad1, %0    \n\t"
171         "       move.4  int_set0, %1                    \n\t"
172                 :
173                 : "d" (~mask), "r" (ldsr_soft_irq_mask)
174                 : "cc", "memory"
175         );
176 }
177
178 extern void ldsr_init(void);
179 extern void ldsr_set_trap_irq(unsigned int irq);
180 extern void ldsr_mask_vector(unsigned int vector);
181 extern void ldsr_unmask_vector(unsigned int vector);
182 extern void ldsr_enable_vector(unsigned int vector);
183 extern void ldsr_disable_vector(unsigned int vector);
184 extern thread_t ldsr_get_threadid(void);
185
186 #endif /* _ASM_UBICOM32_LDSR_H */