2 * arch/ubicom32/crypto/crypto_ubicom32.h
3 * Support for Ubicom32 cryptographic instructions.
5 * (C) Copyright 2009, Ubicom, Inc.
7 * This file is part of the Ubicom32 Linux Kernel Port.
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.
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.
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/>.
23 * Ubicom32 implementation derived from (with many thanks):
28 #ifndef _CRYPTO_ARCH_UBICOM32_CRYPT_H
29 #define _CRYPTO_ARCH_UBICOM32_CRYPT_H
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>
38 #include <asm/ip5000.h>
40 #define CRYPTO_UBICOM32_LOOP_ASM 1
41 #define CRYPTO_UBICOM32_ALIGNMENT 4
42 #define SEC_ALIGNED(p) (((u32)p & 3) == 0)
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)
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)
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
58 #define SEC_CBC_SET SECURITY_CTRL_CBC
59 #define SEC_CBC_NONE 0
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
66 #define SEC_DIR_ENCRYPT SECURITY_CTRL_ENCIPHER
67 #define SEC_DIR_DECRYPT 0
69 #define CRYPTO_UBICOM32_PRIORITY 300
70 #define CRYPTO_UBICOM32_COMPOSITE_PRIORITY 400
72 #define HW_CRYPTO_PS_MAX_IDLE_MS 100 /* idle time (ms) before shuting down sm */
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);
81 #define SEC_COPY_2W(t, s) \
83 " move.4 0(%0), 0(%1) \n\t" \
84 " move.4 4(%0), 4(%1) \n\t" \
90 #define SEC_COPY_4W(t, s) \
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" \
100 #define SEC_COPY_5W(t, s) \
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" \
111 #define SEC_SET_KEY_2W(x) \
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" \
117 : "a" (SECURITY_BASE), "a" (x) \
120 #define SEC_SET_KEY_4W(x) \
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" \
128 : "a"(SECURITY_BASE), "a"(x) \
131 #define SEC_SET_KEY_6W(x) \
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" \
141 : "a" (SECURITY_BASE), "a" (x) \
144 #define SEC_SET_KEY_8W(x) \
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" \
156 : "a" (SECURITY_BASE), "a" (x) \
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)
164 #define DES_SET_KEY(x) SEC_SET_KEY_64(x)
165 #define DES3_SET_KEY(x) SEC_SET_KEY_192(x)
167 #define SEC_SET_INPUT_2W(x) \
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" \
173 : "a" (SECURITY_BASE), "a" (x) \
176 #define SEC_GET_OUTPUT_2W(x) \
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" \
182 : "a" (SECURITY_BASE), "a" (x) \
185 #define SEC_SET_INPUT_4W(x) \
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" \
193 : "a" (SECURITY_BASE), "a" (x) \
196 #define SEC_GET_OUTPUT_4W(x) \
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" \
204 : "a" (SECURITY_BASE), "a" (x) \
207 #define SEC_SET_IV_4W(x) \
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" \
215 : "a" (SECURITY_BASE), "a" (x) \
218 #define SEC_PIPE_FLUSH() asm volatile ( " pipe_flush 0 \n\t" )
220 static inline void hw_crypto_set_ctrl(uint32_t c)
223 " move.4 0(%0), %1 \n\t"
225 : "a" (SECURITY_BASE + SECURITY_CTRL), "d" (c)
229 static inline void hw_crypto_ps_start(void)
231 crypto_ubicom32_ps_timer.expires = jiffies + msecs_to_jiffies(HW_CRYPTO_PS_MAX_IDLE_MS >> 1);
232 add_timer(&crypto_ubicom32_ps_timer);
235 static inline void hw_crypto_turn_on(void)
238 " moveai A4, %0 \n\t"
239 " bset 0x0(A4), 0x0(A4), %1 \n\t"
242 : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
245 crypto_ubicom32_on = true;
248 static inline void hw_crypto_turn_off(void)
251 " moveai A4, %0 \n\t"
252 " bclr 0x0(A4), 0x0(A4), %1 \n\t"
254 : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
257 crypto_ubicom32_on = false;
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.
265 static inline void hw_crypto_check(void)
267 if (likely(crypto_ubicom32_on)) {
270 crypto_ubicom32_last_use = jiffies;
272 hw_crypto_ps_start();
277 * Init power save timer
279 static inline void hw_crypto_ps_init(void)
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;
288 * Initialize OCP security module lock and disables its clock.
290 static inline void hw_crypto_init(void)
292 if (!crypto_ubicom32_inited) {
293 crypto_ubicom32_inited = true;
294 spin_lock_init(&crypto_ubicom32_lock);
296 hw_crypto_turn_off();
302 * Locks the OCP security module and enables its clock.
304 static inline void hw_crypto_lock(void)
306 spin_lock_bh(&crypto_ubicom32_lock);
311 * Unlocks the OCP security module and disables its clock.
313 static inline void hw_crypto_unlock(void)
315 crypto_ubicom32_last_use = jiffies;
316 spin_unlock_bh(&crypto_ubicom32_lock);
319 #define CONFIG_CRYPTO_UBICOM32_DEBUG 1
321 #ifdef CONFIG_CRYPTO_UBICOM32_DEBUG
322 static inline void hex_dump(void *buf, int b_size, const char *msg)
327 printk("%s:\t", msg);
330 for (i=0; i < b_size; i++) {
331 printk("%02x ", b[i]);
335 if ((i & 31) == 31) {
341 #define UBICOM32_SEC_DUMP(a, b, c) hex_dump(a, b, c)
343 #define UBICOM32_SEC_DUMP(a, b, c)
346 #endif /* _CRYPTO_ARCH_UBICOM32_CRYPT_H */