omap-des.c 27 KB

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