e754c19b902bd5ae5f4fef7d5f76375579714833
[openwrt/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 */