diff options
Diffstat (limited to 'drivers/crypto/atmel-aes.c')
-rw-r--r-- | drivers/crypto/atmel-aes.c | 143 |
1 files changed, 94 insertions, 49 deletions
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index c1efd910d97b..d7c9e317423c 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/irq.h> | 30 | #include <linux/irq.h> |
31 | #include <linux/scatterlist.h> | 31 | #include <linux/scatterlist.h> |
32 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
33 | #include <linux/of_device.h> | ||
33 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
34 | #include <linux/crypto.h> | 35 | #include <linux/crypto.h> |
35 | #include <linux/cryptohash.h> | 36 | #include <linux/cryptohash.h> |
@@ -39,6 +40,7 @@ | |||
39 | #include <crypto/hash.h> | 40 | #include <crypto/hash.h> |
40 | #include <crypto/internal/hash.h> | 41 | #include <crypto/internal/hash.h> |
41 | #include <linux/platform_data/crypto-atmel.h> | 42 | #include <linux/platform_data/crypto-atmel.h> |
43 | #include <dt-bindings/dma/at91.h> | ||
42 | #include "atmel-aes-regs.h" | 44 | #include "atmel-aes-regs.h" |
43 | 45 | ||
44 | #define CFB8_BLOCK_SIZE 1 | 46 | #define CFB8_BLOCK_SIZE 1 |
@@ -747,59 +749,50 @@ static int atmel_aes_dma_init(struct atmel_aes_dev *dd, | |||
747 | struct crypto_platform_data *pdata) | 749 | struct crypto_platform_data *pdata) |
748 | { | 750 | { |
749 | int err = -ENOMEM; | 751 | int err = -ENOMEM; |
750 | dma_cap_mask_t mask_in, mask_out; | 752 | dma_cap_mask_t mask; |
753 | |||
754 | dma_cap_zero(mask); | ||
755 | dma_cap_set(DMA_SLAVE, mask); | ||
756 | |||
757 | /* Try to grab 2 DMA channels */ | ||
758 | dd->dma_lch_in.chan = dma_request_slave_channel_compat(mask, | ||
759 | atmel_aes_filter, &pdata->dma_slave->rxdata, dd->dev, "tx"); | ||
760 | if (!dd->dma_lch_in.chan) | ||
761 | goto err_dma_in; | ||
762 | |||
763 | dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; | ||
764 | dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + | ||
765 | AES_IDATAR(0); | ||
766 | dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size; | ||
767 | dd->dma_lch_in.dma_conf.src_addr_width = | ||
768 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
769 | dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size; | ||
770 | dd->dma_lch_in.dma_conf.dst_addr_width = | ||
771 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
772 | dd->dma_lch_in.dma_conf.device_fc = false; | ||
773 | |||
774 | dd->dma_lch_out.chan = dma_request_slave_channel_compat(mask, | ||
775 | atmel_aes_filter, &pdata->dma_slave->txdata, dd->dev, "rx"); | ||
776 | if (!dd->dma_lch_out.chan) | ||
777 | goto err_dma_out; | ||
778 | |||
779 | dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; | ||
780 | dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + | ||
781 | AES_ODATAR(0); | ||
782 | dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size; | ||
783 | dd->dma_lch_out.dma_conf.src_addr_width = | ||
784 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
785 | dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size; | ||
786 | dd->dma_lch_out.dma_conf.dst_addr_width = | ||
787 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
788 | dd->dma_lch_out.dma_conf.device_fc = false; | ||
751 | 789 | ||
752 | if (pdata && pdata->dma_slave->txdata.dma_dev && | 790 | return 0; |
753 | pdata->dma_slave->rxdata.dma_dev) { | ||
754 | |||
755 | /* Try to grab 2 DMA channels */ | ||
756 | dma_cap_zero(mask_in); | ||
757 | dma_cap_set(DMA_SLAVE, mask_in); | ||
758 | |||
759 | dd->dma_lch_in.chan = dma_request_channel(mask_in, | ||
760 | atmel_aes_filter, &pdata->dma_slave->rxdata); | ||
761 | |||
762 | if (!dd->dma_lch_in.chan) | ||
763 | goto err_dma_in; | ||
764 | |||
765 | dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; | ||
766 | dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + | ||
767 | AES_IDATAR(0); | ||
768 | dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size; | ||
769 | dd->dma_lch_in.dma_conf.src_addr_width = | ||
770 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
771 | dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size; | ||
772 | dd->dma_lch_in.dma_conf.dst_addr_width = | ||
773 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
774 | dd->dma_lch_in.dma_conf.device_fc = false; | ||
775 | |||
776 | dma_cap_zero(mask_out); | ||
777 | dma_cap_set(DMA_SLAVE, mask_out); | ||
778 | dd->dma_lch_out.chan = dma_request_channel(mask_out, | ||
779 | atmel_aes_filter, &pdata->dma_slave->txdata); | ||
780 | |||
781 | if (!dd->dma_lch_out.chan) | ||
782 | goto err_dma_out; | ||
783 | |||
784 | dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; | ||
785 | dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + | ||
786 | AES_ODATAR(0); | ||
787 | dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size; | ||
788 | dd->dma_lch_out.dma_conf.src_addr_width = | ||
789 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
790 | dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size; | ||
791 | dd->dma_lch_out.dma_conf.dst_addr_width = | ||
792 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
793 | dd->dma_lch_out.dma_conf.device_fc = false; | ||
794 | |||
795 | return 0; | ||
796 | } else { | ||
797 | return -ENODEV; | ||
798 | } | ||
799 | 791 | ||
800 | err_dma_out: | 792 | err_dma_out: |
801 | dma_release_channel(dd->dma_lch_in.chan); | 793 | dma_release_channel(dd->dma_lch_in.chan); |
802 | err_dma_in: | 794 | err_dma_in: |
795 | dev_warn(dd->dev, "no DMA channel available\n"); | ||
803 | return err; | 796 | return err; |
804 | } | 797 | } |
805 | 798 | ||
@@ -1261,6 +1254,47 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd) | |||
1261 | } | 1254 | } |
1262 | } | 1255 | } |
1263 | 1256 | ||
1257 | #if defined(CONFIG_OF) | ||
1258 | static const struct of_device_id atmel_aes_dt_ids[] = { | ||
1259 | { .compatible = "atmel,at91sam9g46-aes" }, | ||
1260 | { /* sentinel */ } | ||
1261 | }; | ||
1262 | MODULE_DEVICE_TABLE(of, atmel_aes_dt_ids); | ||
1263 | |||
1264 | static struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev) | ||
1265 | { | ||
1266 | struct device_node *np = pdev->dev.of_node; | ||
1267 | struct crypto_platform_data *pdata; | ||
1268 | |||
1269 | if (!np) { | ||
1270 | dev_err(&pdev->dev, "device node not found\n"); | ||
1271 | return ERR_PTR(-EINVAL); | ||
1272 | } | ||
1273 | |||
1274 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
1275 | if (!pdata) { | ||
1276 | dev_err(&pdev->dev, "could not allocate memory for pdata\n"); | ||
1277 | return ERR_PTR(-ENOMEM); | ||
1278 | } | ||
1279 | |||
1280 | pdata->dma_slave = devm_kzalloc(&pdev->dev, | ||
1281 | sizeof(*(pdata->dma_slave)), | ||
1282 | GFP_KERNEL); | ||
1283 | if (!pdata->dma_slave) { | ||
1284 | dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); | ||
1285 | devm_kfree(&pdev->dev, pdata); | ||
1286 | return ERR_PTR(-ENOMEM); | ||
1287 | } | ||
1288 | |||
1289 | return pdata; | ||
1290 | } | ||
1291 | #else | ||
1292 | static inline struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev) | ||
1293 | { | ||
1294 | return ERR_PTR(-EINVAL); | ||
1295 | } | ||
1296 | #endif | ||
1297 | |||
1264 | static int atmel_aes_probe(struct platform_device *pdev) | 1298 | static int atmel_aes_probe(struct platform_device *pdev) |
1265 | { | 1299 | { |
1266 | struct atmel_aes_dev *aes_dd; | 1300 | struct atmel_aes_dev *aes_dd; |
@@ -1272,6 +1306,14 @@ static int atmel_aes_probe(struct platform_device *pdev) | |||
1272 | 1306 | ||
1273 | pdata = pdev->dev.platform_data; | 1307 | pdata = pdev->dev.platform_data; |
1274 | if (!pdata) { | 1308 | if (!pdata) { |
1309 | pdata = atmel_aes_of_init(pdev); | ||
1310 | if (IS_ERR(pdata)) { | ||
1311 | err = PTR_ERR(pdata); | ||
1312 | goto aes_dd_err; | ||
1313 | } | ||
1314 | } | ||
1315 | |||
1316 | if (!pdata->dma_slave) { | ||
1275 | err = -ENXIO; | 1317 | err = -ENXIO; |
1276 | goto aes_dd_err; | 1318 | goto aes_dd_err; |
1277 | } | 1319 | } |
@@ -1358,7 +1400,9 @@ static int atmel_aes_probe(struct platform_device *pdev) | |||
1358 | if (err) | 1400 | if (err) |
1359 | goto err_algs; | 1401 | goto err_algs; |
1360 | 1402 | ||
1361 | dev_info(dev, "Atmel AES\n"); | 1403 | dev_info(dev, "Atmel AES - Using %s, %s for DMA transfers\n", |
1404 | dma_chan_name(aes_dd->dma_lch_in.chan), | ||
1405 | dma_chan_name(aes_dd->dma_lch_out.chan)); | ||
1362 | 1406 | ||
1363 | return 0; | 1407 | return 0; |
1364 | 1408 | ||
@@ -1424,6 +1468,7 @@ static struct platform_driver atmel_aes_driver = { | |||
1424 | .driver = { | 1468 | .driver = { |
1425 | .name = "atmel_aes", | 1469 | .name = "atmel_aes", |
1426 | .owner = THIS_MODULE, | 1470 | .owner = THIS_MODULE, |
1471 | .of_match_table = of_match_ptr(atmel_aes_dt_ids), | ||
1427 | }, | 1472 | }, |
1428 | }; | 1473 | }; |
1429 | 1474 | ||