0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) "%s: " fmt, __func__
0010
0011 #ifdef DEBUG
0012 #define prn(num) printk(#num "=%d\n", num)
0013 #define prx(num) printk(#num "=%x\n", num)
0014 #else
0015 #define prn(num) do { } while (0)
0016 #define prx(num) do { } while (0)
0017 #endif
0018
0019 #include <linux/err.h>
0020 #include <linux/module.h>
0021 #include <linux/init.h>
0022 #include <linux/errno.h>
0023 #include <linux/kernel.h>
0024 #include <linux/platform_device.h>
0025 #include <linux/scatterlist.h>
0026 #include <linux/dma-mapping.h>
0027 #include <linux/dmaengine.h>
0028 #include <linux/pm_runtime.h>
0029 #include <linux/of.h>
0030 #include <linux/of_device.h>
0031 #include <linux/of_address.h>
0032 #include <linux/io.h>
0033 #include <linux/crypto.h>
0034 #include <linux/interrupt.h>
0035 #include <crypto/scatterwalk.h>
0036 #include <crypto/internal/des.h>
0037 #include <crypto/internal/skcipher.h>
0038 #include <crypto/algapi.h>
0039 #include <crypto/engine.h>
0040
0041 #include "omap-crypto.h"
0042
0043 #define DST_MAXBURST 2
0044
0045 #define DES_BLOCK_WORDS (DES_BLOCK_SIZE >> 2)
0046
0047 #define _calc_walked(inout) (dd->inout##_walk.offset - dd->inout##_sg->offset)
0048
0049 #define DES_REG_KEY(dd, x) ((dd)->pdata->key_ofs - \
0050 ((x ^ 0x01) * 0x04))
0051
0052 #define DES_REG_IV(dd, x) ((dd)->pdata->iv_ofs + ((x) * 0x04))
0053
0054 #define DES_REG_CTRL(dd) ((dd)->pdata->ctrl_ofs)
0055 #define DES_REG_CTRL_CBC BIT(4)
0056 #define DES_REG_CTRL_TDES BIT(3)
0057 #define DES_REG_CTRL_DIRECTION BIT(2)
0058 #define DES_REG_CTRL_INPUT_READY BIT(1)
0059 #define DES_REG_CTRL_OUTPUT_READY BIT(0)
0060
0061 #define DES_REG_DATA_N(dd, x) ((dd)->pdata->data_ofs + ((x) * 0x04))
0062
0063 #define DES_REG_REV(dd) ((dd)->pdata->rev_ofs)
0064
0065 #define DES_REG_MASK(dd) ((dd)->pdata->mask_ofs)
0066
0067 #define DES_REG_LENGTH_N(x) (0x24 + ((x) * 0x04))
0068
0069 #define DES_REG_IRQ_STATUS(dd) ((dd)->pdata->irq_status_ofs)
0070 #define DES_REG_IRQ_ENABLE(dd) ((dd)->pdata->irq_enable_ofs)
0071 #define DES_REG_IRQ_DATA_IN BIT(1)
0072 #define DES_REG_IRQ_DATA_OUT BIT(2)
0073
0074 #define FLAGS_MODE_MASK 0x000f
0075 #define FLAGS_ENCRYPT BIT(0)
0076 #define FLAGS_CBC BIT(1)
0077 #define FLAGS_INIT BIT(4)
0078 #define FLAGS_BUSY BIT(6)
0079
0080 #define DEFAULT_AUTOSUSPEND_DELAY 1000
0081
0082 #define FLAGS_IN_DATA_ST_SHIFT 8
0083 #define FLAGS_OUT_DATA_ST_SHIFT 10
0084
0085 struct omap_des_ctx {
0086 struct crypto_engine_ctx enginectx;
0087 struct omap_des_dev *dd;
0088
0089 int keylen;
0090 __le32 key[(3 * DES_KEY_SIZE) / sizeof(u32)];
0091 unsigned long flags;
0092 };
0093
0094 struct omap_des_reqctx {
0095 unsigned long mode;
0096 };
0097
0098 #define OMAP_DES_QUEUE_LENGTH 1
0099 #define OMAP_DES_CACHE_SIZE 0
0100
0101 struct omap_des_algs_info {
0102 struct skcipher_alg *algs_list;
0103 unsigned int size;
0104 unsigned int registered;
0105 };
0106
0107 struct omap_des_pdata {
0108 struct omap_des_algs_info *algs_info;
0109 unsigned int algs_info_size;
0110
0111 void (*trigger)(struct omap_des_dev *dd, int length);
0112
0113 u32 key_ofs;
0114 u32 iv_ofs;
0115 u32 ctrl_ofs;
0116 u32 data_ofs;
0117 u32 rev_ofs;
0118 u32 mask_ofs;
0119 u32 irq_enable_ofs;
0120 u32 irq_status_ofs;
0121
0122 u32 dma_enable_in;
0123 u32 dma_enable_out;
0124 u32 dma_start;
0125
0126 u32 major_mask;
0127 u32 major_shift;
0128 u32 minor_mask;
0129 u32 minor_shift;
0130 };
0131
0132 struct omap_des_dev {
0133 struct list_head list;
0134 unsigned long phys_base;
0135 void __iomem *io_base;
0136 struct omap_des_ctx *ctx;
0137 struct device *dev;
0138 unsigned long flags;
0139 int err;
0140
0141 struct tasklet_struct done_task;
0142
0143 struct skcipher_request *req;
0144 struct crypto_engine *engine;
0145
0146
0147
0148
0149 size_t total;
0150 size_t total_save;
0151
0152 struct scatterlist *in_sg;
0153 struct scatterlist *out_sg;
0154
0155
0156 struct scatterlist in_sgl;
0157 struct scatterlist out_sgl;
0158 struct scatterlist *orig_out;
0159
0160 struct scatter_walk in_walk;
0161 struct scatter_walk out_walk;
0162 struct dma_chan *dma_lch_in;
0163 struct dma_chan *dma_lch_out;
0164 int in_sg_len;
0165 int out_sg_len;
0166 int pio_only;
0167 const struct omap_des_pdata *pdata;
0168 };
0169
0170
0171 static LIST_HEAD(dev_list);
0172 static DEFINE_SPINLOCK(list_lock);
0173
0174 #ifdef DEBUG
0175 #define omap_des_read(dd, offset) \
0176 ({ \
0177 int _read_ret; \
0178 _read_ret = __raw_readl(dd->io_base + offset); \
0179 pr_err("omap_des_read(" #offset "=%#x)= %#x\n", \
0180 offset, _read_ret); \
0181 _read_ret; \
0182 })
0183 #else
0184 static inline u32 omap_des_read(struct omap_des_dev *dd, u32 offset)
0185 {
0186 return __raw_readl(dd->io_base + offset);
0187 }
0188 #endif
0189
0190 #ifdef DEBUG
0191 #define omap_des_write(dd, offset, value) \
0192 do { \
0193 pr_err("omap_des_write(" #offset "=%#x) value=%#x\n", \
0194 offset, value); \
0195 __raw_writel(value, dd->io_base + offset); \
0196 } while (0)
0197 #else
0198 static inline void omap_des_write(struct omap_des_dev *dd, u32 offset,
0199 u32 value)
0200 {
0201 __raw_writel(value, dd->io_base + offset);
0202 }
0203 #endif
0204
0205 static inline void omap_des_write_mask(struct omap_des_dev *dd, u32 offset,
0206 u32 value, u32 mask)
0207 {
0208 u32 val;
0209
0210 val = omap_des_read(dd, offset);
0211 val &= ~mask;
0212 val |= value;
0213 omap_des_write(dd, offset, val);
0214 }
0215
0216 static void omap_des_write_n(struct omap_des_dev *dd, u32 offset,
0217 u32 *value, int count)
0218 {
0219 for (; count--; value++, offset += 4)
0220 omap_des_write(dd, offset, *value);
0221 }
0222
0223 static int omap_des_hw_init(struct omap_des_dev *dd)
0224 {
0225 int err;
0226
0227
0228
0229
0230
0231
0232 err = pm_runtime_resume_and_get(dd->dev);
0233 if (err < 0) {
0234 dev_err(dd->dev, "%s: failed to get_sync(%d)\n", __func__, err);
0235 return err;
0236 }
0237
0238 if (!(dd->flags & FLAGS_INIT)) {
0239 dd->flags |= FLAGS_INIT;
0240 dd->err = 0;
0241 }
0242
0243 return 0;
0244 }
0245
0246 static int omap_des_write_ctrl(struct omap_des_dev *dd)
0247 {
0248 unsigned int key32;
0249 int i, err;
0250 u32 val = 0, mask = 0;
0251
0252 err = omap_des_hw_init(dd);
0253 if (err)
0254 return err;
0255
0256 key32 = dd->ctx->keylen / sizeof(u32);
0257
0258
0259 for (i = 0; i < key32; i++) {
0260 omap_des_write(dd, DES_REG_KEY(dd, i),
0261 __le32_to_cpu(dd->ctx->key[i]));
0262 }
0263
0264 if ((dd->flags & FLAGS_CBC) && dd->req->iv)
0265 omap_des_write_n(dd, DES_REG_IV(dd, 0), (void *)dd->req->iv, 2);
0266
0267 if (dd->flags & FLAGS_CBC)
0268 val |= DES_REG_CTRL_CBC;
0269 if (dd->flags & FLAGS_ENCRYPT)
0270 val |= DES_REG_CTRL_DIRECTION;
0271 if (key32 == 6)
0272 val |= DES_REG_CTRL_TDES;
0273
0274 mask |= DES_REG_CTRL_CBC | DES_REG_CTRL_DIRECTION | DES_REG_CTRL_TDES;
0275
0276 omap_des_write_mask(dd, DES_REG_CTRL(dd), val, mask);
0277
0278 return 0;
0279 }
0280
0281 static void omap_des_dma_trigger_omap4(struct omap_des_dev *dd, int length)
0282 {
0283 u32 mask, val;
0284
0285 omap_des_write(dd, DES_REG_LENGTH_N(0), length);
0286
0287 val = dd->pdata->dma_start;
0288
0289 if (dd->dma_lch_out != NULL)
0290 val |= dd->pdata->dma_enable_out;
0291 if (dd->dma_lch_in != NULL)
0292 val |= dd->pdata->dma_enable_in;
0293
0294 mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
0295 dd->pdata->dma_start;
0296
0297 omap_des_write_mask(dd, DES_REG_MASK(dd), val, mask);
0298 }
0299
0300 static void omap_des_dma_stop(struct omap_des_dev *dd)
0301 {
0302 u32 mask;
0303
0304 mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
0305 dd->pdata->dma_start;
0306
0307 omap_des_write_mask(dd, DES_REG_MASK(dd), 0, mask);
0308 }
0309
0310 static struct omap_des_dev *omap_des_find_dev(struct omap_des_ctx *ctx)
0311 {
0312 struct omap_des_dev *dd = NULL, *tmp;
0313
0314 spin_lock_bh(&list_lock);
0315 if (!ctx->dd) {
0316 list_for_each_entry(tmp, &dev_list, list) {
0317
0318 dd = tmp;
0319 break;
0320 }
0321 ctx->dd = dd;
0322 } else {
0323
0324 dd = ctx->dd;
0325 }
0326 spin_unlock_bh(&list_lock);
0327
0328 return dd;
0329 }
0330
0331 static void omap_des_dma_out_callback(void *data)
0332 {
0333 struct omap_des_dev *dd = data;
0334
0335
0336 tasklet_schedule(&dd->done_task);
0337 }
0338
0339 static int omap_des_dma_init(struct omap_des_dev *dd)
0340 {
0341 int err;
0342
0343 dd->dma_lch_out = NULL;
0344 dd->dma_lch_in = NULL;
0345
0346 dd->dma_lch_in = dma_request_chan(dd->dev, "rx");
0347 if (IS_ERR(dd->dma_lch_in)) {
0348 dev_err(dd->dev, "Unable to request in DMA channel\n");
0349 return PTR_ERR(dd->dma_lch_in);
0350 }
0351
0352 dd->dma_lch_out = dma_request_chan(dd->dev, "tx");
0353 if (IS_ERR(dd->dma_lch_out)) {
0354 dev_err(dd->dev, "Unable to request out DMA channel\n");
0355 err = PTR_ERR(dd->dma_lch_out);
0356 goto err_dma_out;
0357 }
0358
0359 return 0;
0360
0361 err_dma_out:
0362 dma_release_channel(dd->dma_lch_in);
0363
0364 return err;
0365 }
0366
0367 static void omap_des_dma_cleanup(struct omap_des_dev *dd)
0368 {
0369 if (dd->pio_only)
0370 return;
0371
0372 dma_release_channel(dd->dma_lch_out);
0373 dma_release_channel(dd->dma_lch_in);
0374 }
0375
0376 static int omap_des_crypt_dma(struct crypto_tfm *tfm,
0377 struct scatterlist *in_sg, struct scatterlist *out_sg,
0378 int in_sg_len, int out_sg_len)
0379 {
0380 struct omap_des_ctx *ctx = crypto_tfm_ctx(tfm);
0381 struct omap_des_dev *dd = ctx->dd;
0382 struct dma_async_tx_descriptor *tx_in, *tx_out;
0383 struct dma_slave_config cfg;
0384 int ret;
0385
0386 if (dd->pio_only) {
0387 scatterwalk_start(&dd->in_walk, dd->in_sg);
0388 scatterwalk_start(&dd->out_walk, dd->out_sg);
0389
0390
0391
0392 omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x2);
0393 return 0;
0394 }
0395
0396 dma_sync_sg_for_device(dd->dev, dd->in_sg, in_sg_len, DMA_TO_DEVICE);
0397
0398 memset(&cfg, 0, sizeof(cfg));
0399
0400 cfg.src_addr = dd->phys_base + DES_REG_DATA_N(dd, 0);
0401 cfg.dst_addr = dd->phys_base + DES_REG_DATA_N(dd, 0);
0402 cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
0403 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
0404 cfg.src_maxburst = DST_MAXBURST;
0405 cfg.dst_maxburst = DST_MAXBURST;
0406
0407
0408 ret = dmaengine_slave_config(dd->dma_lch_in, &cfg);
0409 if (ret) {
0410 dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n",
0411 ret);
0412 return ret;
0413 }
0414
0415 tx_in = dmaengine_prep_slave_sg(dd->dma_lch_in, in_sg, in_sg_len,
0416 DMA_MEM_TO_DEV,
0417 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
0418 if (!tx_in) {
0419 dev_err(dd->dev, "IN prep_slave_sg() failed\n");
0420 return -EINVAL;
0421 }
0422
0423
0424 tx_in->callback_param = dd;
0425
0426
0427 ret = dmaengine_slave_config(dd->dma_lch_out, &cfg);
0428 if (ret) {
0429 dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n",
0430 ret);
0431 return ret;
0432 }
0433
0434 tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, out_sg_len,
0435 DMA_DEV_TO_MEM,
0436 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
0437 if (!tx_out) {
0438 dev_err(dd->dev, "OUT prep_slave_sg() failed\n");
0439 return -EINVAL;
0440 }
0441
0442 tx_out->callback = omap_des_dma_out_callback;
0443 tx_out->callback_param = dd;
0444
0445 dmaengine_submit(tx_in);
0446 dmaengine_submit(tx_out);
0447
0448 dma_async_issue_pending(dd->dma_lch_in);
0449 dma_async_issue_pending(dd->dma_lch_out);
0450
0451
0452 dd->pdata->trigger(dd, dd->total);
0453
0454 return 0;
0455 }
0456
0457 static int omap_des_crypt_dma_start(struct omap_des_dev *dd)
0458 {
0459 struct crypto_tfm *tfm = crypto_skcipher_tfm(
0460 crypto_skcipher_reqtfm(dd->req));
0461 int err;
0462
0463 pr_debug("total: %zd\n", dd->total);
0464
0465 if (!dd->pio_only) {
0466 err = dma_map_sg(dd->dev, dd->in_sg, dd->in_sg_len,
0467 DMA_TO_DEVICE);
0468 if (!err) {
0469 dev_err(dd->dev, "dma_map_sg() error\n");
0470 return -EINVAL;
0471 }
0472
0473 err = dma_map_sg(dd->dev, dd->out_sg, dd->out_sg_len,
0474 DMA_FROM_DEVICE);
0475 if (!err) {
0476 dev_err(dd->dev, "dma_map_sg() error\n");
0477 return -EINVAL;
0478 }
0479 }
0480
0481 err = omap_des_crypt_dma(tfm, dd->in_sg, dd->out_sg, dd->in_sg_len,
0482 dd->out_sg_len);
0483 if (err && !dd->pio_only) {
0484 dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
0485 dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len,
0486 DMA_FROM_DEVICE);
0487 }
0488
0489 return err;
0490 }
0491
0492 static void omap_des_finish_req(struct omap_des_dev *dd, int err)
0493 {
0494 struct skcipher_request *req = dd->req;
0495
0496 pr_debug("err: %d\n", err);
0497
0498 crypto_finalize_skcipher_request(dd->engine, req, err);
0499
0500 pm_runtime_mark_last_busy(dd->dev);
0501 pm_runtime_put_autosuspend(dd->dev);
0502 }
0503
0504 static int omap_des_crypt_dma_stop(struct omap_des_dev *dd)
0505 {
0506 pr_debug("total: %zd\n", dd->total);
0507
0508 omap_des_dma_stop(dd);
0509
0510 dmaengine_terminate_all(dd->dma_lch_in);
0511 dmaengine_terminate_all(dd->dma_lch_out);
0512
0513 return 0;
0514 }
0515
0516 static int omap_des_handle_queue(struct omap_des_dev *dd,
0517 struct skcipher_request *req)
0518 {
0519 if (req)
0520 return crypto_transfer_skcipher_request_to_engine(dd->engine, req);
0521
0522 return 0;
0523 }
0524
0525 static int omap_des_prepare_req(struct crypto_engine *engine,
0526 void *areq)
0527 {
0528 struct skcipher_request *req = container_of(areq, struct skcipher_request, base);
0529 struct omap_des_ctx *ctx = crypto_skcipher_ctx(
0530 crypto_skcipher_reqtfm(req));
0531 struct omap_des_dev *dd = omap_des_find_dev(ctx);
0532 struct omap_des_reqctx *rctx;
0533 int ret;
0534 u16 flags;
0535
0536 if (!dd)
0537 return -ENODEV;
0538
0539
0540 dd->req = req;
0541 dd->total = req->cryptlen;
0542 dd->total_save = req->cryptlen;
0543 dd->in_sg = req->src;
0544 dd->out_sg = req->dst;
0545 dd->orig_out = req->dst;
0546
0547 flags = OMAP_CRYPTO_COPY_DATA;
0548 if (req->src == req->dst)
0549 flags |= OMAP_CRYPTO_FORCE_COPY;
0550
0551 ret = omap_crypto_align_sg(&dd->in_sg, dd->total, DES_BLOCK_SIZE,
0552 &dd->in_sgl, flags,
0553 FLAGS_IN_DATA_ST_SHIFT, &dd->flags);
0554 if (ret)
0555 return ret;
0556
0557 ret = omap_crypto_align_sg(&dd->out_sg, dd->total, DES_BLOCK_SIZE,
0558 &dd->out_sgl, 0,
0559 FLAGS_OUT_DATA_ST_SHIFT, &dd->flags);
0560 if (ret)
0561 return ret;
0562
0563 dd->in_sg_len = sg_nents_for_len(dd->in_sg, dd->total);
0564 if (dd->in_sg_len < 0)
0565 return dd->in_sg_len;
0566
0567 dd->out_sg_len = sg_nents_for_len(dd->out_sg, dd->total);
0568 if (dd->out_sg_len < 0)
0569 return dd->out_sg_len;
0570
0571 rctx = skcipher_request_ctx(req);
0572 ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
0573 rctx->mode &= FLAGS_MODE_MASK;
0574 dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode;
0575
0576 dd->ctx = ctx;
0577 ctx->dd = dd;
0578
0579 return omap_des_write_ctrl(dd);
0580 }
0581
0582 static int omap_des_crypt_req(struct crypto_engine *engine,
0583 void *areq)
0584 {
0585 struct skcipher_request *req = container_of(areq, struct skcipher_request, base);
0586 struct omap_des_ctx *ctx = crypto_skcipher_ctx(
0587 crypto_skcipher_reqtfm(req));
0588 struct omap_des_dev *dd = omap_des_find_dev(ctx);
0589
0590 if (!dd)
0591 return -ENODEV;
0592
0593 return omap_des_crypt_dma_start(dd);
0594 }
0595
0596 static void omap_des_done_task(unsigned long data)
0597 {
0598 struct omap_des_dev *dd = (struct omap_des_dev *)data;
0599 int i;
0600
0601 pr_debug("enter done_task\n");
0602
0603 if (!dd->pio_only) {
0604 dma_sync_sg_for_device(dd->dev, dd->out_sg, dd->out_sg_len,
0605 DMA_FROM_DEVICE);
0606 dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
0607 dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len,
0608 DMA_FROM_DEVICE);
0609 omap_des_crypt_dma_stop(dd);
0610 }
0611
0612 omap_crypto_cleanup(&dd->in_sgl, NULL, 0, dd->total_save,
0613 FLAGS_IN_DATA_ST_SHIFT, dd->flags);
0614
0615 omap_crypto_cleanup(&dd->out_sgl, dd->orig_out, 0, dd->total_save,
0616 FLAGS_OUT_DATA_ST_SHIFT, dd->flags);
0617
0618 if ((dd->flags & FLAGS_CBC) && dd->req->iv)
0619 for (i = 0; i < 2; i++)
0620 ((u32 *)dd->req->iv)[i] =
0621 omap_des_read(dd, DES_REG_IV(dd, i));
0622
0623 omap_des_finish_req(dd, 0);
0624
0625 pr_debug("exit\n");
0626 }
0627
0628 static int omap_des_crypt(struct skcipher_request *req, unsigned long mode)
0629 {
0630 struct omap_des_ctx *ctx = crypto_skcipher_ctx(
0631 crypto_skcipher_reqtfm(req));
0632 struct omap_des_reqctx *rctx = skcipher_request_ctx(req);
0633 struct omap_des_dev *dd;
0634
0635 pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->cryptlen,
0636 !!(mode & FLAGS_ENCRYPT),
0637 !!(mode & FLAGS_CBC));
0638
0639 if (!req->cryptlen)
0640 return 0;
0641
0642 if (!IS_ALIGNED(req->cryptlen, DES_BLOCK_SIZE))
0643 return -EINVAL;
0644
0645 dd = omap_des_find_dev(ctx);
0646 if (!dd)
0647 return -ENODEV;
0648
0649 rctx->mode = mode;
0650
0651 return omap_des_handle_queue(dd, req);
0652 }
0653
0654
0655
0656 static int omap_des_setkey(struct crypto_skcipher *cipher, const u8 *key,
0657 unsigned int keylen)
0658 {
0659 struct omap_des_ctx *ctx = crypto_skcipher_ctx(cipher);
0660 int err;
0661
0662 pr_debug("enter, keylen: %d\n", keylen);
0663
0664 err = verify_skcipher_des_key(cipher, key);
0665 if (err)
0666 return err;
0667
0668 memcpy(ctx->key, key, keylen);
0669 ctx->keylen = keylen;
0670
0671 return 0;
0672 }
0673
0674 static int omap_des3_setkey(struct crypto_skcipher *cipher, const u8 *key,
0675 unsigned int keylen)
0676 {
0677 struct omap_des_ctx *ctx = crypto_skcipher_ctx(cipher);
0678 int err;
0679
0680 pr_debug("enter, keylen: %d\n", keylen);
0681
0682 err = verify_skcipher_des3_key(cipher, key);
0683 if (err)
0684 return err;
0685
0686 memcpy(ctx->key, key, keylen);
0687 ctx->keylen = keylen;
0688
0689 return 0;
0690 }
0691
0692 static int omap_des_ecb_encrypt(struct skcipher_request *req)
0693 {
0694 return omap_des_crypt(req, FLAGS_ENCRYPT);
0695 }
0696
0697 static int omap_des_ecb_decrypt(struct skcipher_request *req)
0698 {
0699 return omap_des_crypt(req, 0);
0700 }
0701
0702 static int omap_des_cbc_encrypt(struct skcipher_request *req)
0703 {
0704 return omap_des_crypt(req, FLAGS_ENCRYPT | FLAGS_CBC);
0705 }
0706
0707 static int omap_des_cbc_decrypt(struct skcipher_request *req)
0708 {
0709 return omap_des_crypt(req, FLAGS_CBC);
0710 }
0711
0712 static int omap_des_prepare_req(struct crypto_engine *engine,
0713 void *areq);
0714 static int omap_des_crypt_req(struct crypto_engine *engine,
0715 void *areq);
0716
0717 static int omap_des_init_tfm(struct crypto_skcipher *tfm)
0718 {
0719 struct omap_des_ctx *ctx = crypto_skcipher_ctx(tfm);
0720
0721 pr_debug("enter\n");
0722
0723 crypto_skcipher_set_reqsize(tfm, sizeof(struct omap_des_reqctx));
0724
0725 ctx->enginectx.op.prepare_request = omap_des_prepare_req;
0726 ctx->enginectx.op.unprepare_request = NULL;
0727 ctx->enginectx.op.do_one_request = omap_des_crypt_req;
0728
0729 return 0;
0730 }
0731
0732
0733
0734 static struct skcipher_alg algs_ecb_cbc[] = {
0735 {
0736 .base.cra_name = "ecb(des)",
0737 .base.cra_driver_name = "ecb-des-omap",
0738 .base.cra_priority = 300,
0739 .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |
0740 CRYPTO_ALG_ASYNC,
0741 .base.cra_blocksize = DES_BLOCK_SIZE,
0742 .base.cra_ctxsize = sizeof(struct omap_des_ctx),
0743 .base.cra_module = THIS_MODULE,
0744
0745 .min_keysize = DES_KEY_SIZE,
0746 .max_keysize = DES_KEY_SIZE,
0747 .setkey = omap_des_setkey,
0748 .encrypt = omap_des_ecb_encrypt,
0749 .decrypt = omap_des_ecb_decrypt,
0750 .init = omap_des_init_tfm,
0751 },
0752 {
0753 .base.cra_name = "cbc(des)",
0754 .base.cra_driver_name = "cbc-des-omap",
0755 .base.cra_priority = 300,
0756 .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |
0757 CRYPTO_ALG_ASYNC,
0758 .base.cra_blocksize = DES_BLOCK_SIZE,
0759 .base.cra_ctxsize = sizeof(struct omap_des_ctx),
0760 .base.cra_module = THIS_MODULE,
0761
0762 .min_keysize = DES_KEY_SIZE,
0763 .max_keysize = DES_KEY_SIZE,
0764 .ivsize = DES_BLOCK_SIZE,
0765 .setkey = omap_des_setkey,
0766 .encrypt = omap_des_cbc_encrypt,
0767 .decrypt = omap_des_cbc_decrypt,
0768 .init = omap_des_init_tfm,
0769 },
0770 {
0771 .base.cra_name = "ecb(des3_ede)",
0772 .base.cra_driver_name = "ecb-des3-omap",
0773 .base.cra_priority = 300,
0774 .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |
0775 CRYPTO_ALG_ASYNC,
0776 .base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
0777 .base.cra_ctxsize = sizeof(struct omap_des_ctx),
0778 .base.cra_module = THIS_MODULE,
0779
0780 .min_keysize = DES3_EDE_KEY_SIZE,
0781 .max_keysize = DES3_EDE_KEY_SIZE,
0782 .setkey = omap_des3_setkey,
0783 .encrypt = omap_des_ecb_encrypt,
0784 .decrypt = omap_des_ecb_decrypt,
0785 .init = omap_des_init_tfm,
0786 },
0787 {
0788 .base.cra_name = "cbc(des3_ede)",
0789 .base.cra_driver_name = "cbc-des3-omap",
0790 .base.cra_priority = 300,
0791 .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |
0792 CRYPTO_ALG_ASYNC,
0793 .base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
0794 .base.cra_ctxsize = sizeof(struct omap_des_ctx),
0795 .base.cra_module = THIS_MODULE,
0796
0797 .min_keysize = DES3_EDE_KEY_SIZE,
0798 .max_keysize = DES3_EDE_KEY_SIZE,
0799 .ivsize = DES3_EDE_BLOCK_SIZE,
0800 .setkey = omap_des3_setkey,
0801 .encrypt = omap_des_cbc_encrypt,
0802 .decrypt = omap_des_cbc_decrypt,
0803 .init = omap_des_init_tfm,
0804 }
0805 };
0806
0807 static struct omap_des_algs_info omap_des_algs_info_ecb_cbc[] = {
0808 {
0809 .algs_list = algs_ecb_cbc,
0810 .size = ARRAY_SIZE(algs_ecb_cbc),
0811 },
0812 };
0813
0814 #ifdef CONFIG_OF
0815 static const struct omap_des_pdata omap_des_pdata_omap4 = {
0816 .algs_info = omap_des_algs_info_ecb_cbc,
0817 .algs_info_size = ARRAY_SIZE(omap_des_algs_info_ecb_cbc),
0818 .trigger = omap_des_dma_trigger_omap4,
0819 .key_ofs = 0x14,
0820 .iv_ofs = 0x18,
0821 .ctrl_ofs = 0x20,
0822 .data_ofs = 0x28,
0823 .rev_ofs = 0x30,
0824 .mask_ofs = 0x34,
0825 .irq_status_ofs = 0x3c,
0826 .irq_enable_ofs = 0x40,
0827 .dma_enable_in = BIT(5),
0828 .dma_enable_out = BIT(6),
0829 .major_mask = 0x0700,
0830 .major_shift = 8,
0831 .minor_mask = 0x003f,
0832 .minor_shift = 0,
0833 };
0834
0835 static irqreturn_t omap_des_irq(int irq, void *dev_id)
0836 {
0837 struct omap_des_dev *dd = dev_id;
0838 u32 status, i;
0839 u32 *src, *dst;
0840
0841 status = omap_des_read(dd, DES_REG_IRQ_STATUS(dd));
0842 if (status & DES_REG_IRQ_DATA_IN) {
0843 omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x0);
0844
0845 BUG_ON(!dd->in_sg);
0846
0847 BUG_ON(_calc_walked(in) > dd->in_sg->length);
0848
0849 src = sg_virt(dd->in_sg) + _calc_walked(in);
0850
0851 for (i = 0; i < DES_BLOCK_WORDS; i++) {
0852 omap_des_write(dd, DES_REG_DATA_N(dd, i), *src);
0853
0854 scatterwalk_advance(&dd->in_walk, 4);
0855 if (dd->in_sg->length == _calc_walked(in)) {
0856 dd->in_sg = sg_next(dd->in_sg);
0857 if (dd->in_sg) {
0858 scatterwalk_start(&dd->in_walk,
0859 dd->in_sg);
0860 src = sg_virt(dd->in_sg) +
0861 _calc_walked(in);
0862 }
0863 } else {
0864 src++;
0865 }
0866 }
0867
0868
0869 status &= ~DES_REG_IRQ_DATA_IN;
0870 omap_des_write(dd, DES_REG_IRQ_STATUS(dd), status);
0871
0872
0873 omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x4);
0874
0875 } else if (status & DES_REG_IRQ_DATA_OUT) {
0876 omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x0);
0877
0878 BUG_ON(!dd->out_sg);
0879
0880 BUG_ON(_calc_walked(out) > dd->out_sg->length);
0881
0882 dst = sg_virt(dd->out_sg) + _calc_walked(out);
0883
0884 for (i = 0; i < DES_BLOCK_WORDS; i++) {
0885 *dst = omap_des_read(dd, DES_REG_DATA_N(dd, i));
0886 scatterwalk_advance(&dd->out_walk, 4);
0887 if (dd->out_sg->length == _calc_walked(out)) {
0888 dd->out_sg = sg_next(dd->out_sg);
0889 if (dd->out_sg) {
0890 scatterwalk_start(&dd->out_walk,
0891 dd->out_sg);
0892 dst = sg_virt(dd->out_sg) +
0893 _calc_walked(out);
0894 }
0895 } else {
0896 dst++;
0897 }
0898 }
0899
0900 BUG_ON(dd->total < DES_BLOCK_SIZE);
0901
0902 dd->total -= DES_BLOCK_SIZE;
0903
0904
0905 status &= ~DES_REG_IRQ_DATA_OUT;
0906 omap_des_write(dd, DES_REG_IRQ_STATUS(dd), status);
0907
0908 if (!dd->total)
0909
0910 tasklet_schedule(&dd->done_task);
0911 else
0912
0913 omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x2);
0914 }
0915
0916 return IRQ_HANDLED;
0917 }
0918
0919 static const struct of_device_id omap_des_of_match[] = {
0920 {
0921 .compatible = "ti,omap4-des",
0922 .data = &omap_des_pdata_omap4,
0923 },
0924 {},
0925 };
0926 MODULE_DEVICE_TABLE(of, omap_des_of_match);
0927
0928 static int omap_des_get_of(struct omap_des_dev *dd,
0929 struct platform_device *pdev)
0930 {
0931
0932 dd->pdata = of_device_get_match_data(&pdev->dev);
0933 if (!dd->pdata) {
0934 dev_err(&pdev->dev, "no compatible OF match\n");
0935 return -EINVAL;
0936 }
0937
0938 return 0;
0939 }
0940 #else
0941 static int omap_des_get_of(struct omap_des_dev *dd,
0942 struct device *dev)
0943 {
0944 return -EINVAL;
0945 }
0946 #endif
0947
0948 static int omap_des_get_pdev(struct omap_des_dev *dd,
0949 struct platform_device *pdev)
0950 {
0951
0952 dd->pdata = pdev->dev.platform_data;
0953
0954 return 0;
0955 }
0956
0957 static int omap_des_probe(struct platform_device *pdev)
0958 {
0959 struct device *dev = &pdev->dev;
0960 struct omap_des_dev *dd;
0961 struct skcipher_alg *algp;
0962 struct resource *res;
0963 int err = -ENOMEM, i, j, irq = -1;
0964 u32 reg;
0965
0966 dd = devm_kzalloc(dev, sizeof(struct omap_des_dev), GFP_KERNEL);
0967 if (dd == NULL) {
0968 dev_err(dev, "unable to alloc data struct.\n");
0969 goto err_data;
0970 }
0971 dd->dev = dev;
0972 platform_set_drvdata(pdev, dd);
0973
0974 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0975 if (!res) {
0976 dev_err(dev, "no MEM resource info\n");
0977 goto err_res;
0978 }
0979
0980 err = (dev->of_node) ? omap_des_get_of(dd, pdev) :
0981 omap_des_get_pdev(dd, pdev);
0982 if (err)
0983 goto err_res;
0984
0985 dd->io_base = devm_ioremap_resource(dev, res);
0986 if (IS_ERR(dd->io_base)) {
0987 err = PTR_ERR(dd->io_base);
0988 goto err_res;
0989 }
0990 dd->phys_base = res->start;
0991
0992 pm_runtime_use_autosuspend(dev);
0993 pm_runtime_set_autosuspend_delay(dev, DEFAULT_AUTOSUSPEND_DELAY);
0994
0995 pm_runtime_enable(dev);
0996 err = pm_runtime_resume_and_get(dev);
0997 if (err < 0) {
0998 dev_err(dd->dev, "%s: failed to get_sync(%d)\n", __func__, err);
0999 goto err_get;
1000 }
1001
1002 omap_des_dma_stop(dd);
1003
1004 reg = omap_des_read(dd, DES_REG_REV(dd));
1005
1006 pm_runtime_put_sync(dev);
1007
1008 dev_info(dev, "OMAP DES hw accel rev: %u.%u\n",
1009 (reg & dd->pdata->major_mask) >> dd->pdata->major_shift,
1010 (reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
1011
1012 tasklet_init(&dd->done_task, omap_des_done_task, (unsigned long)dd);
1013
1014 err = omap_des_dma_init(dd);
1015 if (err == -EPROBE_DEFER) {
1016 goto err_irq;
1017 } else if (err && DES_REG_IRQ_STATUS(dd) && DES_REG_IRQ_ENABLE(dd)) {
1018 dd->pio_only = 1;
1019
1020 irq = platform_get_irq(pdev, 0);
1021 if (irq < 0) {
1022 err = irq;
1023 goto err_irq;
1024 }
1025
1026 err = devm_request_irq(dev, irq, omap_des_irq, 0,
1027 dev_name(dev), dd);
1028 if (err) {
1029 dev_err(dev, "Unable to grab omap-des IRQ\n");
1030 goto err_irq;
1031 }
1032 }
1033
1034
1035 INIT_LIST_HEAD(&dd->list);
1036 spin_lock_bh(&list_lock);
1037 list_add_tail(&dd->list, &dev_list);
1038 spin_unlock_bh(&list_lock);
1039
1040
1041 dd->engine = crypto_engine_alloc_init(dev, 1);
1042 if (!dd->engine) {
1043 err = -ENOMEM;
1044 goto err_engine;
1045 }
1046
1047 err = crypto_engine_start(dd->engine);
1048 if (err)
1049 goto err_engine;
1050
1051 for (i = 0; i < dd->pdata->algs_info_size; i++) {
1052 for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
1053 algp = &dd->pdata->algs_info[i].algs_list[j];
1054
1055 pr_debug("reg alg: %s\n", algp->base.cra_name);
1056
1057 err = crypto_register_skcipher(algp);
1058 if (err)
1059 goto err_algs;
1060
1061 dd->pdata->algs_info[i].registered++;
1062 }
1063 }
1064
1065 return 0;
1066
1067 err_algs:
1068 for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
1069 for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
1070 crypto_unregister_skcipher(
1071 &dd->pdata->algs_info[i].algs_list[j]);
1072
1073 err_engine:
1074 if (dd->engine)
1075 crypto_engine_exit(dd->engine);
1076
1077 omap_des_dma_cleanup(dd);
1078 err_irq:
1079 tasklet_kill(&dd->done_task);
1080 err_get:
1081 pm_runtime_disable(dev);
1082 err_res:
1083 dd = NULL;
1084 err_data:
1085 dev_err(dev, "initialization failed.\n");
1086 return err;
1087 }
1088
1089 static int omap_des_remove(struct platform_device *pdev)
1090 {
1091 struct omap_des_dev *dd = platform_get_drvdata(pdev);
1092 int i, j;
1093
1094 spin_lock_bh(&list_lock);
1095 list_del(&dd->list);
1096 spin_unlock_bh(&list_lock);
1097
1098 for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
1099 for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
1100 crypto_unregister_skcipher(
1101 &dd->pdata->algs_info[i].algs_list[j]);
1102
1103 tasklet_kill(&dd->done_task);
1104 omap_des_dma_cleanup(dd);
1105 pm_runtime_disable(dd->dev);
1106
1107 return 0;
1108 }
1109
1110 #ifdef CONFIG_PM_SLEEP
1111 static int omap_des_suspend(struct device *dev)
1112 {
1113 pm_runtime_put_sync(dev);
1114 return 0;
1115 }
1116
1117 static int omap_des_resume(struct device *dev)
1118 {
1119 int err;
1120
1121 err = pm_runtime_resume_and_get(dev);
1122 if (err < 0) {
1123 dev_err(dev, "%s: failed to get_sync(%d)\n", __func__, err);
1124 return err;
1125 }
1126 return 0;
1127 }
1128 #endif
1129
1130 static SIMPLE_DEV_PM_OPS(omap_des_pm_ops, omap_des_suspend, omap_des_resume);
1131
1132 static struct platform_driver omap_des_driver = {
1133 .probe = omap_des_probe,
1134 .remove = omap_des_remove,
1135 .driver = {
1136 .name = "omap-des",
1137 .pm = &omap_des_pm_ops,
1138 .of_match_table = of_match_ptr(omap_des_of_match),
1139 },
1140 };
1141
1142 module_platform_driver(omap_des_driver);
1143
1144 MODULE_DESCRIPTION("OMAP DES hw acceleration support.");
1145 MODULE_LICENSE("GPL v2");
1146 MODULE_AUTHOR("Joel Fernandes <joelf@ti.com>");