omap-des.c 28 KB

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