diff options
-rw-r--r-- | Documentation/devicetree/bindings/crypto/atmel-crypto.txt | 23 | ||||
-rw-r--r-- | drivers/crypto/atmel-tdes.c | 143 |
2 files changed, 117 insertions, 49 deletions
diff --git a/Documentation/devicetree/bindings/crypto/atmel-crypto.txt b/Documentation/devicetree/bindings/crypto/atmel-crypto.txt index d273f0ba549e..9a24fd900614 100644 --- a/Documentation/devicetree/bindings/crypto/atmel-crypto.txt +++ b/Documentation/devicetree/bindings/crypto/atmel-crypto.txt | |||
@@ -21,3 +21,26 @@ aes@f8038000 { | |||
21 | dmas = <&dma1 2 18>, | 21 | dmas = <&dma1 2 18>, |
22 | <&dma1 2 19>; | 22 | <&dma1 2 19>; |
23 | dma-names = "tx", "rx"; | 23 | dma-names = "tx", "rx"; |
24 | |||
25 | * Triple Data Encryption Standard (Triple DES) | ||
26 | |||
27 | Required properties: | ||
28 | - compatible : Should be "atmel,at91sam9g46-tdes". | ||
29 | - reg: Should contain TDES registers location and length. | ||
30 | - interrupts: Should contain the IRQ line for the TDES. | ||
31 | |||
32 | Optional properties: | ||
33 | - dmas: List of two DMA specifiers as described in | ||
34 | atmel-dma.txt and dma.txt files. | ||
35 | - dma-names: Contains one identifier string for each DMA specifier | ||
36 | in the dmas property. | ||
37 | |||
38 | Example: | ||
39 | tdes@f803c000 { | ||
40 | compatible = "atmel,at91sam9g46-tdes"; | ||
41 | reg = <0xf803c000 0x100>; | ||
42 | interrupts = <44 4 0>; | ||
43 | dmas = <&dma1 2 20>, | ||
44 | <&dma1 2 21>; | ||
45 | dma-names = "tx", "rx"; | ||
46 | }; | ||
diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index 4a99564a08e6..6cde5b530c69 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.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> |
@@ -716,59 +717,50 @@ static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd, | |||
716 | struct crypto_platform_data *pdata) | 717 | struct crypto_platform_data *pdata) |
717 | { | 718 | { |
718 | int err = -ENOMEM; | 719 | int err = -ENOMEM; |
719 | dma_cap_mask_t mask_in, mask_out; | 720 | dma_cap_mask_t mask; |
721 | |||
722 | dma_cap_zero(mask); | ||
723 | dma_cap_set(DMA_SLAVE, mask); | ||
724 | |||
725 | /* Try to grab 2 DMA channels */ | ||
726 | dd->dma_lch_in.chan = dma_request_slave_channel_compat(mask, | ||
727 | atmel_tdes_filter, &pdata->dma_slave->rxdata, dd->dev, "tx"); | ||
728 | if (!dd->dma_lch_in.chan) | ||
729 | goto err_dma_in; | ||
730 | |||
731 | dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; | ||
732 | dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + | ||
733 | TDES_IDATA1R; | ||
734 | dd->dma_lch_in.dma_conf.src_maxburst = 1; | ||
735 | dd->dma_lch_in.dma_conf.src_addr_width = | ||
736 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
737 | dd->dma_lch_in.dma_conf.dst_maxburst = 1; | ||
738 | dd->dma_lch_in.dma_conf.dst_addr_width = | ||
739 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
740 | dd->dma_lch_in.dma_conf.device_fc = false; | ||
741 | |||
742 | dd->dma_lch_out.chan = dma_request_slave_channel_compat(mask, | ||
743 | atmel_tdes_filter, &pdata->dma_slave->txdata, dd->dev, "rx"); | ||
744 | if (!dd->dma_lch_out.chan) | ||
745 | goto err_dma_out; | ||
746 | |||
747 | dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; | ||
748 | dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + | ||
749 | TDES_ODATA1R; | ||
750 | dd->dma_lch_out.dma_conf.src_maxburst = 1; | ||
751 | dd->dma_lch_out.dma_conf.src_addr_width = | ||
752 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
753 | dd->dma_lch_out.dma_conf.dst_maxburst = 1; | ||
754 | dd->dma_lch_out.dma_conf.dst_addr_width = | ||
755 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
756 | dd->dma_lch_out.dma_conf.device_fc = false; | ||
720 | 757 | ||
721 | if (pdata && pdata->dma_slave->txdata.dma_dev && | 758 | return 0; |
722 | pdata->dma_slave->rxdata.dma_dev) { | ||
723 | |||
724 | /* Try to grab 2 DMA channels */ | ||
725 | dma_cap_zero(mask_in); | ||
726 | dma_cap_set(DMA_SLAVE, mask_in); | ||
727 | |||
728 | dd->dma_lch_in.chan = dma_request_channel(mask_in, | ||
729 | atmel_tdes_filter, &pdata->dma_slave->rxdata); | ||
730 | |||
731 | if (!dd->dma_lch_in.chan) | ||
732 | goto err_dma_in; | ||
733 | |||
734 | dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; | ||
735 | dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + | ||
736 | TDES_IDATA1R; | ||
737 | dd->dma_lch_in.dma_conf.src_maxburst = 1; | ||
738 | dd->dma_lch_in.dma_conf.src_addr_width = | ||
739 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
740 | dd->dma_lch_in.dma_conf.dst_maxburst = 1; | ||
741 | dd->dma_lch_in.dma_conf.dst_addr_width = | ||
742 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
743 | dd->dma_lch_in.dma_conf.device_fc = false; | ||
744 | |||
745 | dma_cap_zero(mask_out); | ||
746 | dma_cap_set(DMA_SLAVE, mask_out); | ||
747 | dd->dma_lch_out.chan = dma_request_channel(mask_out, | ||
748 | atmel_tdes_filter, &pdata->dma_slave->txdata); | ||
749 | |||
750 | if (!dd->dma_lch_out.chan) | ||
751 | goto err_dma_out; | ||
752 | |||
753 | dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; | ||
754 | dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + | ||
755 | TDES_ODATA1R; | ||
756 | dd->dma_lch_out.dma_conf.src_maxburst = 1; | ||
757 | dd->dma_lch_out.dma_conf.src_addr_width = | ||
758 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
759 | dd->dma_lch_out.dma_conf.dst_maxburst = 1; | ||
760 | dd->dma_lch_out.dma_conf.dst_addr_width = | ||
761 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
762 | dd->dma_lch_out.dma_conf.device_fc = false; | ||
763 | |||
764 | return 0; | ||
765 | } else { | ||
766 | return -ENODEV; | ||
767 | } | ||
768 | 759 | ||
769 | err_dma_out: | 760 | err_dma_out: |
770 | dma_release_channel(dd->dma_lch_in.chan); | 761 | dma_release_channel(dd->dma_lch_in.chan); |
771 | err_dma_in: | 762 | err_dma_in: |
763 | dev_warn(dd->dev, "no DMA channel available\n"); | ||
772 | return err; | 764 | return err; |
773 | } | 765 | } |
774 | 766 | ||
@@ -1317,6 +1309,47 @@ static void atmel_tdes_get_cap(struct atmel_tdes_dev *dd) | |||
1317 | } | 1309 | } |
1318 | } | 1310 | } |
1319 | 1311 | ||
1312 | #if defined(CONFIG_OF) | ||
1313 | static const struct of_device_id atmel_tdes_dt_ids[] = { | ||
1314 | { .compatible = "atmel,at91sam9g46-tdes" }, | ||
1315 | { /* sentinel */ } | ||
1316 | }; | ||
1317 | MODULE_DEVICE_TABLE(of, atmel_tdes_dt_ids); | ||
1318 | |||
1319 | static struct crypto_platform_data *atmel_tdes_of_init(struct platform_device *pdev) | ||
1320 | { | ||
1321 | struct device_node *np = pdev->dev.of_node; | ||
1322 | struct crypto_platform_data *pdata; | ||
1323 | |||
1324 | if (!np) { | ||
1325 | dev_err(&pdev->dev, "device node not found\n"); | ||
1326 | return ERR_PTR(-EINVAL); | ||
1327 | } | ||
1328 | |||
1329 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
1330 | if (!pdata) { | ||
1331 | dev_err(&pdev->dev, "could not allocate memory for pdata\n"); | ||
1332 | return ERR_PTR(-ENOMEM); | ||
1333 | } | ||
1334 | |||
1335 | pdata->dma_slave = devm_kzalloc(&pdev->dev, | ||
1336 | sizeof(*(pdata->dma_slave)), | ||
1337 | GFP_KERNEL); | ||
1338 | if (!pdata->dma_slave) { | ||
1339 | dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); | ||
1340 | devm_kfree(&pdev->dev, pdata); | ||
1341 | return ERR_PTR(-ENOMEM); | ||
1342 | } | ||
1343 | |||
1344 | return pdata; | ||
1345 | } | ||
1346 | #else /* CONFIG_OF */ | ||
1347 | static inline struct crypto_platform_data *atmel_tdes_of_init(struct platform_device *pdev) | ||
1348 | { | ||
1349 | return ERR_PTR(-EINVAL); | ||
1350 | } | ||
1351 | #endif | ||
1352 | |||
1320 | static int atmel_tdes_probe(struct platform_device *pdev) | 1353 | static int atmel_tdes_probe(struct platform_device *pdev) |
1321 | { | 1354 | { |
1322 | struct atmel_tdes_dev *tdes_dd; | 1355 | struct atmel_tdes_dev *tdes_dd; |
@@ -1399,13 +1432,24 @@ static int atmel_tdes_probe(struct platform_device *pdev) | |||
1399 | if (tdes_dd->caps.has_dma) { | 1432 | if (tdes_dd->caps.has_dma) { |
1400 | pdata = pdev->dev.platform_data; | 1433 | pdata = pdev->dev.platform_data; |
1401 | if (!pdata) { | 1434 | if (!pdata) { |
1402 | dev_err(&pdev->dev, "platform data not available\n"); | 1435 | pdata = atmel_tdes_of_init(pdev); |
1436 | if (IS_ERR(pdata)) { | ||
1437 | dev_err(&pdev->dev, "platform data not available\n"); | ||
1438 | err = PTR_ERR(pdata); | ||
1439 | goto err_pdata; | ||
1440 | } | ||
1441 | } | ||
1442 | if (!pdata->dma_slave) { | ||
1403 | err = -ENXIO; | 1443 | err = -ENXIO; |
1404 | goto err_pdata; | 1444 | goto err_pdata; |
1405 | } | 1445 | } |
1406 | err = atmel_tdes_dma_init(tdes_dd, pdata); | 1446 | err = atmel_tdes_dma_init(tdes_dd, pdata); |
1407 | if (err) | 1447 | if (err) |
1408 | goto err_tdes_dma; | 1448 | goto err_tdes_dma; |
1449 | |||
1450 | dev_info(dev, "using %s, %s for DMA transfers\n", | ||
1451 | dma_chan_name(tdes_dd->dma_lch_in.chan), | ||
1452 | dma_chan_name(tdes_dd->dma_lch_out.chan)); | ||
1409 | } | 1453 | } |
1410 | 1454 | ||
1411 | spin_lock(&atmel_tdes.lock); | 1455 | spin_lock(&atmel_tdes.lock); |
@@ -1487,6 +1531,7 @@ static struct platform_driver atmel_tdes_driver = { | |||
1487 | .driver = { | 1531 | .driver = { |
1488 | .name = "atmel_tdes", | 1532 | .name = "atmel_tdes", |
1489 | .owner = THIS_MODULE, | 1533 | .owner = THIS_MODULE, |
1534 | .of_match_table = of_match_ptr(atmel_tdes_dt_ids), | ||
1490 | }, | 1535 | }, |
1491 | }; | 1536 | }; |
1492 | 1537 | ||