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 16struct npcm_aes_priv { 17 struct npcm_aes_regs *regs; 18}; 19 20static struct npcm_aes_priv *aes_priv; 21static u8 fkeyind_to_set = 0xff; 22 23static 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 42int 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 55static 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(®s->aes_sw_reset) | SW_RESET_BIT, ®s->aes_sw_reset); 62 writel(readl(®s->aes_fifo_status) | DIN_FIFO_OVERFLOW, ®s->aes_fifo_status); 63 writel(readl(®s->aes_fifo_status) | DOUT_FIFO_UNDERFLOW, ®s->aes_fifo_status); 64 65 /* Workaround to over come Errata #648 */ 66 orgctrlval = readl(®s->aes_control); 67 ctrl = (0x00002004 | dec_enc); /* AES256(CBC) */ 68 69 if (ctrl != orgctrlval) { 70 writel(ctrl, ®s->aes_control); 71 72 if (ctrl != readl(®s->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, ®s->aes_control); 79 writew(ctrl, (u16 *)®s->aes_control + 1); 80 /* Write configurable info in a single write operation */ 81 mb(); 82 } 83 84 read_ctrl = readl(®s->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(®s->aes_busy, AES_BUSY_BIT, AES_BUSY_BIT)) 100 return -EAGAIN; 101 102 return 0; 103} 104 105static 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], ®s->aes_iv_0 + i); 114} 115 116static 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(®s->aes_sk) | AES_SK_BIT, ®s->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], ®s->aes_key_0 + i); 138 139 fkeyind_to_set = 0xff; 140 } 141} 142 143static 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], ®s->aes_fifo_data); 151} 152 153static 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(®s->aes_fifo_data); 161} 162 163static 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(®s->aes_busy) | AES_BUSY_BIT, ®s->aes_busy); 172 173 /* Clear overflow and underflow */ 174 writel(readl(®s->aes_fifo_status) | DIN_FIFO_OVERFLOW, ®s->aes_fifo_status); 175 writel(readl(®s->aes_fifo_status) | DOUT_FIFO_UNDERFLOW, ®s->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(®s->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(®s->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(®s->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(®s->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(®s->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(®s->aes_fifo_status, DOUT_FIFO_FULL, 0); 231 232 /* Read next block */ 233 npcm_aes_read(dataout); 234 dataout += aes_datablk; 235 } 236} 237 238void 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 244void 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 257void 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 270static 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 289static const struct udevice_id npcm_aes_ids[] = { 290 { .compatible = "nuvoton,npcm845-aes" }, 291 { .compatible = "nuvoton,npcm750-aes" }, 292 { } 293}; 294 295U_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