aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorMark A. Greer <mgreer@animalcreek.com>2013-01-08 13:57:46 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2013-01-19 18:16:44 -0500
commit0d35583a13ad29af06375678daa2e11772ec9267 (patch)
treefe011e9e5d2a9029cdf4169a5c16646ae90f9db4 /drivers/crypto
parentb4b87a934c30fb91cbdd18ae028acdc361e1cf0f (diff)
crypto: omap-aes - Add OMAP4/AM33XX AES Support
Add support for the OMAP4 version of the AES module that is present on OMAP4 and AM33xx SoCs. The modules have several differences including register offsets and how DMA is triggered. To handle these differences, a platform_data structure is defined and contains routine pointers, register offsets, and bit offsets within registers. OMAP2/OMAP3-specific routines are suffixed with '_omap2' and OMAP4/AM33xx routines are suffixed with '_omap4'. Note: The code being integrated is from the TI AM33xx SDK and was written by Greg Turner <gkmturner@gmail.com> and Herman Schuurman (current email unknown) while at TI. CC: Greg Turner <gkmturner@gmail.com> CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com> Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/omap-aes.c158
1 files changed, 125 insertions, 33 deletions
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index d34aa5df3dc1..bd1ad97404ab 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (c) 2010 Nokia Corporation 6 * Copyright (c) 2010 Nokia Corporation
7 * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com> 7 * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
8 * Copyright (c) 2011 Texas Instruments Incorporated
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as published 11 * it under the terms of the GNU General Public License version 2 as published
@@ -42,10 +43,11 @@
42#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end)) 43#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
43#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end)) 44#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
44 45
45#define AES_REG_KEY(x) (0x1C - ((x ^ 0x01) * 0x04)) 46#define AES_REG_KEY(dd, x) ((dd)->pdata->key_ofs - \
46#define AES_REG_IV(x) (0x20 + ((x) * 0x04)) 47 ((x ^ 0x01) * 0x04))
48#define AES_REG_IV(dd, x) ((dd)->pdata->iv_ofs + ((x) * 0x04))
47 49
48#define AES_REG_CTRL 0x30 50#define AES_REG_CTRL(dd) ((dd)->pdata->ctrl_ofs)
49#define AES_REG_CTRL_CTR_WIDTH (1 << 7) 51#define AES_REG_CTRL_CTR_WIDTH (1 << 7)
50#define AES_REG_CTRL_CTR (1 << 6) 52#define AES_REG_CTRL_CTR (1 << 6)
51#define AES_REG_CTRL_CBC (1 << 5) 53#define AES_REG_CTRL_CBC (1 << 5)
@@ -54,14 +56,11 @@
54#define AES_REG_CTRL_INPUT_READY (1 << 1) 56#define AES_REG_CTRL_INPUT_READY (1 << 1)
55#define AES_REG_CTRL_OUTPUT_READY (1 << 0) 57#define AES_REG_CTRL_OUTPUT_READY (1 << 0)
56 58
57#define AES_REG_DATA 0x34 59#define AES_REG_DATA_N(dd, x) ((dd)->pdata->data_ofs + ((x) * 0x04))
58#define AES_REG_DATA_N(x) (0x34 + ((x) * 0x04))
59 60
60#define AES_REG_REV 0x44 61#define AES_REG_REV(dd) ((dd)->pdata->rev_ofs)
61#define AES_REG_REV_MAJOR 0xF0
62#define AES_REG_REV_MINOR 0x0F
63 62
64#define AES_REG_MASK 0x48 63#define AES_REG_MASK(dd) ((dd)->pdata->mask_ofs)
65#define AES_REG_MASK_SIDLE (1 << 6) 64#define AES_REG_MASK_SIDLE (1 << 6)
66#define AES_REG_MASK_START (1 << 5) 65#define AES_REG_MASK_START (1 << 5)
67#define AES_REG_MASK_DMA_OUT_EN (1 << 3) 66#define AES_REG_MASK_DMA_OUT_EN (1 << 3)
@@ -69,8 +68,7 @@
69#define AES_REG_MASK_SOFTRESET (1 << 1) 68#define AES_REG_MASK_SOFTRESET (1 << 1)
70#define AES_REG_AUTOIDLE (1 << 0) 69#define AES_REG_AUTOIDLE (1 << 0)
71 70
72#define AES_REG_SYSSTATUS 0x4C 71#define AES_REG_LENGTH_N(x) (0x54 + ((x) * 0x04))
73#define AES_REG_SYSSTATUS_RESETDONE (1 << 0)
74 72
75#define DEFAULT_TIMEOUT (5*HZ) 73#define DEFAULT_TIMEOUT (5*HZ)
76 74
@@ -98,6 +96,26 @@ struct omap_aes_reqctx {
98#define OMAP_AES_QUEUE_LENGTH 1 96#define OMAP_AES_QUEUE_LENGTH 1
99#define OMAP_AES_CACHE_SIZE 0 97#define OMAP_AES_CACHE_SIZE 0
100 98
99struct omap_aes_pdata {
100 void (*trigger)(struct omap_aes_dev *dd, int length);
101
102 u32 key_ofs;
103 u32 iv_ofs;
104 u32 ctrl_ofs;
105 u32 data_ofs;
106 u32 rev_ofs;
107 u32 mask_ofs;
108
109 u32 dma_enable_in;
110 u32 dma_enable_out;
111 u32 dma_start;
112
113 u32 major_mask;
114 u32 major_shift;
115 u32 minor_mask;
116 u32 minor_shift;
117};
118
101struct omap_aes_dev { 119struct omap_aes_dev {
102 struct list_head list; 120 struct list_head list;
103 unsigned long phys_base; 121 unsigned long phys_base;
@@ -132,6 +150,8 @@ struct omap_aes_dev {
132 int dma_out; 150 int dma_out;
133 struct dma_chan *dma_lch_out; 151 struct dma_chan *dma_lch_out;
134 dma_addr_t dma_addr_out; 152 dma_addr_t dma_addr_out;
153
154 const struct omap_aes_pdata *pdata;
135}; 155};
136 156
137/* keep registered devices data here */ 157/* keep registered devices data here */
@@ -194,26 +214,16 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
194 if (err) 214 if (err)
195 return err; 215 return err;
196 216
197 val = 0;
198 if (dd->dma_lch_out != NULL)
199 val |= AES_REG_MASK_DMA_OUT_EN;
200 if (dd->dma_lch_in != NULL)
201 val |= AES_REG_MASK_DMA_IN_EN;
202
203 mask = AES_REG_MASK_DMA_IN_EN | AES_REG_MASK_DMA_OUT_EN;
204
205 omap_aes_write_mask(dd, AES_REG_MASK, val, mask);
206
207 key32 = dd->ctx->keylen / sizeof(u32); 217 key32 = dd->ctx->keylen / sizeof(u32);
208 218
209 /* it seems a key should always be set even if it has not changed */ 219 /* it seems a key should always be set even if it has not changed */
210 for (i = 0; i < key32; i++) { 220 for (i = 0; i < key32; i++) {
211 omap_aes_write(dd, AES_REG_KEY(i), 221 omap_aes_write(dd, AES_REG_KEY(dd, i),
212 __le32_to_cpu(dd->ctx->key[i])); 222 __le32_to_cpu(dd->ctx->key[i]));
213 } 223 }
214 224
215 if ((dd->flags & FLAGS_CBC) && dd->req->info) 225 if ((dd->flags & FLAGS_CBC) && dd->req->info)
216 omap_aes_write_n(dd, AES_REG_IV(0), dd->req->info, 4); 226 omap_aes_write_n(dd, AES_REG_IV(dd, 0), dd->req->info, 4);
217 227
218 val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3); 228 val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
219 if (dd->flags & FLAGS_CBC) 229 if (dd->flags & FLAGS_CBC)
@@ -224,11 +234,47 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
224 mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION | 234 mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
225 AES_REG_CTRL_KEY_SIZE; 235 AES_REG_CTRL_KEY_SIZE;
226 236
227 omap_aes_write_mask(dd, AES_REG_CTRL, val, mask); 237 omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, mask);
228 238
229 return 0; 239 return 0;
230} 240}
231 241
242static void omap_aes_dma_trigger_omap2(struct omap_aes_dev *dd, int length)
243{
244 u32 mask, val;
245
246 val = dd->pdata->dma_start;
247
248 if (dd->dma_lch_out != NULL)
249 val |= dd->pdata->dma_enable_out;
250 if (dd->dma_lch_in != NULL)
251 val |= dd->pdata->dma_enable_in;
252
253 mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
254 dd->pdata->dma_start;
255
256 omap_aes_write_mask(dd, AES_REG_MASK(dd), val, mask);
257
258}
259
260static void omap_aes_dma_trigger_omap4(struct omap_aes_dev *dd, int length)
261{
262 omap_aes_write(dd, AES_REG_LENGTH_N(0), length);
263 omap_aes_write(dd, AES_REG_LENGTH_N(1), 0);
264
265 omap_aes_dma_trigger_omap2(dd, length);
266}
267
268static void omap_aes_dma_stop(struct omap_aes_dev *dd)
269{
270 u32 mask;
271
272 mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
273 dd->pdata->dma_start;
274
275 omap_aes_write_mask(dd, AES_REG_MASK(dd), 0, mask);
276}
277
232static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx) 278static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
233{ 279{
234 struct omap_aes_dev *dd = NULL, *tmp; 280 struct omap_aes_dev *dd = NULL, *tmp;
@@ -413,8 +459,8 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
413 459
414 memset(&cfg, 0, sizeof(cfg)); 460 memset(&cfg, 0, sizeof(cfg));
415 461
416 cfg.src_addr = dd->phys_base + AES_REG_DATA; 462 cfg.src_addr = dd->phys_base + AES_REG_DATA_N(dd, 0);
417 cfg.dst_addr = dd->phys_base + AES_REG_DATA; 463 cfg.dst_addr = dd->phys_base + AES_REG_DATA_N(dd, 0);
418 cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 464 cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
419 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 465 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
420 cfg.src_maxburst = DST_MAXBURST; 466 cfg.src_maxburst = DST_MAXBURST;
@@ -464,9 +510,8 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
464 dma_async_issue_pending(dd->dma_lch_in); 510 dma_async_issue_pending(dd->dma_lch_in);
465 dma_async_issue_pending(dd->dma_lch_out); 511 dma_async_issue_pending(dd->dma_lch_out);
466 512
467 /* start DMA or disable idle mode */ 513 /* start DMA */
468 omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START, 514 dd->pdata->trigger(dd, length);
469 AES_REG_MASK_START);
470 515
471 return 0; 516 return 0;
472} 517}
@@ -586,7 +631,7 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
586 631
587 pr_debug("total: %d\n", dd->total); 632 pr_debug("total: %d\n", dd->total);
588 633
589 omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START); 634 omap_aes_dma_stop(dd);
590 635
591 dmaengine_terminate_all(dd->dma_lch_in); 636 dmaengine_terminate_all(dd->dma_lch_in);
592 dmaengine_terminate_all(dd->dma_lch_out); 637 dmaengine_terminate_all(dd->dma_lch_out);
@@ -826,10 +871,48 @@ static struct crypto_alg algs[] = {
826} 871}
827}; 872};
828 873
874static const struct omap_aes_pdata omap_aes_pdata_omap2 = {
875 .trigger = omap_aes_dma_trigger_omap2,
876 .key_ofs = 0x1c,
877 .iv_ofs = 0x20,
878 .ctrl_ofs = 0x30,
879 .data_ofs = 0x34,
880 .rev_ofs = 0x44,
881 .mask_ofs = 0x48,
882 .dma_enable_in = BIT(2),
883 .dma_enable_out = BIT(3),
884 .dma_start = BIT(5),
885 .major_mask = 0xf0,
886 .major_shift = 4,
887 .minor_mask = 0x0f,
888 .minor_shift = 0,
889};
890
829#ifdef CONFIG_OF 891#ifdef CONFIG_OF
892static const struct omap_aes_pdata omap_aes_pdata_omap4 = {
893 .trigger = omap_aes_dma_trigger_omap4,
894 .key_ofs = 0x3c,
895 .iv_ofs = 0x40,
896 .ctrl_ofs = 0x50,
897 .data_ofs = 0x60,
898 .rev_ofs = 0x80,
899 .mask_ofs = 0x84,
900 .dma_enable_in = BIT(5),
901 .dma_enable_out = BIT(6),
902 .major_mask = 0x0700,
903 .major_shift = 8,
904 .minor_mask = 0x003f,
905 .minor_shift = 0,
906};
907
830static const struct of_device_id omap_aes_of_match[] = { 908static const struct of_device_id omap_aes_of_match[] = {
831 { 909 {
832 .compatible = "ti,omap2-aes", 910 .compatible = "ti,omap2-aes",
911 .data = &omap_aes_pdata_omap2,
912 },
913 {
914 .compatible = "ti,omap4-aes",
915 .data = &omap_aes_pdata_omap4,
833 }, 916 },
834 {}, 917 {},
835}; 918};
@@ -859,6 +942,8 @@ static int omap_aes_get_res_of(struct omap_aes_dev *dd,
859 dd->dma_out = -1; /* Dummy value that's unused */ 942 dd->dma_out = -1; /* Dummy value that's unused */
860 dd->dma_in = -1; /* Dummy value that's unused */ 943 dd->dma_in = -1; /* Dummy value that's unused */
861 944
945 dd->pdata = match->data;
946
862err: 947err:
863 return err; 948 return err;
864} 949}
@@ -908,6 +993,9 @@ static int omap_aes_get_res_pdev(struct omap_aes_dev *dd,
908 } 993 }
909 dd->dma_in = r->start; 994 dd->dma_in = r->start;
910 995
996 /* Only OMAP2/3 can be non-DT */
997 dd->pdata = &omap_aes_pdata_omap2;
998
911err: 999err:
912 return err; 1000 return err;
913} 1001}
@@ -947,12 +1035,16 @@ static int omap_aes_probe(struct platform_device *pdev)
947 pm_runtime_enable(dev); 1035 pm_runtime_enable(dev);
948 pm_runtime_get_sync(dev); 1036 pm_runtime_get_sync(dev);
949 1037
950 reg = omap_aes_read(dd, AES_REG_REV); 1038 omap_aes_dma_stop(dd);
951 dev_info(dev, "OMAP AES hw accel rev: %u.%u\n", 1039
952 (reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR); 1040 reg = omap_aes_read(dd, AES_REG_REV(dd));
953 1041
954 pm_runtime_put_sync(dev); 1042 pm_runtime_put_sync(dev);
955 1043
1044 dev_info(dev, "OMAP AES hw accel rev: %u.%u\n",
1045 (reg & dd->pdata->major_mask) >> dd->pdata->major_shift,
1046 (reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
1047
956 tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd); 1048 tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd);
957 tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd); 1049 tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd);
958 1050