00001
00047 #include <assert.h>
00048 #include <debug.h>
00049 #include <malloc.h>
00050 #include <status-codes.h>
00051 #include <string.h>
00052 #include <interrupt.h>
00053 #include <chip/memory-map.h>
00054 #include <aes.h>
00055
00056 #include "aes_regs.h"
00057
00068 void aes_init(struct aes_module *module, uint32_t mode)
00069 {
00070 assert(module);
00071
00072 module->port = (void *)AES_BASE;
00073 module->mode = mode | AES_MR_START_MODE_DMA;
00074
00075 aes_write_reg(module->port, CR, AES_CR_SWRST);
00076 aes_write_reg(module->port, MR, module->mode);
00077
00078 module->dma_rx_channel = dmac_aes_alloc_rx_channel();
00079 module->dma_tx_channel = dmac_aes_alloc_tx_channel();
00080
00081 module->counter = 0;
00082 }
00083
00092 void aes_free(struct aes_module *module)
00093 {
00094 assert(module);
00095
00096 module->port = NULL;
00097 dmac_aes_free_channel(module->dma_rx_channel);
00098 dmac_aes_free_channel(module->dma_tx_channel);
00099 }
00100
00110 void aes_set_cipher(struct aes_module *module, uint32_t mode)
00111 {
00112 assert(module);
00113
00114 module->mode = (module->mode & ~AES_MR_CIPHER_MASK) |
00115 (mode & AES_MR_CIPHER_MASK);
00116
00117 aes_write_reg(module->port, CR, AES_CR_SWRST);
00118 aes_write_reg(module->port, MR, module->mode);
00119 }
00120
00129 uint32_t aes_get_cipher(struct aes_module *module)
00130 {
00131 assert(module);
00132
00133 return (module->mode & AES_MR_CIPHER_MASK);
00134 }
00135
00145 void aes_load_init_vector(struct aes_module *module, const uint32_t *vector)
00146 {
00147 int i;
00148
00149 assert(module);
00150 assert(vector);
00151
00152 for (i = 0; i < 4; i++)
00153 aes_write_init_reg(module->port, i, *vector++);
00154 }
00155
00167 void aes_load_key(struct aes_module *module, const uint32_t *key)
00168 {
00169 int i;
00170 int key_length = 0;
00171
00172 assert(module);
00173 assert(key);
00174
00175 switch (module->mode & AES_KEYSIZE_MASK) {
00176 case AES_KEYSIZE_128:
00177 key_length = 4;
00178 break;
00179 case AES_KEYSIZE_192:
00180 key_length = 6;
00181 break;
00182 case AES_KEYSIZE_256:
00183 key_length = 8;
00184 break;
00185 default:
00186 unhandled_case(module->mode);
00187 }
00188
00189 for (i = 0; i < key_length; i++)
00190 aes_write_key_reg(module->port, i, *key++);
00191 }
00192
00201 void aes_free_duplicate_buffers(struct slist *buf_list)
00202 {
00203 struct buffer *buf;
00204
00205 assert(buf_list);
00206
00207 while (!slist_is_empty(buf_list)) {
00208 buf = slist_pop_head(buf_list, struct buffer, node);
00209 buffer_free(buf);
00210 }
00211 }
00212
00228 int aes_duplicate_buffer_refs(struct slist *copy, struct slist *original)
00229 {
00230 struct buffer *buf;
00231 struct buffer *temp;
00232
00233 assert(copy);
00234 assert(original);
00235
00236 slist_for_each(original, buf, node) {
00237 temp = buffer_alloc();
00238 if (unlikely(!temp))
00239 goto ret_error;
00240 temp->addr.ptr = buf->addr.ptr;
00241 temp->addr.phys = buf->addr.phys;
00242 temp->len = buf->len;
00243 slist_insert_tail(copy, &temp->node);
00244 }
00245 return 0;
00246
00247 ret_error:
00248 aes_free_duplicate_buffers(copy);
00249 return -1;
00250 }
00251
00252 static void aes_dma_tx_done(struct dmac_channel *chan,
00253 struct dmac_request *req)
00254 {
00255 struct aes_request *areq = req->context;
00256
00257 aes_free_duplicate_buffers(&req->buf_list);
00258 free(req);
00259
00260 if (++areq->done_counter >= 2 && areq->req_done)
00261 areq->req_done(areq, &areq->rx_buf_list, areq->context);
00262 }
00263
00264 static void aes_dma_rx_done(struct dmac_channel *chan,
00265 struct dmac_request *req)
00266 {
00267 struct aes_request *areq = req->context;
00268 unsigned int iflags;
00269
00270 assert(req);
00271 assert(areq);
00272
00273 iflags = cpu_irq_save();
00274 if (!slist_is_empty(&req->buf_list))
00275 slist_move_to_tail(&areq->rx_buf_list, &req->buf_list);
00276 cpu_irq_restore(iflags);
00277
00278 free(req);
00279
00280 if (++areq->done_counter >= 2 && areq->req_done)
00281 areq->req_done(areq, &areq->rx_buf_list, areq->context);
00282 }
00283
00284 static void aes_dma_req_init(struct dmac_request *req,
00285 struct aes_request *areq, enum dma_direction dir)
00286 {
00287 memset(req, 0, sizeof(struct dmac_request));
00288 dmac_req_init(req);
00289 req->direction = dir;
00290
00291 switch (dir) {
00292 case DMA_TO_DEVICE:
00293 req->req_done = aes_dma_tx_done;
00294 break;
00295
00296 case DMA_FROM_DEVICE:
00297 req->req_done = aes_dma_rx_done;
00298 break;
00299
00300 default:
00301 unhandled_case(dir);
00302 }
00303
00304 req->reg_width = DMAC_REG_WIDTH_32BIT;
00305 req->burst_length = DMAC_BURST_LENGTH_4;
00306 req->context = areq;
00307 }
00308
00320 void aes_submit_request(struct aes_request *req)
00321 {
00322 struct dmac_request *tx_req = &req->tx_req;
00323 struct dmac_request *rx_req = &req->rx_req;
00324
00325 assert(req);
00326
00327 aes_dma_req_init(tx_req, req, DMA_TO_DEVICE);
00328 aes_dma_req_init(rx_req, req, DMA_FROM_DEVICE);
00329 req->done_counter = 0;
00330
00331 if (!slist_is_empty(&req->tx_buf_list)) {
00332
00333 slist_move_to_tail(&tx_req->buf_list, &req->tx_buf_list);
00334 slist_move_to_tail(&rx_req->buf_list, &req->rx_buf_list);
00335
00336
00337 dmac_chan_submit_request(req->module->dma_rx_channel, rx_req);
00338 dmac_chan_submit_request(req->module->dma_tx_channel, tx_req);
00339 } else {
00340
00341
00342 aes_dma_tx_done(req->module->dma_tx_channel, tx_req);
00343 aes_dma_rx_done(req->module->dma_rx_channel, rx_req);
00344 }
00345 }
00346
00356 struct aes_request *aes_alloc_request(struct aes_module *module)
00357 {
00358 struct aes_request *req;
00359
00360 assert(module);
00361
00362 assert(module->port);
00363
00364 req = malloc(sizeof(struct aes_request));
00365 assert(req);
00366 req->module = module;
00367
00368 return req;
00369 }
00370
00378 void aes_free_request(struct aes_request *req)
00379 {
00380 assert(slist_is_empty(&req->tx_buf_list));
00381 assert(slist_is_empty(&req->rx_buf_list));
00382
00383 free(req);
00384 }
00385
00399 void aes_prepare_request(struct aes_request *req, struct slist *buf_list)
00400 {
00401 slist_init(&req->tx_buf_list);
00402 slist_init(&req->rx_buf_list);
00403
00404 if (!slist_is_empty(buf_list)) {
00405 assert(!aes_duplicate_buffer_refs(
00406 &req->rx_buf_list, buf_list));
00407 slist_move_to_tail(&req->tx_buf_list, buf_list);
00408 }
00409 }