aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorNicolas Ferre <nicolas.ferre@atmel.com>2013-10-15 06:14:58 -0400
committerNicolas Ferre <nicolas.ferre@atmel.com>2013-12-12 12:39:35 -0500
commit84c8976b643af63150072e6c3e5f156dd6f9c910 (patch)
tree298e02044dda27984e4e54aa3ae53f29947bd3aa /drivers/crypto
parentbe943c7d27b14dbd700770d2fd6c704be95a0ec9 (diff)
crypto: atmel-tdes - add support for Device Tree
Add support for Device Tree and use of the DMA DT API to get the channels if needed. Documentation is added for these DT nodes. Initial code by: Nicolas Royer and Eukrea. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/atmel-tdes.c143
1 files changed, 94 insertions, 49 deletions
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
769err_dma_out: 760err_dma_out:
770 dma_release_channel(dd->dma_lch_in.chan); 761 dma_release_channel(dd->dma_lch_in.chan);
771err_dma_in: 762err_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)
1313static const struct of_device_id atmel_tdes_dt_ids[] = {
1314 { .compatible = "atmel,at91sam9g46-tdes" },
1315 { /* sentinel */ }
1316};
1317MODULE_DEVICE_TABLE(of, atmel_tdes_dt_ids);
1318
1319static 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 */
1347static inline struct crypto_platform_data *atmel_tdes_of_init(struct platform_device *pdev)
1348{
1349 return ERR_PTR(-EINVAL);
1350}
1351#endif
1352
1320static int atmel_tdes_probe(struct platform_device *pdev) 1353static 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