1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2021 Nuvoton Technology Corp.
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <uboot_aes.h>
9 #include <asm/io.h>
10 #include <asm/arch/aes.h>
11 #include <asm/arch/otp.h>
12 #include <malloc.h>
13 
14 #define ONE_SECOND 0xC00000
15 
16 struct npcm_aes_priv {
17 	struct npcm_aes_regs *regs;
18 };
19 
20 static struct npcm_aes_priv *aes_priv;
21 static u8 fkeyind_to_set = 0xff;
22 
second_timeout(u32 * addr,u32 bitmask,u32 bitpol)23 static int second_timeout(u32 *addr, u32 bitmask, u32 bitpol)
24 {
25 	ulong time, i = 0;
26 
27 	time = get_timer(0);
28 
29 	/* default 1 second timeout */
30 	while (((readl(addr) & bitmask) == bitpol) && i < ONE_SECOND)
31 		i++;
32 
33 	if (i == ONE_SECOND) {
34 		printf("%xms timeout: addr = %x, mask = %x\n", (u32)get_timer(time),
35 		       *addr, bitmask);
36 		return -1;
37 	}
38 
39 	return 0;
40 }
41 
npcm_aes_select_key(u8 fkeyind)42 int npcm_aes_select_key(u8 fkeyind)
43 {
44 	if (npcm_otp_is_fuse_array_disabled(NPCM_KEY_SA)) {
45 		printf("AES key access denied\n");
46 		return -EACCES;
47 	}
48 
49 	if (fkeyind < 4)
50 		fkeyind_to_set = fkeyind;
51 
52 	return 0;
53 }
54 
npcm_aes_init(u8 dec_enc)55 static int npcm_aes_init(u8 dec_enc)
56 {
57 	struct npcm_aes_regs *regs = aes_priv->regs;
58 	u32 ctrl, orgctrlval, wrtimeout;
59 
60 	/* reset hw */
61 	writel(readl(&regs->aes_sw_reset) | SW_RESET_BIT, &regs->aes_sw_reset);
62 	writel(readl(&regs->aes_fifo_status) | DIN_FIFO_OVERFLOW, &regs->aes_fifo_status);
63 	writel(readl(&regs->aes_fifo_status) | DOUT_FIFO_UNDERFLOW, &regs->aes_fifo_status);
64 
65 	/* Workaround to over come Errata #648 */
66 	orgctrlval = readl(&regs->aes_control);
67 	ctrl = (0x00002004 | dec_enc);    /* AES256(CBC) */
68 
69 	if (ctrl != orgctrlval) {
70 		writel(ctrl, &regs->aes_control);
71 
72 		if (ctrl != readl(&regs->aes_control)) {
73 			u32 read_ctrl;
74 			int intwr;
75 
76 			for (wrtimeout = 0; wrtimeout < 1000; wrtimeout++) {
77 				for (intwr = 0 ; intwr < 10; intwr++) {
78 					writel(ctrl, &regs->aes_control);
79 					writew(ctrl, (u16 *)&regs->aes_control + 1);
80 					/* Write configurable info in a single write operation */
81 					mb();
82 				}
83 
84 				read_ctrl = readl(&regs->aes_control);
85 				if (ctrl == read_ctrl)
86 					break;
87 			}
88 
89 			if (wrtimeout == 1000) {
90 				printf("\nTIMEOUT expected data=0x%x Actual AES_CONTROL data 0x%x\n\n",
91 				       ctrl, read_ctrl);
92 				return -EAGAIN;
93 			}
94 
95 			printf("Workaround success, wrtimeout = %d\n", wrtimeout);
96 		}
97 	}
98 
99 	if (second_timeout(&regs->aes_busy, AES_BUSY_BIT, AES_BUSY_BIT))
100 		return -EAGAIN;
101 
102 	return 0;
103 }
104 
npcm_aes_load_iv(u8 * iv)105 static inline void npcm_aes_load_iv(u8 *iv)
106 {
107 	struct npcm_aes_regs *regs = aes_priv->regs;
108 	u32 *p = (u32 *)iv;
109 	u32 i;
110 
111 	/* Initialization Vector is loaded in 32-bit chunks */
112 	for (i = 0; i < (SIZE_AES_BLOCK / sizeof(u32)); i++)
113 		writel(p[i], &regs->aes_iv_0 + i);
114 }
115 
npcm_aes_load_key(u8 * key)116 static inline void npcm_aes_load_key(u8 *key)
117 {
118 	struct npcm_aes_regs *regs = aes_priv->regs;
119 	u32 *p = (u32 *)key;
120 	u32 i;
121 
122 	/* The key can be loaded either via the configuration or by using sideband
123 	 *  key port (aes_select_key).
124 	 *  If aes_select_key has been called ('fkeyind_to_set' was set to desired
125 	 *  key index) and no key is specified (key is NULL), we should use the
126 	 *  key index. Otherwise, we write the given key to the registers.
127 	 */
128 	if (!key && fkeyind_to_set < 4) {
129 		npcm_otp_select_key(fkeyind_to_set);
130 
131 		/* Sample the new key */
132 		writel(readl(&regs->aes_sk) | AES_SK_BIT, &regs->aes_sk);
133 
134 	} else {
135 		/* Initialization Vector is loaded in 32-bit chunks */
136 		for (i = 0; i < (2 * SIZE_AES_BLOCK / sizeof(u32)); i++)
137 			writel(p[i], &regs->aes_key_0 + i);
138 
139 		fkeyind_to_set = 0xff;
140 	}
141 }
142 
npcm_aes_write(u32 * in)143 static inline void npcm_aes_write(u32 *in)
144 {
145 	struct npcm_aes_regs *regs = aes_priv->regs;
146 	u32 i;
147 
148 	/* 16 Byte AES Block is written in 32-bit chunks */
149 	for (i = 0; i < (SIZE_AES_BLOCK / sizeof(u32)); i++)
150 		writel(in[i], &regs->aes_fifo_data);
151 }
152 
npcm_aes_read(u32 * out)153 static inline void npcm_aes_read(u32 *out)
154 {
155 	struct npcm_aes_regs *regs = aes_priv->regs;
156 	u32 i;
157 
158 	/* Data is read in 32-bit chunks */
159 	for (i = 0; i < (SIZE_AES_BLOCK / sizeof(u32)); i++)
160 		out[i] = readl(&regs->aes_fifo_data);
161 }
162 
npcm_aes_feed(u32 num_aes_blocks,u32 * datain,u32 * dataout)163 static void npcm_aes_feed(u32 num_aes_blocks, u32 *datain, u32 *dataout)
164 {
165 	struct npcm_aes_regs *regs = aes_priv->regs;
166 	u32 aes_datablk;
167 	u32 total_blocks = num_aes_blocks;
168 	u32 blocks_left = num_aes_blocks;
169 
170 	/* data mode */
171 	writel(readl(&regs->aes_busy) | AES_BUSY_BIT, &regs->aes_busy);
172 
173 	/* Clear overflow and underflow */
174 	writel(readl(&regs->aes_fifo_status) | DIN_FIFO_OVERFLOW, &regs->aes_fifo_status);
175 	writel(readl(&regs->aes_fifo_status) | DOUT_FIFO_UNDERFLOW, &regs->aes_fifo_status);
176 
177 	/* datain/dataout is advanced in 32-bit chunks */
178 	aes_datablk = (SIZE_AES_BLOCK / sizeof(u32));
179 
180 	/* Quit if there is no complete blocks */
181 	if (total_blocks == 0)
182 		return;
183 
184 	/* Write the first block */
185 	if (total_blocks > 1) {
186 		npcm_aes_write(datain);
187 		datain += aes_datablk;
188 		blocks_left--;
189 	}
190 
191 	/* Write the second block */
192 	if (total_blocks > 2) {
193 		second_timeout(&regs->aes_fifo_status, DIN_FIFO_EMPTY, 0);
194 		npcm_aes_write(datain);
195 		datain += aes_datablk;
196 		blocks_left--;
197 	}
198 
199 	/* Write & read available blocks */
200 	while (blocks_left > 0) {
201 		second_timeout(&regs->aes_fifo_status, DIN_FIFO_FULL, DIN_FIFO_FULL);
202 
203 		/* Write next block */
204 		npcm_aes_write(datain);
205 		datain  += aes_datablk;
206 
207 		/* Wait till DOUT FIFO is empty */
208 		second_timeout(&regs->aes_fifo_status, DOUT_FIFO_EMPTY, DOUT_FIFO_EMPTY);
209 
210 		/* Read next block */
211 		npcm_aes_read(dataout);
212 		dataout += aes_datablk;
213 
214 		blocks_left--;
215 	}
216 
217 	if (total_blocks > 2) {
218 		second_timeout(&regs->aes_fifo_status, DOUT_FIFO_FULL, 0);
219 
220 		/* Read next block */
221 		npcm_aes_read(dataout);
222 		dataout += aes_datablk;
223 
224 		second_timeout(&regs->aes_fifo_status, DOUT_FIFO_FULL, 0);
225 
226 		/* Read next block */
227 		npcm_aes_read(dataout);
228 		dataout += aes_datablk;
229 	} else if (total_blocks > 1) {
230 		second_timeout(&regs->aes_fifo_status, DOUT_FIFO_FULL, 0);
231 
232 		/* Read next block */
233 		npcm_aes_read(dataout);
234 		dataout += aes_datablk;
235 	}
236 }
237 
aes_expand_key(u8 * key,u32 key_size,u8 * expkey)238 void aes_expand_key(u8 *key, u32 key_size, u8 *expkey)
239 {
240 	/* npcm hw expands the key automatically, just copy it */
241 	memcpy(expkey, key, SIZE_AES_BLOCK * 2);
242 }
243 
aes_cbc_encrypt_blocks(u32 key_size,u8 * key_exp,u8 * iv,u8 * src,u8 * dst,u32 num_aes_blocks)244 void aes_cbc_encrypt_blocks(u32 key_size, u8 *key_exp, u8 *iv, u8 *src, u8 *dst,
245 			    u32 num_aes_blocks)
246 {
247 	if (npcm_aes_init(AES_OP_ENCRYPT))
248 		return;
249 
250 	npcm_aes_load_iv(iv);
251 
252 	npcm_aes_load_key(key_exp);
253 
254 	npcm_aes_feed(num_aes_blocks, (u32 *)src, (u32 *)dst);
255 }
256 
aes_cbc_decrypt_blocks(u32 key_size,u8 * key_exp,u8 * iv,u8 * src,u8 * dst,u32 num_aes_blocks)257 void aes_cbc_decrypt_blocks(u32 key_size, u8 *key_exp, u8 *iv, u8 *src, u8 *dst,
258 			    u32 num_aes_blocks)
259 {
260 	if (npcm_aes_init(AES_OP_DECRYPT))
261 		return;
262 
263 	npcm_aes_load_iv(iv);
264 
265 	npcm_aes_load_key(key_exp);
266 
267 	npcm_aes_feed(num_aes_blocks, (u32 *)src, (u32 *)dst);
268 }
269 
npcm_aes_bind(struct udevice * dev)270 static int npcm_aes_bind(struct udevice *dev)
271 {
272 	aes_priv = calloc(1, sizeof(struct npcm_aes_priv));
273 	if (!aes_priv) {
274 		printf("%s: %d\n", __func__, __LINE__);
275 		return -ENOMEM;
276 	}
277 
278 	aes_priv->regs = dev_read_addr_ptr(dev);
279 	if (!aes_priv->regs) {
280 		printf("Cannot find aes reg address, binding failed\n");
281 		return -EINVAL;
282 	}
283 
284 	printf("AES: NPCM AES module bind OK\n");
285 
286 	return 0;
287 }
288 
289 static const struct udevice_id npcm_aes_ids[] = {
290 	{ .compatible = "nuvoton,npcm845-aes" },
291 	{ .compatible = "nuvoton,npcm750-aes" },
292 	{ }
293 };
294 
295 U_BOOT_DRIVER(npcm_aes) = {
296 	.name = "npcm_aes",
297 	.id = UCLASS_MISC,
298 	.of_match = npcm_aes_ids,
299 	.priv_auto = sizeof(struct npcm_aes_priv),
300 	.bind = npcm_aes_bind,
301 };
302