cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

omap-des.c (27449B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Support for OMAP DES and Triple DES HW acceleration.
      4 *
      5 * Copyright (c) 2013 Texas Instruments Incorporated
      6 * Author: Joel Fernandes <joelf@ti.com>
      7 */
      8
      9#define pr_fmt(fmt) "%s: " fmt, __func__
     10
     11#ifdef DEBUG
     12#define prn(num) printk(#num "=%d\n", num)
     13#define prx(num) printk(#num "=%x\n", num)
     14#else
     15#define prn(num) do { } while (0)
     16#define prx(num)  do { } while (0)
     17#endif
     18
     19#include <linux/err.h>
     20#include <linux/module.h>
     21#include <linux/init.h>
     22#include <linux/errno.h>
     23#include <linux/kernel.h>
     24#include <linux/platform_device.h>
     25#include <linux/scatterlist.h>
     26#include <linux/dma-mapping.h>
     27#include <linux/dmaengine.h>
     28#include <linux/pm_runtime.h>
     29#include <linux/of.h>
     30#include <linux/of_device.h>
     31#include <linux/of_address.h>
     32#include <linux/io.h>
     33#include <linux/crypto.h>
     34#include <linux/interrupt.h>
     35#include <crypto/scatterwalk.h>
     36#include <crypto/internal/des.h>
     37#include <crypto/internal/skcipher.h>
     38#include <crypto/algapi.h>
     39#include <crypto/engine.h>
     40
     41#include "omap-crypto.h"
     42
     43#define DST_MAXBURST			2
     44
     45#define DES_BLOCK_WORDS		(DES_BLOCK_SIZE >> 2)
     46
     47#define _calc_walked(inout) (dd->inout##_walk.offset - dd->inout##_sg->offset)
     48
     49#define DES_REG_KEY(dd, x)		((dd)->pdata->key_ofs - \
     50						((x ^ 0x01) * 0x04))
     51
     52#define DES_REG_IV(dd, x)		((dd)->pdata->iv_ofs + ((x) * 0x04))
     53
     54#define DES_REG_CTRL(dd)		((dd)->pdata->ctrl_ofs)
     55#define DES_REG_CTRL_CBC		BIT(4)
     56#define DES_REG_CTRL_TDES		BIT(3)
     57#define DES_REG_CTRL_DIRECTION		BIT(2)
     58#define DES_REG_CTRL_INPUT_READY	BIT(1)
     59#define DES_REG_CTRL_OUTPUT_READY	BIT(0)
     60
     61#define DES_REG_DATA_N(dd, x)		((dd)->pdata->data_ofs + ((x) * 0x04))
     62
     63#define DES_REG_REV(dd)			((dd)->pdata->rev_ofs)
     64
     65#define DES_REG_MASK(dd)		((dd)->pdata->mask_ofs)
     66
     67#define DES_REG_LENGTH_N(x)		(0x24 + ((x) * 0x04))
     68
     69#define DES_REG_IRQ_STATUS(dd)         ((dd)->pdata->irq_status_ofs)
     70#define DES_REG_IRQ_ENABLE(dd)         ((dd)->pdata->irq_enable_ofs)
     71#define DES_REG_IRQ_DATA_IN            BIT(1)
     72#define DES_REG_IRQ_DATA_OUT           BIT(2)
     73
     74#define FLAGS_MODE_MASK		0x000f
     75#define FLAGS_ENCRYPT		BIT(0)
     76#define FLAGS_CBC		BIT(1)
     77#define FLAGS_INIT		BIT(4)
     78#define FLAGS_BUSY		BIT(6)
     79
     80#define DEFAULT_AUTOSUSPEND_DELAY	1000
     81
     82#define FLAGS_IN_DATA_ST_SHIFT	8
     83#define FLAGS_OUT_DATA_ST_SHIFT	10
     84
     85struct omap_des_ctx {
     86	struct crypto_engine_ctx enginectx;
     87	struct omap_des_dev *dd;
     88
     89	int		keylen;
     90	__le32		key[(3 * DES_KEY_SIZE) / sizeof(u32)];
     91	unsigned long	flags;
     92};
     93
     94struct omap_des_reqctx {
     95	unsigned long mode;
     96};
     97
     98#define OMAP_DES_QUEUE_LENGTH	1
     99#define OMAP_DES_CACHE_SIZE	0
    100
    101struct omap_des_algs_info {
    102	struct skcipher_alg	*algs_list;
    103	unsigned int		size;
    104	unsigned int		registered;
    105};
    106
    107struct omap_des_pdata {
    108	struct omap_des_algs_info	*algs_info;
    109	unsigned int	algs_info_size;
    110
    111	void		(*trigger)(struct omap_des_dev *dd, int length);
    112
    113	u32		key_ofs;
    114	u32		iv_ofs;
    115	u32		ctrl_ofs;
    116	u32		data_ofs;
    117	u32		rev_ofs;
    118	u32		mask_ofs;
    119	u32             irq_enable_ofs;
    120	u32             irq_status_ofs;
    121
    122	u32		dma_enable_in;
    123	u32		dma_enable_out;
    124	u32		dma_start;
    125
    126	u32		major_mask;
    127	u32		major_shift;
    128	u32		minor_mask;
    129	u32		minor_shift;
    130};
    131
    132struct omap_des_dev {
    133	struct list_head	list;
    134	unsigned long		phys_base;
    135	void __iomem		*io_base;
    136	struct omap_des_ctx	*ctx;
    137	struct device		*dev;
    138	unsigned long		flags;
    139	int			err;
    140
    141	struct tasklet_struct	done_task;
    142
    143	struct skcipher_request	*req;
    144	struct crypto_engine		*engine;
    145	/*
    146	 * total is used by PIO mode for book keeping so introduce
    147	 * variable total_save as need it to calc page_order
    148	 */
    149	size_t                          total;
    150	size_t                          total_save;
    151
    152	struct scatterlist		*in_sg;
    153	struct scatterlist		*out_sg;
    154
    155	/* Buffers for copying for unaligned cases */
    156	struct scatterlist		in_sgl;
    157	struct scatterlist		out_sgl;
    158	struct scatterlist		*orig_out;
    159
    160	struct scatter_walk		in_walk;
    161	struct scatter_walk		out_walk;
    162	struct dma_chan		*dma_lch_in;
    163	struct dma_chan		*dma_lch_out;
    164	int			in_sg_len;
    165	int			out_sg_len;
    166	int			pio_only;
    167	const struct omap_des_pdata	*pdata;
    168};
    169
    170/* keep registered devices data here */
    171static LIST_HEAD(dev_list);
    172static DEFINE_SPINLOCK(list_lock);
    173
    174#ifdef DEBUG
    175#define omap_des_read(dd, offset)                               \
    176	({                                                              \
    177	 int _read_ret;                                          \
    178	 _read_ret = __raw_readl(dd->io_base + offset);          \
    179	 pr_err("omap_des_read(" #offset "=%#x)= %#x\n",       \
    180		 offset, _read_ret);                            \
    181	 _read_ret;                                              \
    182	 })
    183#else
    184static inline u32 omap_des_read(struct omap_des_dev *dd, u32 offset)
    185{
    186	return __raw_readl(dd->io_base + offset);
    187}
    188#endif
    189
    190#ifdef DEBUG
    191#define omap_des_write(dd, offset, value)                               \
    192	do {                                                            \
    193		pr_err("omap_des_write(" #offset "=%#x) value=%#x\n", \
    194				offset, value);                                \
    195		__raw_writel(value, dd->io_base + offset);              \
    196	} while (0)
    197#else
    198static inline void omap_des_write(struct omap_des_dev *dd, u32 offset,
    199		u32 value)
    200{
    201	__raw_writel(value, dd->io_base + offset);
    202}
    203#endif
    204
    205static inline void omap_des_write_mask(struct omap_des_dev *dd, u32 offset,
    206					u32 value, u32 mask)
    207{
    208	u32 val;
    209
    210	val = omap_des_read(dd, offset);
    211	val &= ~mask;
    212	val |= value;
    213	omap_des_write(dd, offset, val);
    214}
    215
    216static void omap_des_write_n(struct omap_des_dev *dd, u32 offset,
    217					u32 *value, int count)
    218{
    219	for (; count--; value++, offset += 4)
    220		omap_des_write(dd, offset, *value);
    221}
    222
    223static int omap_des_hw_init(struct omap_des_dev *dd)
    224{
    225	int err;
    226
    227	/*
    228	 * clocks are enabled when request starts and disabled when finished.
    229	 * It may be long delays between requests.
    230	 * Device might go to off mode to save power.
    231	 */
    232	err = pm_runtime_resume_and_get(dd->dev);
    233	if (err < 0) {
    234		dev_err(dd->dev, "%s: failed to get_sync(%d)\n", __func__, err);
    235		return err;
    236	}
    237
    238	if (!(dd->flags & FLAGS_INIT)) {
    239		dd->flags |= FLAGS_INIT;
    240		dd->err = 0;
    241	}
    242
    243	return 0;
    244}
    245
    246static int omap_des_write_ctrl(struct omap_des_dev *dd)
    247{
    248	unsigned int key32;
    249	int i, err;
    250	u32 val = 0, mask = 0;
    251
    252	err = omap_des_hw_init(dd);
    253	if (err)
    254		return err;
    255
    256	key32 = dd->ctx->keylen / sizeof(u32);
    257
    258	/* it seems a key should always be set even if it has not changed */
    259	for (i = 0; i < key32; i++) {
    260		omap_des_write(dd, DES_REG_KEY(dd, i),
    261			       __le32_to_cpu(dd->ctx->key[i]));
    262	}
    263
    264	if ((dd->flags & FLAGS_CBC) && dd->req->iv)
    265		omap_des_write_n(dd, DES_REG_IV(dd, 0), (void *)dd->req->iv, 2);
    266
    267	if (dd->flags & FLAGS_CBC)
    268		val |= DES_REG_CTRL_CBC;
    269	if (dd->flags & FLAGS_ENCRYPT)
    270		val |= DES_REG_CTRL_DIRECTION;
    271	if (key32 == 6)
    272		val |= DES_REG_CTRL_TDES;
    273
    274	mask |= DES_REG_CTRL_CBC | DES_REG_CTRL_DIRECTION | DES_REG_CTRL_TDES;
    275
    276	omap_des_write_mask(dd, DES_REG_CTRL(dd), val, mask);
    277
    278	return 0;
    279}
    280
    281static void omap_des_dma_trigger_omap4(struct omap_des_dev *dd, int length)
    282{
    283	u32 mask, val;
    284
    285	omap_des_write(dd, DES_REG_LENGTH_N(0), length);
    286
    287	val = dd->pdata->dma_start;
    288
    289	if (dd->dma_lch_out != NULL)
    290		val |= dd->pdata->dma_enable_out;
    291	if (dd->dma_lch_in != NULL)
    292		val |= dd->pdata->dma_enable_in;
    293
    294	mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
    295	       dd->pdata->dma_start;
    296
    297	omap_des_write_mask(dd, DES_REG_MASK(dd), val, mask);
    298}
    299
    300static void omap_des_dma_stop(struct omap_des_dev *dd)
    301{
    302	u32 mask;
    303
    304	mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
    305	       dd->pdata->dma_start;
    306
    307	omap_des_write_mask(dd, DES_REG_MASK(dd), 0, mask);
    308}
    309
    310static struct omap_des_dev *omap_des_find_dev(struct omap_des_ctx *ctx)
    311{
    312	struct omap_des_dev *dd = NULL, *tmp;
    313
    314	spin_lock_bh(&list_lock);
    315	if (!ctx->dd) {
    316		list_for_each_entry(tmp, &dev_list, list) {
    317			/* FIXME: take fist available des core */
    318			dd = tmp;
    319			break;
    320		}
    321		ctx->dd = dd;
    322	} else {
    323		/* already found before */
    324		dd = ctx->dd;
    325	}
    326	spin_unlock_bh(&list_lock);
    327
    328	return dd;
    329}
    330
    331static void omap_des_dma_out_callback(void *data)
    332{
    333	struct omap_des_dev *dd = data;
    334
    335	/* dma_lch_out - completed */
    336	tasklet_schedule(&dd->done_task);
    337}
    338
    339static int omap_des_dma_init(struct omap_des_dev *dd)
    340{
    341	int err;
    342
    343	dd->dma_lch_out = NULL;
    344	dd->dma_lch_in = NULL;
    345
    346	dd->dma_lch_in = dma_request_chan(dd->dev, "rx");
    347	if (IS_ERR(dd->dma_lch_in)) {
    348		dev_err(dd->dev, "Unable to request in DMA channel\n");
    349		return PTR_ERR(dd->dma_lch_in);
    350	}
    351
    352	dd->dma_lch_out = dma_request_chan(dd->dev, "tx");
    353	if (IS_ERR(dd->dma_lch_out)) {
    354		dev_err(dd->dev, "Unable to request out DMA channel\n");
    355		err = PTR_ERR(dd->dma_lch_out);
    356		goto err_dma_out;
    357	}
    358
    359	return 0;
    360
    361err_dma_out:
    362	dma_release_channel(dd->dma_lch_in);
    363
    364	return err;
    365}
    366
    367static void omap_des_dma_cleanup(struct omap_des_dev *dd)
    368{
    369	if (dd->pio_only)
    370		return;
    371
    372	dma_release_channel(dd->dma_lch_out);
    373	dma_release_channel(dd->dma_lch_in);
    374}
    375
    376static int omap_des_crypt_dma(struct crypto_tfm *tfm,
    377		struct scatterlist *in_sg, struct scatterlist *out_sg,
    378		int in_sg_len, int out_sg_len)
    379{
    380	struct omap_des_ctx *ctx = crypto_tfm_ctx(tfm);
    381	struct omap_des_dev *dd = ctx->dd;
    382	struct dma_async_tx_descriptor *tx_in, *tx_out;
    383	struct dma_slave_config cfg;
    384	int ret;
    385
    386	if (dd->pio_only) {
    387		scatterwalk_start(&dd->in_walk, dd->in_sg);
    388		scatterwalk_start(&dd->out_walk, dd->out_sg);
    389
    390		/* Enable DATAIN interrupt and let it take
    391		   care of the rest */
    392		omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x2);
    393		return 0;
    394	}
    395
    396	dma_sync_sg_for_device(dd->dev, dd->in_sg, in_sg_len, DMA_TO_DEVICE);
    397
    398	memset(&cfg, 0, sizeof(cfg));
    399
    400	cfg.src_addr = dd->phys_base + DES_REG_DATA_N(dd, 0);
    401	cfg.dst_addr = dd->phys_base + DES_REG_DATA_N(dd, 0);
    402	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
    403	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
    404	cfg.src_maxburst = DST_MAXBURST;
    405	cfg.dst_maxburst = DST_MAXBURST;
    406
    407	/* IN */
    408	ret = dmaengine_slave_config(dd->dma_lch_in, &cfg);
    409	if (ret) {
    410		dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n",
    411			ret);
    412		return ret;
    413	}
    414
    415	tx_in = dmaengine_prep_slave_sg(dd->dma_lch_in, in_sg, in_sg_len,
    416					DMA_MEM_TO_DEV,
    417					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
    418	if (!tx_in) {
    419		dev_err(dd->dev, "IN prep_slave_sg() failed\n");
    420		return -EINVAL;
    421	}
    422
    423	/* No callback necessary */
    424	tx_in->callback_param = dd;
    425
    426	/* OUT */
    427	ret = dmaengine_slave_config(dd->dma_lch_out, &cfg);
    428	if (ret) {
    429		dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n",
    430			ret);
    431		return ret;
    432	}
    433
    434	tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, out_sg_len,
    435					DMA_DEV_TO_MEM,
    436					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
    437	if (!tx_out) {
    438		dev_err(dd->dev, "OUT prep_slave_sg() failed\n");
    439		return -EINVAL;
    440	}
    441
    442	tx_out->callback = omap_des_dma_out_callback;
    443	tx_out->callback_param = dd;
    444
    445	dmaengine_submit(tx_in);
    446	dmaengine_submit(tx_out);
    447
    448	dma_async_issue_pending(dd->dma_lch_in);
    449	dma_async_issue_pending(dd->dma_lch_out);
    450
    451	/* start DMA */
    452	dd->pdata->trigger(dd, dd->total);
    453
    454	return 0;
    455}
    456
    457static int omap_des_crypt_dma_start(struct omap_des_dev *dd)
    458{
    459	struct crypto_tfm *tfm = crypto_skcipher_tfm(
    460					crypto_skcipher_reqtfm(dd->req));
    461	int err;
    462
    463	pr_debug("total: %zd\n", dd->total);
    464
    465	if (!dd->pio_only) {
    466		err = dma_map_sg(dd->dev, dd->in_sg, dd->in_sg_len,
    467				 DMA_TO_DEVICE);
    468		if (!err) {
    469			dev_err(dd->dev, "dma_map_sg() error\n");
    470			return -EINVAL;
    471		}
    472
    473		err = dma_map_sg(dd->dev, dd->out_sg, dd->out_sg_len,
    474				 DMA_FROM_DEVICE);
    475		if (!err) {
    476			dev_err(dd->dev, "dma_map_sg() error\n");
    477			return -EINVAL;
    478		}
    479	}
    480
    481	err = omap_des_crypt_dma(tfm, dd->in_sg, dd->out_sg, dd->in_sg_len,
    482				 dd->out_sg_len);
    483	if (err && !dd->pio_only) {
    484		dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
    485		dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len,
    486			     DMA_FROM_DEVICE);
    487	}
    488
    489	return err;
    490}
    491
    492static void omap_des_finish_req(struct omap_des_dev *dd, int err)
    493{
    494	struct skcipher_request *req = dd->req;
    495
    496	pr_debug("err: %d\n", err);
    497
    498	crypto_finalize_skcipher_request(dd->engine, req, err);
    499
    500	pm_runtime_mark_last_busy(dd->dev);
    501	pm_runtime_put_autosuspend(dd->dev);
    502}
    503
    504static int omap_des_crypt_dma_stop(struct omap_des_dev *dd)
    505{
    506	pr_debug("total: %zd\n", dd->total);
    507
    508	omap_des_dma_stop(dd);
    509
    510	dmaengine_terminate_all(dd->dma_lch_in);
    511	dmaengine_terminate_all(dd->dma_lch_out);
    512
    513	return 0;
    514}
    515
    516static int omap_des_handle_queue(struct omap_des_dev *dd,
    517				 struct skcipher_request *req)
    518{
    519	if (req)
    520		return crypto_transfer_skcipher_request_to_engine(dd->engine, req);
    521
    522	return 0;
    523}
    524
    525static int omap_des_prepare_req(struct crypto_engine *engine,
    526				void *areq)
    527{
    528	struct skcipher_request *req = container_of(areq, struct skcipher_request, base);
    529	struct omap_des_ctx *ctx = crypto_skcipher_ctx(
    530			crypto_skcipher_reqtfm(req));
    531	struct omap_des_dev *dd = omap_des_find_dev(ctx);
    532	struct omap_des_reqctx *rctx;
    533	int ret;
    534	u16 flags;
    535
    536	if (!dd)
    537		return -ENODEV;
    538
    539	/* assign new request to device */
    540	dd->req = req;
    541	dd->total = req->cryptlen;
    542	dd->total_save = req->cryptlen;
    543	dd->in_sg = req->src;
    544	dd->out_sg = req->dst;
    545	dd->orig_out = req->dst;
    546
    547	flags = OMAP_CRYPTO_COPY_DATA;
    548	if (req->src == req->dst)
    549		flags |= OMAP_CRYPTO_FORCE_COPY;
    550
    551	ret = omap_crypto_align_sg(&dd->in_sg, dd->total, DES_BLOCK_SIZE,
    552				   &dd->in_sgl, flags,
    553				   FLAGS_IN_DATA_ST_SHIFT, &dd->flags);
    554	if (ret)
    555		return ret;
    556
    557	ret = omap_crypto_align_sg(&dd->out_sg, dd->total, DES_BLOCK_SIZE,
    558				   &dd->out_sgl, 0,
    559				   FLAGS_OUT_DATA_ST_SHIFT, &dd->flags);
    560	if (ret)
    561		return ret;
    562
    563	dd->in_sg_len = sg_nents_for_len(dd->in_sg, dd->total);
    564	if (dd->in_sg_len < 0)
    565		return dd->in_sg_len;
    566
    567	dd->out_sg_len = sg_nents_for_len(dd->out_sg, dd->total);
    568	if (dd->out_sg_len < 0)
    569		return dd->out_sg_len;
    570
    571	rctx = skcipher_request_ctx(req);
    572	ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
    573	rctx->mode &= FLAGS_MODE_MASK;
    574	dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode;
    575
    576	dd->ctx = ctx;
    577	ctx->dd = dd;
    578
    579	return omap_des_write_ctrl(dd);
    580}
    581
    582static int omap_des_crypt_req(struct crypto_engine *engine,
    583			      void *areq)
    584{
    585	struct skcipher_request *req = container_of(areq, struct skcipher_request, base);
    586	struct omap_des_ctx *ctx = crypto_skcipher_ctx(
    587			crypto_skcipher_reqtfm(req));
    588	struct omap_des_dev *dd = omap_des_find_dev(ctx);
    589
    590	if (!dd)
    591		return -ENODEV;
    592
    593	return omap_des_crypt_dma_start(dd);
    594}
    595
    596static void omap_des_done_task(unsigned long data)
    597{
    598	struct omap_des_dev *dd = (struct omap_des_dev *)data;
    599	int i;
    600
    601	pr_debug("enter done_task\n");
    602
    603	if (!dd->pio_only) {
    604		dma_sync_sg_for_device(dd->dev, dd->out_sg, dd->out_sg_len,
    605				       DMA_FROM_DEVICE);
    606		dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
    607		dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len,
    608			     DMA_FROM_DEVICE);
    609		omap_des_crypt_dma_stop(dd);
    610	}
    611
    612	omap_crypto_cleanup(&dd->in_sgl, NULL, 0, dd->total_save,
    613			    FLAGS_IN_DATA_ST_SHIFT, dd->flags);
    614
    615	omap_crypto_cleanup(&dd->out_sgl, dd->orig_out, 0, dd->total_save,
    616			    FLAGS_OUT_DATA_ST_SHIFT, dd->flags);
    617
    618	if ((dd->flags & FLAGS_CBC) && dd->req->iv)
    619		for (i = 0; i < 2; i++)
    620			((u32 *)dd->req->iv)[i] =
    621				omap_des_read(dd, DES_REG_IV(dd, i));
    622
    623	omap_des_finish_req(dd, 0);
    624
    625	pr_debug("exit\n");
    626}
    627
    628static int omap_des_crypt(struct skcipher_request *req, unsigned long mode)
    629{
    630	struct omap_des_ctx *ctx = crypto_skcipher_ctx(
    631			crypto_skcipher_reqtfm(req));
    632	struct omap_des_reqctx *rctx = skcipher_request_ctx(req);
    633	struct omap_des_dev *dd;
    634
    635	pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->cryptlen,
    636		 !!(mode & FLAGS_ENCRYPT),
    637		 !!(mode & FLAGS_CBC));
    638
    639	if (!req->cryptlen)
    640		return 0;
    641
    642	if (!IS_ALIGNED(req->cryptlen, DES_BLOCK_SIZE))
    643		return -EINVAL;
    644
    645	dd = omap_des_find_dev(ctx);
    646	if (!dd)
    647		return -ENODEV;
    648
    649	rctx->mode = mode;
    650
    651	return omap_des_handle_queue(dd, req);
    652}
    653
    654/* ********************** ALG API ************************************ */
    655
    656static int omap_des_setkey(struct crypto_skcipher *cipher, const u8 *key,
    657			   unsigned int keylen)
    658{
    659	struct omap_des_ctx *ctx = crypto_skcipher_ctx(cipher);
    660	int err;
    661
    662	pr_debug("enter, keylen: %d\n", keylen);
    663
    664	err = verify_skcipher_des_key(cipher, key);
    665	if (err)
    666		return err;
    667
    668	memcpy(ctx->key, key, keylen);
    669	ctx->keylen = keylen;
    670
    671	return 0;
    672}
    673
    674static int omap_des3_setkey(struct crypto_skcipher *cipher, const u8 *key,
    675			    unsigned int keylen)
    676{
    677	struct omap_des_ctx *ctx = crypto_skcipher_ctx(cipher);
    678	int err;
    679
    680	pr_debug("enter, keylen: %d\n", keylen);
    681
    682	err = verify_skcipher_des3_key(cipher, key);
    683	if (err)
    684		return err;
    685
    686	memcpy(ctx->key, key, keylen);
    687	ctx->keylen = keylen;
    688
    689	return 0;
    690}
    691
    692static int omap_des_ecb_encrypt(struct skcipher_request *req)
    693{
    694	return omap_des_crypt(req, FLAGS_ENCRYPT);
    695}
    696
    697static int omap_des_ecb_decrypt(struct skcipher_request *req)
    698{
    699	return omap_des_crypt(req, 0);
    700}
    701
    702static int omap_des_cbc_encrypt(struct skcipher_request *req)
    703{
    704	return omap_des_crypt(req, FLAGS_ENCRYPT | FLAGS_CBC);
    705}
    706
    707static int omap_des_cbc_decrypt(struct skcipher_request *req)
    708{
    709	return omap_des_crypt(req, FLAGS_CBC);
    710}
    711
    712static int omap_des_prepare_req(struct crypto_engine *engine,
    713				void *areq);
    714static int omap_des_crypt_req(struct crypto_engine *engine,
    715			      void *areq);
    716
    717static int omap_des_init_tfm(struct crypto_skcipher *tfm)
    718{
    719	struct omap_des_ctx *ctx = crypto_skcipher_ctx(tfm);
    720
    721	pr_debug("enter\n");
    722
    723	crypto_skcipher_set_reqsize(tfm, sizeof(struct omap_des_reqctx));
    724
    725	ctx->enginectx.op.prepare_request = omap_des_prepare_req;
    726	ctx->enginectx.op.unprepare_request = NULL;
    727	ctx->enginectx.op.do_one_request = omap_des_crypt_req;
    728
    729	return 0;
    730}
    731
    732/* ********************** ALGS ************************************ */
    733
    734static struct skcipher_alg algs_ecb_cbc[] = {
    735{
    736	.base.cra_name		= "ecb(des)",
    737	.base.cra_driver_name	= "ecb-des-omap",
    738	.base.cra_priority	= 300,
    739	.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
    740				  CRYPTO_ALG_ASYNC,
    741	.base.cra_blocksize	= DES_BLOCK_SIZE,
    742	.base.cra_ctxsize	= sizeof(struct omap_des_ctx),
    743	.base.cra_module	= THIS_MODULE,
    744
    745	.min_keysize		= DES_KEY_SIZE,
    746	.max_keysize		= DES_KEY_SIZE,
    747	.setkey			= omap_des_setkey,
    748	.encrypt		= omap_des_ecb_encrypt,
    749	.decrypt		= omap_des_ecb_decrypt,
    750	.init			= omap_des_init_tfm,
    751},
    752{
    753	.base.cra_name		= "cbc(des)",
    754	.base.cra_driver_name	= "cbc-des-omap",
    755	.base.cra_priority	= 300,
    756	.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
    757				  CRYPTO_ALG_ASYNC,
    758	.base.cra_blocksize	= DES_BLOCK_SIZE,
    759	.base.cra_ctxsize	= sizeof(struct omap_des_ctx),
    760	.base.cra_module	= THIS_MODULE,
    761
    762	.min_keysize		= DES_KEY_SIZE,
    763	.max_keysize		= DES_KEY_SIZE,
    764	.ivsize			= DES_BLOCK_SIZE,
    765	.setkey			= omap_des_setkey,
    766	.encrypt		= omap_des_cbc_encrypt,
    767	.decrypt		= omap_des_cbc_decrypt,
    768	.init			= omap_des_init_tfm,
    769},
    770{
    771	.base.cra_name		= "ecb(des3_ede)",
    772	.base.cra_driver_name	= "ecb-des3-omap",
    773	.base.cra_priority	= 300,
    774	.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
    775				  CRYPTO_ALG_ASYNC,
    776	.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
    777	.base.cra_ctxsize	= sizeof(struct omap_des_ctx),
    778	.base.cra_module	= THIS_MODULE,
    779
    780	.min_keysize		= DES3_EDE_KEY_SIZE,
    781	.max_keysize		= DES3_EDE_KEY_SIZE,
    782	.setkey			= omap_des3_setkey,
    783	.encrypt		= omap_des_ecb_encrypt,
    784	.decrypt		= omap_des_ecb_decrypt,
    785	.init			= omap_des_init_tfm,
    786},
    787{
    788	.base.cra_name		= "cbc(des3_ede)",
    789	.base.cra_driver_name	= "cbc-des3-omap",
    790	.base.cra_priority	= 300,
    791	.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
    792				  CRYPTO_ALG_ASYNC,
    793	.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
    794	.base.cra_ctxsize	= sizeof(struct omap_des_ctx),
    795	.base.cra_module	= THIS_MODULE,
    796
    797	.min_keysize		= DES3_EDE_KEY_SIZE,
    798	.max_keysize		= DES3_EDE_KEY_SIZE,
    799	.ivsize			= DES3_EDE_BLOCK_SIZE,
    800	.setkey			= omap_des3_setkey,
    801	.encrypt		= omap_des_cbc_encrypt,
    802	.decrypt		= omap_des_cbc_decrypt,
    803	.init			= omap_des_init_tfm,
    804}
    805};
    806
    807static struct omap_des_algs_info omap_des_algs_info_ecb_cbc[] = {
    808	{
    809		.algs_list	= algs_ecb_cbc,
    810		.size		= ARRAY_SIZE(algs_ecb_cbc),
    811	},
    812};
    813
    814#ifdef CONFIG_OF
    815static const struct omap_des_pdata omap_des_pdata_omap4 = {
    816	.algs_info	= omap_des_algs_info_ecb_cbc,
    817	.algs_info_size	= ARRAY_SIZE(omap_des_algs_info_ecb_cbc),
    818	.trigger	= omap_des_dma_trigger_omap4,
    819	.key_ofs	= 0x14,
    820	.iv_ofs		= 0x18,
    821	.ctrl_ofs	= 0x20,
    822	.data_ofs	= 0x28,
    823	.rev_ofs	= 0x30,
    824	.mask_ofs	= 0x34,
    825	.irq_status_ofs = 0x3c,
    826	.irq_enable_ofs = 0x40,
    827	.dma_enable_in	= BIT(5),
    828	.dma_enable_out	= BIT(6),
    829	.major_mask	= 0x0700,
    830	.major_shift	= 8,
    831	.minor_mask	= 0x003f,
    832	.minor_shift	= 0,
    833};
    834
    835static irqreturn_t omap_des_irq(int irq, void *dev_id)
    836{
    837	struct omap_des_dev *dd = dev_id;
    838	u32 status, i;
    839	u32 *src, *dst;
    840
    841	status = omap_des_read(dd, DES_REG_IRQ_STATUS(dd));
    842	if (status & DES_REG_IRQ_DATA_IN) {
    843		omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x0);
    844
    845		BUG_ON(!dd->in_sg);
    846
    847		BUG_ON(_calc_walked(in) > dd->in_sg->length);
    848
    849		src = sg_virt(dd->in_sg) + _calc_walked(in);
    850
    851		for (i = 0; i < DES_BLOCK_WORDS; i++) {
    852			omap_des_write(dd, DES_REG_DATA_N(dd, i), *src);
    853
    854			scatterwalk_advance(&dd->in_walk, 4);
    855			if (dd->in_sg->length == _calc_walked(in)) {
    856				dd->in_sg = sg_next(dd->in_sg);
    857				if (dd->in_sg) {
    858					scatterwalk_start(&dd->in_walk,
    859							  dd->in_sg);
    860					src = sg_virt(dd->in_sg) +
    861					      _calc_walked(in);
    862				}
    863			} else {
    864				src++;
    865			}
    866		}
    867
    868		/* Clear IRQ status */
    869		status &= ~DES_REG_IRQ_DATA_IN;
    870		omap_des_write(dd, DES_REG_IRQ_STATUS(dd), status);
    871
    872		/* Enable DATA_OUT interrupt */
    873		omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x4);
    874
    875	} else if (status & DES_REG_IRQ_DATA_OUT) {
    876		omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x0);
    877
    878		BUG_ON(!dd->out_sg);
    879
    880		BUG_ON(_calc_walked(out) > dd->out_sg->length);
    881
    882		dst = sg_virt(dd->out_sg) + _calc_walked(out);
    883
    884		for (i = 0; i < DES_BLOCK_WORDS; i++) {
    885			*dst = omap_des_read(dd, DES_REG_DATA_N(dd, i));
    886			scatterwalk_advance(&dd->out_walk, 4);
    887			if (dd->out_sg->length == _calc_walked(out)) {
    888				dd->out_sg = sg_next(dd->out_sg);
    889				if (dd->out_sg) {
    890					scatterwalk_start(&dd->out_walk,
    891							  dd->out_sg);
    892					dst = sg_virt(dd->out_sg) +
    893					      _calc_walked(out);
    894				}
    895			} else {
    896				dst++;
    897			}
    898		}
    899
    900		BUG_ON(dd->total < DES_BLOCK_SIZE);
    901
    902		dd->total -= DES_BLOCK_SIZE;
    903
    904		/* Clear IRQ status */
    905		status &= ~DES_REG_IRQ_DATA_OUT;
    906		omap_des_write(dd, DES_REG_IRQ_STATUS(dd), status);
    907
    908		if (!dd->total)
    909			/* All bytes read! */
    910			tasklet_schedule(&dd->done_task);
    911		else
    912			/* Enable DATA_IN interrupt for next block */
    913			omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x2);
    914	}
    915
    916	return IRQ_HANDLED;
    917}
    918
    919static const struct of_device_id omap_des_of_match[] = {
    920	{
    921		.compatible	= "ti,omap4-des",
    922		.data		= &omap_des_pdata_omap4,
    923	},
    924	{},
    925};
    926MODULE_DEVICE_TABLE(of, omap_des_of_match);
    927
    928static int omap_des_get_of(struct omap_des_dev *dd,
    929		struct platform_device *pdev)
    930{
    931
    932	dd->pdata = of_device_get_match_data(&pdev->dev);
    933	if (!dd->pdata) {
    934		dev_err(&pdev->dev, "no compatible OF match\n");
    935		return -EINVAL;
    936	}
    937
    938	return 0;
    939}
    940#else
    941static int omap_des_get_of(struct omap_des_dev *dd,
    942		struct device *dev)
    943{
    944	return -EINVAL;
    945}
    946#endif
    947
    948static int omap_des_get_pdev(struct omap_des_dev *dd,
    949		struct platform_device *pdev)
    950{
    951	/* non-DT devices get pdata from pdev */
    952	dd->pdata = pdev->dev.platform_data;
    953
    954	return 0;
    955}
    956
    957static int omap_des_probe(struct platform_device *pdev)
    958{
    959	struct device *dev = &pdev->dev;
    960	struct omap_des_dev *dd;
    961	struct skcipher_alg *algp;
    962	struct resource *res;
    963	int err = -ENOMEM, i, j, irq = -1;
    964	u32 reg;
    965
    966	dd = devm_kzalloc(dev, sizeof(struct omap_des_dev), GFP_KERNEL);
    967	if (dd == NULL) {
    968		dev_err(dev, "unable to alloc data struct.\n");
    969		goto err_data;
    970	}
    971	dd->dev = dev;
    972	platform_set_drvdata(pdev, dd);
    973
    974	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    975	if (!res) {
    976		dev_err(dev, "no MEM resource info\n");
    977		goto err_res;
    978	}
    979
    980	err = (dev->of_node) ? omap_des_get_of(dd, pdev) :
    981			       omap_des_get_pdev(dd, pdev);
    982	if (err)
    983		goto err_res;
    984
    985	dd->io_base = devm_ioremap_resource(dev, res);
    986	if (IS_ERR(dd->io_base)) {
    987		err = PTR_ERR(dd->io_base);
    988		goto err_res;
    989	}
    990	dd->phys_base = res->start;
    991
    992	pm_runtime_use_autosuspend(dev);
    993	pm_runtime_set_autosuspend_delay(dev, DEFAULT_AUTOSUSPEND_DELAY);
    994
    995	pm_runtime_enable(dev);
    996	err = pm_runtime_resume_and_get(dev);
    997	if (err < 0) {
    998		dev_err(dd->dev, "%s: failed to get_sync(%d)\n", __func__, err);
    999		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	/* Initialize des crypto engine */
   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
   1067err_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
   1073err_engine:
   1074	if (dd->engine)
   1075		crypto_engine_exit(dd->engine);
   1076
   1077	omap_des_dma_cleanup(dd);
   1078err_irq:
   1079	tasklet_kill(&dd->done_task);
   1080err_get:
   1081	pm_runtime_disable(dev);
   1082err_res:
   1083	dd = NULL;
   1084err_data:
   1085	dev_err(dev, "initialization failed.\n");
   1086	return err;
   1087}
   1088
   1089static 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	if (!dd)
   1095		return -ENODEV;
   1096
   1097	spin_lock_bh(&list_lock);
   1098	list_del(&dd->list);
   1099	spin_unlock_bh(&list_lock);
   1100
   1101	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
   1102		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
   1103			crypto_unregister_skcipher(
   1104					&dd->pdata->algs_info[i].algs_list[j]);
   1105
   1106	tasklet_kill(&dd->done_task);
   1107	omap_des_dma_cleanup(dd);
   1108	pm_runtime_disable(dd->dev);
   1109	dd = NULL;
   1110
   1111	return 0;
   1112}
   1113
   1114#ifdef CONFIG_PM_SLEEP
   1115static int omap_des_suspend(struct device *dev)
   1116{
   1117	pm_runtime_put_sync(dev);
   1118	return 0;
   1119}
   1120
   1121static int omap_des_resume(struct device *dev)
   1122{
   1123	int err;
   1124
   1125	err = pm_runtime_resume_and_get(dev);
   1126	if (err < 0) {
   1127		dev_err(dev, "%s: failed to get_sync(%d)\n", __func__, err);
   1128		return err;
   1129	}
   1130	return 0;
   1131}
   1132#endif
   1133
   1134static SIMPLE_DEV_PM_OPS(omap_des_pm_ops, omap_des_suspend, omap_des_resume);
   1135
   1136static struct platform_driver omap_des_driver = {
   1137	.probe	= omap_des_probe,
   1138	.remove	= omap_des_remove,
   1139	.driver	= {
   1140		.name	= "omap-des",
   1141		.pm	= &omap_des_pm_ops,
   1142		.of_match_table	= of_match_ptr(omap_des_of_match),
   1143	},
   1144};
   1145
   1146module_platform_driver(omap_des_driver);
   1147
   1148MODULE_DESCRIPTION("OMAP DES hw acceleration support.");
   1149MODULE_LICENSE("GPL v2");
   1150MODULE_AUTHOR("Joel Fernandes <joelf@ti.com>");