Blame view
drivers/crypto/s5p-sss.c
19.4 KB
a49e490c7 crypto: s5p-sss -... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* * Cryptographic API. * * Support for Samsung S5PV210 HW acceleration. * * Copyright (C) 2011 NetUP Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include <linux/delay.h> #include <linux/err.h> #include <linux/module.h> #include <linux/init.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/clk.h> #include <linux/platform_device.h> #include <linux/scatterlist.h> #include <linux/dma-mapping.h> #include <linux/io.h> |
6b9f16e6c crypto: s5p-sss -... |
25 |
#include <linux/of.h> |
a49e490c7 crypto: s5p-sss -... |
26 27 28 29 30 31 |
#include <linux/crypto.h> #include <linux/interrupt.h> #include <crypto/algapi.h> #include <crypto/aes.h> #include <crypto/ctr.h> |
a49e490c7 crypto: s5p-sss -... |
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
#define _SBF(s, v) ((v) << (s)) #define _BIT(b) _SBF(b, 1) /* Feed control registers */ #define SSS_REG_FCINTSTAT 0x0000 #define SSS_FCINTSTAT_BRDMAINT _BIT(3) #define SSS_FCINTSTAT_BTDMAINT _BIT(2) #define SSS_FCINTSTAT_HRDMAINT _BIT(1) #define SSS_FCINTSTAT_PKDMAINT _BIT(0) #define SSS_REG_FCINTENSET 0x0004 #define SSS_FCINTENSET_BRDMAINTENSET _BIT(3) #define SSS_FCINTENSET_BTDMAINTENSET _BIT(2) #define SSS_FCINTENSET_HRDMAINTENSET _BIT(1) #define SSS_FCINTENSET_PKDMAINTENSET _BIT(0) #define SSS_REG_FCINTENCLR 0x0008 #define SSS_FCINTENCLR_BRDMAINTENCLR _BIT(3) #define SSS_FCINTENCLR_BTDMAINTENCLR _BIT(2) #define SSS_FCINTENCLR_HRDMAINTENCLR _BIT(1) #define SSS_FCINTENCLR_PKDMAINTENCLR _BIT(0) #define SSS_REG_FCINTPEND 0x000C #define SSS_FCINTPEND_BRDMAINTP _BIT(3) #define SSS_FCINTPEND_BTDMAINTP _BIT(2) #define SSS_FCINTPEND_HRDMAINTP _BIT(1) #define SSS_FCINTPEND_PKDMAINTP _BIT(0) #define SSS_REG_FCFIFOSTAT 0x0010 #define SSS_FCFIFOSTAT_BRFIFOFUL _BIT(7) #define SSS_FCFIFOSTAT_BRFIFOEMP _BIT(6) #define SSS_FCFIFOSTAT_BTFIFOFUL _BIT(5) #define SSS_FCFIFOSTAT_BTFIFOEMP _BIT(4) #define SSS_FCFIFOSTAT_HRFIFOFUL _BIT(3) #define SSS_FCFIFOSTAT_HRFIFOEMP _BIT(2) #define SSS_FCFIFOSTAT_PKFIFOFUL _BIT(1) #define SSS_FCFIFOSTAT_PKFIFOEMP _BIT(0) #define SSS_REG_FCFIFOCTRL 0x0014 #define SSS_FCFIFOCTRL_DESSEL _BIT(2) #define SSS_HASHIN_INDEPENDENT _SBF(0, 0x00) #define SSS_HASHIN_CIPHER_INPUT _SBF(0, 0x01) #define SSS_HASHIN_CIPHER_OUTPUT _SBF(0, 0x02) #define SSS_REG_FCBRDMAS 0x0020 #define SSS_REG_FCBRDMAL 0x0024 #define SSS_REG_FCBRDMAC 0x0028 #define SSS_FCBRDMAC_BYTESWAP _BIT(1) #define SSS_FCBRDMAC_FLUSH _BIT(0) #define SSS_REG_FCBTDMAS 0x0030 #define SSS_REG_FCBTDMAL 0x0034 #define SSS_REG_FCBTDMAC 0x0038 #define SSS_FCBTDMAC_BYTESWAP _BIT(1) #define SSS_FCBTDMAC_FLUSH _BIT(0) #define SSS_REG_FCHRDMAS 0x0040 #define SSS_REG_FCHRDMAL 0x0044 #define SSS_REG_FCHRDMAC 0x0048 #define SSS_FCHRDMAC_BYTESWAP _BIT(1) #define SSS_FCHRDMAC_FLUSH _BIT(0) #define SSS_REG_FCPKDMAS 0x0050 #define SSS_REG_FCPKDMAL 0x0054 #define SSS_REG_FCPKDMAC 0x0058 #define SSS_FCPKDMAC_BYTESWAP _BIT(3) #define SSS_FCPKDMAC_DESCEND _BIT(2) #define SSS_FCPKDMAC_TRANSMIT _BIT(1) #define SSS_FCPKDMAC_FLUSH _BIT(0) #define SSS_REG_FCPKDMAO 0x005C /* AES registers */ |
892451071 crypto: s5p-sss -... |
105 |
#define SSS_REG_AES_CONTROL 0x00 |
a49e490c7 crypto: s5p-sss -... |
106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
#define SSS_AES_BYTESWAP_DI _BIT(11) #define SSS_AES_BYTESWAP_DO _BIT(10) #define SSS_AES_BYTESWAP_IV _BIT(9) #define SSS_AES_BYTESWAP_CNT _BIT(8) #define SSS_AES_BYTESWAP_KEY _BIT(7) #define SSS_AES_KEY_CHANGE_MODE _BIT(6) #define SSS_AES_KEY_SIZE_128 _SBF(4, 0x00) #define SSS_AES_KEY_SIZE_192 _SBF(4, 0x01) #define SSS_AES_KEY_SIZE_256 _SBF(4, 0x02) #define SSS_AES_FIFO_MODE _BIT(3) #define SSS_AES_CHAIN_MODE_ECB _SBF(1, 0x00) #define SSS_AES_CHAIN_MODE_CBC _SBF(1, 0x01) #define SSS_AES_CHAIN_MODE_CTR _SBF(1, 0x02) #define SSS_AES_MODE_DECRYPT _BIT(0) |
892451071 crypto: s5p-sss -... |
120 |
#define SSS_REG_AES_STATUS 0x04 |
a49e490c7 crypto: s5p-sss -... |
121 122 123 |
#define SSS_AES_BUSY _BIT(2) #define SSS_AES_INPUT_READY _BIT(1) #define SSS_AES_OUTPUT_READY _BIT(0) |
892451071 crypto: s5p-sss -... |
124 125 126 127 128 |
#define SSS_REG_AES_IN_DATA(s) (0x10 + (s << 2)) #define SSS_REG_AES_OUT_DATA(s) (0x20 + (s << 2)) #define SSS_REG_AES_IV_DATA(s) (0x30 + (s << 2)) #define SSS_REG_AES_CNT_DATA(s) (0x40 + (s << 2)) #define SSS_REG_AES_KEY_DATA(s) (0x80 + (s << 2)) |
a49e490c7 crypto: s5p-sss -... |
129 130 131 132 |
#define SSS_REG(dev, reg) ((dev)->ioaddr + (SSS_REG_##reg)) #define SSS_READ(dev, reg) __raw_readl(SSS_REG(dev, reg)) #define SSS_WRITE(dev, reg, val) __raw_writel((val), SSS_REG(dev, reg)) |
892451071 crypto: s5p-sss -... |
133 134 135 |
#define SSS_AES_REG(dev, reg) ((dev)->aes_ioaddr + SSS_REG_##reg) #define SSS_AES_WRITE(dev, reg, val) __raw_writel((val), \ SSS_AES_REG(dev, reg)) |
a49e490c7 crypto: s5p-sss -... |
136 137 138 139 140 141 142 143 |
/* HW engine modes */ #define FLAGS_AES_DECRYPT _BIT(0) #define FLAGS_AES_MODE_MASK _SBF(1, 0x03) #define FLAGS_AES_CBC _SBF(1, 0x01) #define FLAGS_AES_CTR _SBF(1, 0x02) #define AES_KEY_LEN 16 #define CRYPTO_QUEUE_LEN 1 |
892451071 crypto: s5p-sss -... |
144 145 146 147 148 149 150 151 152 153 154 155 156 |
/** * struct samsung_aes_variant - platform specific SSS driver data * @has_hash_irq: true if SSS module uses hash interrupt, false otherwise * @aes_offset: AES register offset from SSS module's base. * * Specifies platform specific configuration of SSS module. * Note: A structure for driver specific platform data is used for future * expansion of its usage. */ struct samsung_aes_variant { bool has_hash_irq; unsigned int aes_offset; }; |
a49e490c7 crypto: s5p-sss -... |
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
struct s5p_aes_reqctx { unsigned long mode; }; struct s5p_aes_ctx { struct s5p_aes_dev *dev; uint8_t aes_key[AES_MAX_KEY_SIZE]; uint8_t nonce[CTR_RFC3686_NONCE_SIZE]; int keylen; }; struct s5p_aes_dev { struct device *dev; struct clk *clk; void __iomem *ioaddr; |
892451071 crypto: s5p-sss -... |
173 |
void __iomem *aes_ioaddr; |
a49e490c7 crypto: s5p-sss -... |
174 175 176 177 178 179 180 181 182 183 184 185 |
int irq_hash; int irq_fc; struct ablkcipher_request *req; struct s5p_aes_ctx *ctx; struct scatterlist *sg_src; struct scatterlist *sg_dst; struct tasklet_struct tasklet; struct crypto_queue queue; bool busy; spinlock_t lock; |
892451071 crypto: s5p-sss -... |
186 187 |
struct samsung_aes_variant *variant; |
a49e490c7 crypto: s5p-sss -... |
188 189 190 |
}; static struct s5p_aes_dev *s5p_dev; |
892451071 crypto: s5p-sss -... |
191 192 193 194 195 196 197 198 199 |
static const struct samsung_aes_variant s5p_aes_data = { .has_hash_irq = true, .aes_offset = 0x4000, }; static const struct samsung_aes_variant exynos_aes_data = { .has_hash_irq = false, .aes_offset = 0x200, }; |
6b9f16e6c crypto: s5p-sss -... |
200 |
static const struct of_device_id s5p_sss_dt_match[] = { |
892451071 crypto: s5p-sss -... |
201 202 203 204 205 206 207 208 |
{ .compatible = "samsung,s5pv210-secss", .data = &s5p_aes_data, }, { .compatible = "samsung,exynos4210-secss", .data = &exynos_aes_data, }, |
6b9f16e6c crypto: s5p-sss -... |
209 210 211 |
{ }, }; MODULE_DEVICE_TABLE(of, s5p_sss_dt_match); |
892451071 crypto: s5p-sss -... |
212 213 214 215 216 217 218 219 220 221 222 223 |
static inline struct samsung_aes_variant *find_s5p_sss_version (struct platform_device *pdev) { if (IS_ENABLED(CONFIG_OF) && (pdev->dev.of_node)) { const struct of_device_id *match; match = of_match_node(s5p_sss_dt_match, pdev->dev.of_node); return (struct samsung_aes_variant *)match->data; } return (struct samsung_aes_variant *) platform_get_device_id(pdev)->driver_data; } |
a49e490c7 crypto: s5p-sss -... |
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
static void s5p_set_dma_indata(struct s5p_aes_dev *dev, struct scatterlist *sg) { SSS_WRITE(dev, FCBRDMAS, sg_dma_address(sg)); SSS_WRITE(dev, FCBRDMAL, sg_dma_len(sg)); } static void s5p_set_dma_outdata(struct s5p_aes_dev *dev, struct scatterlist *sg) { SSS_WRITE(dev, FCBTDMAS, sg_dma_address(sg)); SSS_WRITE(dev, FCBTDMAL, sg_dma_len(sg)); } static void s5p_aes_complete(struct s5p_aes_dev *dev, int err) { /* holding a lock outside */ dev->req->base.complete(&dev->req->base, err); dev->busy = false; } static void s5p_unset_outdata(struct s5p_aes_dev *dev) { dma_unmap_sg(dev->dev, dev->sg_dst, 1, DMA_FROM_DEVICE); } static void s5p_unset_indata(struct s5p_aes_dev *dev) { dma_unmap_sg(dev->dev, dev->sg_src, 1, DMA_TO_DEVICE); } static int s5p_set_outdata(struct s5p_aes_dev *dev, struct scatterlist *sg) { int err; if (!IS_ALIGNED(sg_dma_len(sg), AES_BLOCK_SIZE)) { err = -EINVAL; goto exit; } if (!sg_dma_len(sg)) { err = -EINVAL; goto exit; } err = dma_map_sg(dev->dev, sg, 1, DMA_FROM_DEVICE); if (!err) { err = -ENOMEM; goto exit; } dev->sg_dst = sg; err = 0; exit: return err; } static int s5p_set_indata(struct s5p_aes_dev *dev, struct scatterlist *sg) { int err; if (!IS_ALIGNED(sg_dma_len(sg), AES_BLOCK_SIZE)) { err = -EINVAL; goto exit; } if (!sg_dma_len(sg)) { err = -EINVAL; goto exit; } err = dma_map_sg(dev->dev, sg, 1, DMA_TO_DEVICE); if (!err) { err = -ENOMEM; goto exit; } dev->sg_src = sg; err = 0; exit: return err; } static void s5p_aes_tx(struct s5p_aes_dev *dev) { int err = 0; s5p_unset_outdata(dev); if (!sg_is_last(dev->sg_dst)) { err = s5p_set_outdata(dev, sg_next(dev->sg_dst)); if (err) { s5p_aes_complete(dev, err); return; } s5p_set_dma_outdata(dev, dev->sg_dst); |
dc5e3f195 crypto: s5p-sss -... |
319 |
} else { |
a49e490c7 crypto: s5p-sss -... |
320 |
s5p_aes_complete(dev, err); |
dc5e3f195 crypto: s5p-sss -... |
321 322 323 324 |
dev->busy = true; tasklet_schedule(&dev->tasklet); } |
a49e490c7 crypto: s5p-sss -... |
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
} static void s5p_aes_rx(struct s5p_aes_dev *dev) { int err; s5p_unset_indata(dev); if (!sg_is_last(dev->sg_src)) { err = s5p_set_indata(dev, sg_next(dev->sg_src)); if (err) { s5p_aes_complete(dev, err); return; } s5p_set_dma_indata(dev, dev->sg_src); } } static irqreturn_t s5p_aes_interrupt(int irq, void *dev_id) { struct platform_device *pdev = dev_id; struct s5p_aes_dev *dev = platform_get_drvdata(pdev); uint32_t status; unsigned long flags; spin_lock_irqsave(&dev->lock, flags); if (irq == dev->irq_fc) { status = SSS_READ(dev, FCINTSTAT); if (status & SSS_FCINTSTAT_BRDMAINT) s5p_aes_rx(dev); if (status & SSS_FCINTSTAT_BTDMAINT) s5p_aes_tx(dev); SSS_WRITE(dev, FCINTPEND, status); } spin_unlock_irqrestore(&dev->lock, flags); return IRQ_HANDLED; } static void s5p_set_aes(struct s5p_aes_dev *dev, uint8_t *key, uint8_t *iv, unsigned int keylen) { void __iomem *keystart; |
8f9702aad crypto: s5p-sss -... |
372 373 |
if (iv) memcpy(dev->aes_ioaddr + SSS_REG_AES_IV_DATA(0), iv, 0x10); |
a49e490c7 crypto: s5p-sss -... |
374 375 |
if (keylen == AES_KEYSIZE_256) |
892451071 crypto: s5p-sss -... |
376 |
keystart = dev->aes_ioaddr + SSS_REG_AES_KEY_DATA(0); |
a49e490c7 crypto: s5p-sss -... |
377 |
else if (keylen == AES_KEYSIZE_192) |
892451071 crypto: s5p-sss -... |
378 |
keystart = dev->aes_ioaddr + SSS_REG_AES_KEY_DATA(2); |
a49e490c7 crypto: s5p-sss -... |
379 |
else |
892451071 crypto: s5p-sss -... |
380 |
keystart = dev->aes_ioaddr + SSS_REG_AES_KEY_DATA(4); |
a49e490c7 crypto: s5p-sss -... |
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 |
memcpy(keystart, key, keylen); } static void s5p_aes_crypt_start(struct s5p_aes_dev *dev, unsigned long mode) { struct ablkcipher_request *req = dev->req; uint32_t aes_control; int err; unsigned long flags; aes_control = SSS_AES_KEY_CHANGE_MODE; if (mode & FLAGS_AES_DECRYPT) aes_control |= SSS_AES_MODE_DECRYPT; if ((mode & FLAGS_AES_MODE_MASK) == FLAGS_AES_CBC) aes_control |= SSS_AES_CHAIN_MODE_CBC; else if ((mode & FLAGS_AES_MODE_MASK) == FLAGS_AES_CTR) aes_control |= SSS_AES_CHAIN_MODE_CTR; if (dev->ctx->keylen == AES_KEYSIZE_192) aes_control |= SSS_AES_KEY_SIZE_192; else if (dev->ctx->keylen == AES_KEYSIZE_256) aes_control |= SSS_AES_KEY_SIZE_256; aes_control |= SSS_AES_FIFO_MODE; /* as a variant it is possible to use byte swapping on DMA side */ aes_control |= SSS_AES_BYTESWAP_DI | SSS_AES_BYTESWAP_DO | SSS_AES_BYTESWAP_IV | SSS_AES_BYTESWAP_KEY | SSS_AES_BYTESWAP_CNT; spin_lock_irqsave(&dev->lock, flags); SSS_WRITE(dev, FCINTENCLR, SSS_FCINTENCLR_BTDMAINTENCLR | SSS_FCINTENCLR_BRDMAINTENCLR); SSS_WRITE(dev, FCFIFOCTRL, 0x00); err = s5p_set_indata(dev, req->src); if (err) goto indata_error; err = s5p_set_outdata(dev, req->dst); if (err) goto outdata_error; |
892451071 crypto: s5p-sss -... |
429 |
SSS_AES_WRITE(dev, AES_CONTROL, aes_control); |
a49e490c7 crypto: s5p-sss -... |
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 |
s5p_set_aes(dev, dev->ctx->aes_key, req->info, dev->ctx->keylen); s5p_set_dma_indata(dev, req->src); s5p_set_dma_outdata(dev, req->dst); SSS_WRITE(dev, FCINTENSET, SSS_FCINTENSET_BTDMAINTENSET | SSS_FCINTENSET_BRDMAINTENSET); spin_unlock_irqrestore(&dev->lock, flags); return; outdata_error: s5p_unset_indata(dev); indata_error: s5p_aes_complete(dev, err); spin_unlock_irqrestore(&dev->lock, flags); } static void s5p_tasklet_cb(unsigned long data) { struct s5p_aes_dev *dev = (struct s5p_aes_dev *)data; struct crypto_async_request *async_req, *backlog; struct s5p_aes_reqctx *reqctx; unsigned long flags; spin_lock_irqsave(&dev->lock, flags); backlog = crypto_get_backlog(&dev->queue); async_req = crypto_dequeue_request(&dev->queue); |
a49e490c7 crypto: s5p-sss -... |
460 |
|
dc5e3f195 crypto: s5p-sss -... |
461 462 463 |
if (!async_req) { dev->busy = false; spin_unlock_irqrestore(&dev->lock, flags); |
a49e490c7 crypto: s5p-sss -... |
464 |
return; |
dc5e3f195 crypto: s5p-sss -... |
465 466 |
} spin_unlock_irqrestore(&dev->lock, flags); |
a49e490c7 crypto: s5p-sss -... |
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 |
if (backlog) backlog->complete(backlog, -EINPROGRESS); dev->req = ablkcipher_request_cast(async_req); dev->ctx = crypto_tfm_ctx(dev->req->base.tfm); reqctx = ablkcipher_request_ctx(dev->req); s5p_aes_crypt_start(dev, reqctx->mode); } static int s5p_aes_handle_req(struct s5p_aes_dev *dev, struct ablkcipher_request *req) { unsigned long flags; int err; spin_lock_irqsave(&dev->lock, flags); |
dc5e3f195 crypto: s5p-sss -... |
485 |
err = ablkcipher_enqueue_request(&dev->queue, req); |
a49e490c7 crypto: s5p-sss -... |
486 |
if (dev->busy) { |
a49e490c7 crypto: s5p-sss -... |
487 488 489 490 |
spin_unlock_irqrestore(&dev->lock, flags); goto exit; } dev->busy = true; |
a49e490c7 crypto: s5p-sss -... |
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 |
spin_unlock_irqrestore(&dev->lock, flags); tasklet_schedule(&dev->tasklet); exit: return err; } static int s5p_aes_crypt(struct ablkcipher_request *req, unsigned long mode) { struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); struct s5p_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); struct s5p_aes_reqctx *reqctx = ablkcipher_request_ctx(req); struct s5p_aes_dev *dev = ctx->dev; if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) { pr_err("request size is not exact amount of AES blocks "); return -EINVAL; } reqctx->mode = mode; return s5p_aes_handle_req(dev, req); } static int s5p_aes_setkey(struct crypto_ablkcipher *cipher, const uint8_t *key, unsigned int keylen) { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); struct s5p_aes_ctx *ctx = crypto_tfm_ctx(tfm); if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && keylen != AES_KEYSIZE_256) return -EINVAL; memcpy(ctx->aes_key, key, keylen); ctx->keylen = keylen; return 0; } static int s5p_aes_ecb_encrypt(struct ablkcipher_request *req) { return s5p_aes_crypt(req, 0); } static int s5p_aes_ecb_decrypt(struct ablkcipher_request *req) { return s5p_aes_crypt(req, FLAGS_AES_DECRYPT); } static int s5p_aes_cbc_encrypt(struct ablkcipher_request *req) { return s5p_aes_crypt(req, FLAGS_AES_CBC); } static int s5p_aes_cbc_decrypt(struct ablkcipher_request *req) { return s5p_aes_crypt(req, FLAGS_AES_DECRYPT | FLAGS_AES_CBC); } static int s5p_aes_cra_init(struct crypto_tfm *tfm) { struct s5p_aes_ctx *ctx = crypto_tfm_ctx(tfm); ctx->dev = s5p_dev; tfm->crt_ablkcipher.reqsize = sizeof(struct s5p_aes_reqctx); return 0; } static struct crypto_alg algs[] = { { .cra_name = "ecb(aes)", .cra_driver_name = "ecb-aes-s5p", .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | |
d912bb767 crypto: Add CRYPT... |
570 571 |
CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, |
a49e490c7 crypto: s5p-sss -... |
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 |
.cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s5p_aes_ctx), .cra_alignmask = 0x0f, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, .cra_init = s5p_aes_cra_init, .cra_u.ablkcipher = { .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, .setkey = s5p_aes_setkey, .encrypt = s5p_aes_ecb_encrypt, .decrypt = s5p_aes_ecb_decrypt, } }, { .cra_name = "cbc(aes)", .cra_driver_name = "cbc-aes-s5p", .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | |
d912bb767 crypto: Add CRYPT... |
591 592 |
CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, |
a49e490c7 crypto: s5p-sss -... |
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 |
.cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s5p_aes_ctx), .cra_alignmask = 0x0f, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, .cra_init = s5p_aes_cra_init, .cra_u.ablkcipher = { .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, .ivsize = AES_BLOCK_SIZE, .setkey = s5p_aes_setkey, .encrypt = s5p_aes_cbc_encrypt, .decrypt = s5p_aes_cbc_decrypt, } }, }; static int s5p_aes_probe(struct platform_device *pdev) { int i, j, err = -ENODEV; struct s5p_aes_dev *pdata; struct device *dev = &pdev->dev; struct resource *res; |
892451071 crypto: s5p-sss -... |
616 |
struct samsung_aes_variant *variant; |
a49e490c7 crypto: s5p-sss -... |
617 618 619 |
if (s5p_dev) return -EEXIST; |
a49e490c7 crypto: s5p-sss -... |
620 621 622 |
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; |
0fdefe2c9 crypto: s5p-sss -... |
623 624 625 626 |
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(pdata->ioaddr)) return PTR_ERR(pdata->ioaddr); |
a49e490c7 crypto: s5p-sss -... |
627 |
|
892451071 crypto: s5p-sss -... |
628 |
variant = find_s5p_sss_version(pdev); |
5c22ba661 crypto: s5p-sss -... |
629 |
pdata->clk = devm_clk_get(dev, "secss"); |
a49e490c7 crypto: s5p-sss -... |
630 631 632 633 634 |
if (IS_ERR(pdata->clk)) { dev_err(dev, "failed to find secss clock source "); return -ENOENT; } |
c1eb7ef26 crypto: s5p-sss -... |
635 636 637 638 639 640 |
err = clk_prepare_enable(pdata->clk); if (err < 0) { dev_err(dev, "Enabling SSS clk failed, err %d ", err); return err; } |
a49e490c7 crypto: s5p-sss -... |
641 642 |
spin_lock_init(&pdata->lock); |
a49e490c7 crypto: s5p-sss -... |
643 |
|
892451071 crypto: s5p-sss -... |
644 |
pdata->aes_ioaddr = pdata->ioaddr + variant->aes_offset; |
96fc70b63 crypto: s5p-sss -... |
645 646 647 648 649 |
pdata->irq_fc = platform_get_irq(pdev, 0); if (pdata->irq_fc < 0) { err = pdata->irq_fc; dev_warn(dev, "feed control interrupt is not available. "); |
a49e490c7 crypto: s5p-sss -... |
650 651 |
goto err_irq; } |
96fc70b63 crypto: s5p-sss -... |
652 |
err = devm_request_irq(dev, pdata->irq_fc, s5p_aes_interrupt, |
a49e490c7 crypto: s5p-sss -... |
653 654 |
IRQF_SHARED, pdev->name, pdev); if (err < 0) { |
96fc70b63 crypto: s5p-sss -... |
655 656 |
dev_warn(dev, "feed control interrupt is not available. "); |
a49e490c7 crypto: s5p-sss -... |
657 658 |
goto err_irq; } |
892451071 crypto: s5p-sss -... |
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 |
if (variant->has_hash_irq) { pdata->irq_hash = platform_get_irq(pdev, 1); if (pdata->irq_hash < 0) { err = pdata->irq_hash; dev_warn(dev, "hash interrupt is not available. "); goto err_irq; } err = devm_request_irq(dev, pdata->irq_hash, s5p_aes_interrupt, IRQF_SHARED, pdev->name, pdev); if (err < 0) { dev_warn(dev, "hash interrupt is not available. "); goto err_irq; } |
a49e490c7 crypto: s5p-sss -... |
674 |
} |
dc5e3f195 crypto: s5p-sss -... |
675 |
pdata->busy = false; |
892451071 crypto: s5p-sss -... |
676 |
pdata->variant = variant; |
a49e490c7 crypto: s5p-sss -... |
677 678 679 680 681 682 683 684 |
pdata->dev = dev; platform_set_drvdata(pdev, pdata); s5p_dev = pdata; tasklet_init(&pdata->tasklet, s5p_tasklet_cb, (unsigned long)pdata); crypto_init_queue(&pdata->queue, CRYPTO_QUEUE_LEN); for (i = 0; i < ARRAY_SIZE(algs); i++) { |
a49e490c7 crypto: s5p-sss -... |
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 |
err = crypto_register_alg(&algs[i]); if (err) goto err_algs; } pr_info("s5p-sss driver registered "); return 0; err_algs: dev_err(dev, "can't register '%s': %d ", algs[i].cra_name, err); for (j = 0; j < i; j++) crypto_unregister_alg(&algs[j]); tasklet_kill(&pdata->tasklet); err_irq: |
c1eb7ef26 crypto: s5p-sss -... |
705 |
clk_disable_unprepare(pdata->clk); |
a49e490c7 crypto: s5p-sss -... |
706 707 |
s5p_dev = NULL; |
a49e490c7 crypto: s5p-sss -... |
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 |
return err; } static int s5p_aes_remove(struct platform_device *pdev) { struct s5p_aes_dev *pdata = platform_get_drvdata(pdev); int i; if (!pdata) return -ENODEV; for (i = 0; i < ARRAY_SIZE(algs); i++) crypto_unregister_alg(&algs[i]); tasklet_kill(&pdata->tasklet); |
c1eb7ef26 crypto: s5p-sss -... |
724 |
clk_disable_unprepare(pdata->clk); |
a49e490c7 crypto: s5p-sss -... |
725 726 |
s5p_dev = NULL; |
a49e490c7 crypto: s5p-sss -... |
727 728 729 730 731 732 733 734 |
return 0; } static struct platform_driver s5p_aes_crypto = { .probe = s5p_aes_probe, .remove = s5p_aes_remove, .driver = { |
a49e490c7 crypto: s5p-sss -... |
735 |
.name = "s5p-secss", |
6b9f16e6c crypto: s5p-sss -... |
736 |
.of_match_table = s5p_sss_dt_match, |
a49e490c7 crypto: s5p-sss -... |
737 738 |
}, }; |
741e8c2d8 crypto: convert d... |
739 |
module_platform_driver(s5p_aes_crypto); |
a49e490c7 crypto: s5p-sss -... |
740 741 742 743 |
MODULE_DESCRIPTION("S5PV210 AES hw acceleration support."); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Vladimir Zapolskiy <vzapolskiy@gmail.com>"); |