branch Attitude Adjustment
[12.09/openwrt.git] / target / linux / ubicom32 / files / arch / ubicom32 / crypto / crypto_ubicom32.h
1 /*
2  * arch/ubicom32/crypto/crypto_ubicom32.h
3  *   Support for Ubicom32 cryptographic instructions.
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 _CRYPTO_ARCH_UBICOM32_CRYPT_H
29 #define _CRYPTO_ARCH_UBICOM32_CRYPT_H
30
31 #include <linux/module.h>
32 #include <linux/kernel.h>
33 #include <linux/jiffies.h>
34 #include <linux/timer.h>
35 #include <linux/spinlock.h>
36 #include <asm/errno.h>
37 #include <asm/io.h>
38 #include <asm/ip5000.h>
39
40 #define CRYPTO_UBICOM32_LOOP_ASM 1
41 #define CRYPTO_UBICOM32_ALIGNMENT 4
42 #define SEC_ALIGNED(p) (((u32)p & 3) == 0)
43
44 #define SEC_BASE                SECURITY_BASE
45 #define SEC_KEY_OFFSET          SECURITY_KEY_VALUE(0)
46 #define SEC_INPUT_OFFSET        SECURITY_KEY_IN(0)
47 #define SEC_OUTPUT_OFFSET       SECURITY_KEY_OUT(0)
48 #define SEC_HASH_OFFSET         SECURITY_KEY_HASH(0)
49
50 #define SEC_KEY_128_BITS        SECURITY_CTRL_KEY_SIZE(0)
51 #define SEC_KEY_192_BITS        SECURITY_CTRL_KEY_SIZE(1)
52 #define SEC_KEY_256_BITS        SECURITY_CTRL_KEY_SIZE(2)
53
54 #define SEC_HASH_NONE           SECURITY_CTRL_HASH_ALG_NONE
55 #define SEC_HASH_MD5            SECURITY_CTRL_HASH_ALG_MD5
56 #define SEC_HASH_SHA1           SECURITY_CTRL_HASH_ALG_SHA1
57
58 #define SEC_CBC_SET             SECURITY_CTRL_CBC
59 #define SEC_CBC_NONE            0
60
61 #define SEC_ALG_AES             SECURITY_CTRL_CIPHER_ALG_AES
62 #define SEC_ALG_NONE            SECURITY_CTRL_CIPHER_ALG_NONE
63 #define SEC_ALG_DES             SECURITY_CTRL_CIPHER_ALG_DES
64 #define SEC_ALG_3DES            SECURITY_CTRL_CIPHER_ALG_3DES
65
66 #define SEC_DIR_ENCRYPT         SECURITY_CTRL_ENCIPHER
67 #define SEC_DIR_DECRYPT         0
68
69 #define CRYPTO_UBICOM32_PRIORITY 300
70 #define CRYPTO_UBICOM32_COMPOSITE_PRIORITY 400
71
72 #define HW_CRYPTO_PS_MAX_IDLE_MS 100    /* idle time (ms) before shuting down sm */
73
74 extern spinlock_t crypto_ubicom32_lock;
75 extern bool crypto_ubicom32_inited;
76 extern volatile bool crypto_ubicom32_on;
77 extern volatile unsigned long crypto_ubicom32_last_use;
78 extern struct timer_list crypto_ubicom32_ps_timer;
79 extern void crypto_ubicom32_ps_check(unsigned long data);
80
81 #define SEC_COPY_2W(t, s)                               \
82         asm volatile (                                  \
83         "       move.4 0(%0), 0(%1)             \n\t"   \
84         "       move.4 4(%0), 4(%1)             \n\t"   \
85                                                         \
86                 :                                       \
87                 : "a" (t), "a" (s)                      \
88         )
89
90 #define SEC_COPY_4W(t, s)                               \
91         asm volatile (                                  \
92         "       move.4 0(%0), 0(%1)             \n\t"   \
93         "       move.4 4(%0), 4(%1)             \n\t"   \
94         "       move.4 8(%0), 8(%1)             \n\t"   \
95         "       move.4 12(%0), 12(%1)           \n\t"   \
96                 :                                       \
97                 : "a" (t), "a" (s)                      \
98         )
99
100 #define SEC_COPY_5W(t, s)                               \
101         asm volatile (                                  \
102         "       move.4 0(%0), 0(%1)             \n\t"   \
103         "       move.4 4(%0), 4(%1)             \n\t"   \
104         "       move.4 8(%0), 8(%1)             \n\t"   \
105         "       move.4 12(%0), 12(%1)           \n\t"   \
106         "       move.4 16(%0), 16(%1)           \n\t"   \
107                 :                                       \
108                 : "a" (t), "a" (s)                      \
109         )
110
111 #define SEC_SET_KEY_2W(x)                               \
112         asm volatile (                                  \
113         "       ; write key to Security Keyblock \n\t"  \
114         "       move.4 0x10(%0), 0(%1)          \n\t"   \
115         "       move.4 0x14(%0), 4(%1)          \n\t"   \
116                 :                                       \
117                 : "a" (SECURITY_BASE), "a" (x)          \
118         )
119
120 #define SEC_SET_KEY_4W(x) \
121         asm volatile ( \
122         "       ; write key to Security Keyblock \n\t"  \
123         "       move.4 0x10(%0), 0(%1)          \n\t"   \
124         "       move.4 0x14(%0), 4(%1)          \n\t"   \
125         "       move.4 0x18(%0), 8(%1)          \n\t"   \
126         "       move.4 0x1c(%0), 12(%1)         \n\t"   \
127                 :                                       \
128                 : "a"(SECURITY_BASE), "a"(x)            \
129         )
130
131 #define SEC_SET_KEY_6W(x)                               \
132         asm volatile (                                  \
133         "       ; write key to Security Keyblock \n\t"  \
134         "       move.4 0x10(%0), 0(%1)          \n\t"   \
135         "       move.4 0x14(%0), 4(%1)          \n\t"   \
136         "       move.4 0x18(%0), 8(%1)          \n\t"   \
137         "       move.4 0x1c(%0), 12(%1)         \n\t"   \
138         "       move.4 0x20(%0), 16(%1)         \n\t"   \
139         "       move.4 0x24(%0), 20(%1)         \n\t"   \
140                 :                                       \
141                 : "a" (SECURITY_BASE), "a" (x)          \
142         )
143
144 #define SEC_SET_KEY_8W(x)                               \
145         asm volatile (                                  \
146         "       ; write key to Security Keyblock \n\t"  \
147         "       move.4 0x10(%0), 0(%1)          \n\t"   \
148         "       move.4 0x14(%0), 4(%1)          \n\t"   \
149         "       move.4 0x18(%0), 8(%1)          \n\t"   \
150         "       move.4 0x1c(%0), 12(%1)         \n\t"   \
151         "       move.4 0x20(%0), 16(%1)         \n\t"   \
152         "       move.4 0x24(%0), 20(%1)         \n\t"   \
153         "       move.4 0x28(%0), 24(%1)         \n\t"   \
154         "       move.4 0x2c(%0), 28(%1)         \n\t"   \
155                 :                                       \
156                 : "a" (SECURITY_BASE), "a" (x)          \
157         )
158
159 #define SEC_SET_KEY_64(k)       SEC_SET_KEY_2W(k)
160 #define SEC_SET_KEY_128(k)      SEC_SET_KEY_4W(k)
161 #define SEC_SET_KEY_192(k)      SEC_SET_KEY_6W(k)
162 #define SEC_SET_KEY_256(k)      SEC_SET_KEY_8W(k)
163
164 #define DES_SET_KEY(x)          SEC_SET_KEY_64(x)
165 #define DES3_SET_KEY(x)         SEC_SET_KEY_192(x)
166
167 #define SEC_SET_INPUT_2W(x)                             \
168         asm volatile (                                  \
169         "       ; write key to Security Keyblock \n\t"  \
170         "       move.4 0x30(%0), 0(%1)          \n\t"   \
171         "       move.4 0x34(%0), 4(%1)          \n\t"   \
172                 :                                       \
173                 : "a" (SECURITY_BASE), "a" (x)          \
174         )
175
176 #define SEC_GET_OUTPUT_2W(x)                            \
177         asm volatile (                                  \
178         "       ; write key to Security Keyblock \n\t"  \
179         "       move.4 0(%1), 0x50(%0)          \n\t"   \
180         "       move.4 4(%1), 0x54(%0)          \n\t"   \
181                 :                                       \
182                 : "a" (SECURITY_BASE), "a" (x)          \
183         )
184
185 #define SEC_SET_INPUT_4W(x) \
186         asm volatile ( \
187         "       ; write key to Security Keyblock \n\t"  \
188         "       move.4 0x30(%0), 0(%1)          \n\t"   \
189         "       move.4 0x34(%0), 4(%1)          \n\t"   \
190         "       move.4 0x38(%0), 8(%1)          \n\t"   \
191         "       move.4 0x3c(%0), 12(%1)         \n\t"   \
192                 :                                       \
193                 : "a" (SECURITY_BASE), "a" (x)          \
194         )
195
196 #define SEC_GET_OUTPUT_4W(x)                            \
197         asm volatile (                                  \
198         "       ; read output from Security Keyblock \n\t" \
199         "       move.4 0(%1), 0x50(%0)          \n\t"   \
200         "       move.4 4(%1), 0x54(%0)          \n\t"   \
201         "       move.4 8(%1), 0x58(%0)          \n\t"   \
202         "       move.4 12(%1), 0x5c(%0)         \n\t"   \
203                 :                                       \
204                 : "a" (SECURITY_BASE), "a" (x)          \
205         )
206
207 #define SEC_SET_IV_4W(x)                                \
208         asm volatile (                                  \
209         "       ; write IV to Security Keyblock  \n\t"  \
210         "       move.4 0x50(%0), 0(%1)          \n\t"   \
211         "       move.4 0x54(%0), 4(%1)          \n\t"   \
212         "       move.4 0x58(%0), 8(%1)          \n\t"   \
213         "       move.4 0x5c(%0), 12(%1)         \n\t"   \
214                 :                                       \
215                 : "a" (SECURITY_BASE), "a" (x)          \
216         )
217
218 #define SEC_PIPE_FLUSH() asm volatile ( " pipe_flush 0 \n\t" )
219
220 static inline void hw_crypto_set_ctrl(uint32_t c)
221 {
222         asm volatile (
223         "       move.4  0(%0), %1               \n\t"
224                 :
225                 : "a" (SECURITY_BASE + SECURITY_CTRL), "d" (c)
226         );
227 }
228
229 static inline void hw_crypto_ps_start(void)
230 {
231         crypto_ubicom32_ps_timer.expires = jiffies + msecs_to_jiffies(HW_CRYPTO_PS_MAX_IDLE_MS >> 1);
232         add_timer(&crypto_ubicom32_ps_timer);
233 }
234
235 static inline void hw_crypto_turn_on(void)
236 {
237         asm volatile (
238         "       moveai  A4, %0                  \n\t"
239         "       bset    0x0(A4), 0x0(A4), %1    \n\t"
240         "       cycles 11                       \n\t"
241                 :
242                 : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
243                 : "a4", "cc"
244         );
245         crypto_ubicom32_on = true;
246 }
247
248 static inline void hw_crypto_turn_off(void)
249 {
250         asm volatile (
251         "       moveai  A4, %0                  \n\t"
252         "       bclr    0x0(A4), 0x0(A4), %1    \n\t"
253                 :
254                 : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
255                 : "a4", "cc"
256         );
257         crypto_ubicom32_on = false;
258 }
259
260 /*
261  * hw_crypto_check
262  *      Most probably hw crypto is called in clusters and it makes no sense to turn it off
263  *      and on and waster 13 cycles every time.
264  */
265 static inline void hw_crypto_check(void)
266 {
267         if (likely(crypto_ubicom32_on)) {
268                 return;
269         }
270         crypto_ubicom32_last_use = jiffies;
271         hw_crypto_turn_on();
272         hw_crypto_ps_start();
273 }
274
275 /*
276  * hw_crypto_ps_init
277  *      Init power save timer
278  */
279 static inline void hw_crypto_ps_init(void)
280 {
281         init_timer_deferrable(&crypto_ubicom32_ps_timer);
282         crypto_ubicom32_ps_timer.function = crypto_ubicom32_ps_check;
283         crypto_ubicom32_ps_timer.data = 0;
284 }
285
286 /*
287  * hw_crypto_init()
288  *      Initialize OCP security module lock and disables its clock.
289  */
290 static inline void hw_crypto_init(void)
291 {
292         if (!crypto_ubicom32_inited) {
293                 crypto_ubicom32_inited = true;
294                 spin_lock_init(&crypto_ubicom32_lock);
295                 hw_crypto_ps_init();
296                 hw_crypto_turn_off();
297         }
298 }
299
300 /*
301  * hw_crypto_lock()
302  *      Locks the OCP security module and enables its clock.
303  */
304 static inline void hw_crypto_lock(void)
305 {
306         spin_lock_bh(&crypto_ubicom32_lock);
307 }
308
309 /*
310  * hw_crypto_unlock()
311  *      Unlocks the OCP security module and disables its clock.
312  */
313 static inline void hw_crypto_unlock(void)
314 {
315         crypto_ubicom32_last_use = jiffies;
316         spin_unlock_bh(&crypto_ubicom32_lock);
317 }
318
319 #define CONFIG_CRYPTO_UBICOM32_DEBUG 1
320
321 #ifdef CONFIG_CRYPTO_UBICOM32_DEBUG
322 static inline void hex_dump(void *buf, int b_size, const char *msg)
323 {
324         u8 *b = (u8 *)buf;
325         int i;
326         if (msg) {
327                 printk("%s:\t", msg);
328         }
329
330         for (i=0; i < b_size; i++) {
331                 printk("%02x ", b[i]);
332                 if ((i & 3) == 3) {
333                         printk(" ");
334                 }
335                 if ((i & 31) == 31) {
336                         printk("\n");
337                 }
338         }
339         printk("\n");
340 }
341 #define UBICOM32_SEC_DUMP(a, b, c) hex_dump(a, b, c)
342 #else
343 #define UBICOM32_SEC_DUMP(a, b, c)
344 #endif
345
346 #endif  /* _CRYPTO_ARCH_UBICOM32_CRYPT_H */