diff options
-rw-r--r-- | Documentation/devicetree/bindings/crypto/atmel-crypto.txt | 22 | ||||
-rw-r--r-- | drivers/crypto/atmel-sha.c | 99 |
2 files changed, 97 insertions, 24 deletions
diff --git a/Documentation/devicetree/bindings/crypto/atmel-crypto.txt b/Documentation/devicetree/bindings/crypto/atmel-crypto.txt index 9a24fd900614..f2aab3dc2b52 100644 --- a/Documentation/devicetree/bindings/crypto/atmel-crypto.txt +++ b/Documentation/devicetree/bindings/crypto/atmel-crypto.txt | |||
@@ -44,3 +44,25 @@ tdes@f803c000 { | |||
44 | <&dma1 2 21>; | 44 | <&dma1 2 21>; |
45 | dma-names = "tx", "rx"; | 45 | dma-names = "tx", "rx"; |
46 | }; | 46 | }; |
47 | |||
48 | * Secure Hash Algorithm (SHA) | ||
49 | |||
50 | Required properties: | ||
51 | - compatible : Should be "atmel,at91sam9g46-sha". | ||
52 | - reg: Should contain SHA registers location and length. | ||
53 | - interrupts: Should contain the IRQ line for the SHA. | ||
54 | |||
55 | Optional properties: | ||
56 | - dmas: One DMA specifiers as described in | ||
57 | atmel-dma.txt and dma.txt files. | ||
58 | - dma-names: Contains one identifier string for each DMA specifier | ||
59 | in the dmas property. Only one "tx" string needed. | ||
60 | |||
61 | Example: | ||
62 | sha@f8034000 { | ||
63 | compatible = "atmel,at91sam9g46-sha"; | ||
64 | reg = <0xf8034000 0x100>; | ||
65 | interrupts = <42 4 0>; | ||
66 | dmas = <&dma1 2 17>; | ||
67 | dma-names = "tx"; | ||
68 | }; | ||
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index eaed8bf183bc..ecfdf727cc36 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.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> |
@@ -1263,32 +1264,29 @@ static int atmel_sha_dma_init(struct atmel_sha_dev *dd, | |||
1263 | int err = -ENOMEM; | 1264 | int err = -ENOMEM; |
1264 | dma_cap_mask_t mask_in; | 1265 | dma_cap_mask_t mask_in; |
1265 | 1266 | ||
1266 | if (pdata && pdata->dma_slave->rxdata.dma_dev) { | 1267 | /* Try to grab DMA channel */ |
1267 | /* Try to grab DMA channel */ | 1268 | dma_cap_zero(mask_in); |
1268 | dma_cap_zero(mask_in); | 1269 | dma_cap_set(DMA_SLAVE, mask_in); |
1269 | dma_cap_set(DMA_SLAVE, mask_in); | ||
1270 | 1270 | ||
1271 | dd->dma_lch_in.chan = dma_request_channel(mask_in, | 1271 | dd->dma_lch_in.chan = dma_request_slave_channel_compat(mask_in, |
1272 | atmel_sha_filter, &pdata->dma_slave->rxdata); | 1272 | atmel_sha_filter, &pdata->dma_slave->rxdata, dd->dev, "tx"); |
1273 | 1273 | if (!dd->dma_lch_in.chan) { | |
1274 | if (!dd->dma_lch_in.chan) | 1274 | dev_warn(dd->dev, "no DMA channel available\n"); |
1275 | return err; | 1275 | return err; |
1276 | |||
1277 | dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; | ||
1278 | dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + | ||
1279 | SHA_REG_DIN(0); | ||
1280 | dd->dma_lch_in.dma_conf.src_maxburst = 1; | ||
1281 | dd->dma_lch_in.dma_conf.src_addr_width = | ||
1282 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
1283 | dd->dma_lch_in.dma_conf.dst_maxburst = 1; | ||
1284 | dd->dma_lch_in.dma_conf.dst_addr_width = | ||
1285 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
1286 | dd->dma_lch_in.dma_conf.device_fc = false; | ||
1287 | |||
1288 | return 0; | ||
1289 | } | 1276 | } |
1290 | 1277 | ||
1291 | return -ENODEV; | 1278 | dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; |
1279 | dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + | ||
1280 | SHA_REG_DIN(0); | ||
1281 | dd->dma_lch_in.dma_conf.src_maxburst = 1; | ||
1282 | dd->dma_lch_in.dma_conf.src_addr_width = | ||
1283 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
1284 | dd->dma_lch_in.dma_conf.dst_maxburst = 1; | ||
1285 | dd->dma_lch_in.dma_conf.dst_addr_width = | ||
1286 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
1287 | dd->dma_lch_in.dma_conf.device_fc = false; | ||
1288 | |||
1289 | return 0; | ||
1292 | } | 1290 | } |
1293 | 1291 | ||
1294 | static void atmel_sha_dma_cleanup(struct atmel_sha_dev *dd) | 1292 | static void atmel_sha_dma_cleanup(struct atmel_sha_dev *dd) |
@@ -1326,6 +1324,48 @@ static void atmel_sha_get_cap(struct atmel_sha_dev *dd) | |||
1326 | } | 1324 | } |
1327 | } | 1325 | } |
1328 | 1326 | ||
1327 | #if defined(CONFIG_OF) | ||
1328 | static const struct of_device_id atmel_sha_dt_ids[] = { | ||
1329 | { .compatible = "atmel,at91sam9g46-sha" }, | ||
1330 | { /* sentinel */ } | ||
1331 | }; | ||
1332 | |||
1333 | MODULE_DEVICE_TABLE(of, atmel_sha_dt_ids); | ||
1334 | |||
1335 | static struct crypto_platform_data *atmel_sha_of_init(struct platform_device *pdev) | ||
1336 | { | ||
1337 | struct device_node *np = pdev->dev.of_node; | ||
1338 | struct crypto_platform_data *pdata; | ||
1339 | |||
1340 | if (!np) { | ||
1341 | dev_err(&pdev->dev, "device node not found\n"); | ||
1342 | return ERR_PTR(-EINVAL); | ||
1343 | } | ||
1344 | |||
1345 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
1346 | if (!pdata) { | ||
1347 | dev_err(&pdev->dev, "could not allocate memory for pdata\n"); | ||
1348 | return ERR_PTR(-ENOMEM); | ||
1349 | } | ||
1350 | |||
1351 | pdata->dma_slave = devm_kzalloc(&pdev->dev, | ||
1352 | sizeof(*(pdata->dma_slave)), | ||
1353 | GFP_KERNEL); | ||
1354 | if (!pdata->dma_slave) { | ||
1355 | dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); | ||
1356 | devm_kfree(&pdev->dev, pdata); | ||
1357 | return ERR_PTR(-ENOMEM); | ||
1358 | } | ||
1359 | |||
1360 | return pdata; | ||
1361 | } | ||
1362 | #else /* CONFIG_OF */ | ||
1363 | static inline struct crypto_platform_data *atmel_sha_of_init(struct platform_device *dev) | ||
1364 | { | ||
1365 | return ERR_PTR(-EINVAL); | ||
1366 | } | ||
1367 | #endif | ||
1368 | |||
1329 | static int atmel_sha_probe(struct platform_device *pdev) | 1369 | static int atmel_sha_probe(struct platform_device *pdev) |
1330 | { | 1370 | { |
1331 | struct atmel_sha_dev *sha_dd; | 1371 | struct atmel_sha_dev *sha_dd; |
@@ -1402,13 +1442,23 @@ static int atmel_sha_probe(struct platform_device *pdev) | |||
1402 | if (sha_dd->caps.has_dma) { | 1442 | if (sha_dd->caps.has_dma) { |
1403 | pdata = pdev->dev.platform_data; | 1443 | pdata = pdev->dev.platform_data; |
1404 | if (!pdata) { | 1444 | if (!pdata) { |
1405 | dev_err(&pdev->dev, "platform data not available\n"); | 1445 | pdata = atmel_sha_of_init(pdev); |
1446 | if (IS_ERR(pdata)) { | ||
1447 | dev_err(&pdev->dev, "platform data not available\n"); | ||
1448 | err = PTR_ERR(pdata); | ||
1449 | goto err_pdata; | ||
1450 | } | ||
1451 | } | ||
1452 | if (!pdata->dma_slave) { | ||
1406 | err = -ENXIO; | 1453 | err = -ENXIO; |
1407 | goto err_pdata; | 1454 | goto err_pdata; |
1408 | } | 1455 | } |
1409 | err = atmel_sha_dma_init(sha_dd, pdata); | 1456 | err = atmel_sha_dma_init(sha_dd, pdata); |
1410 | if (err) | 1457 | if (err) |
1411 | goto err_sha_dma; | 1458 | goto err_sha_dma; |
1459 | |||
1460 | dev_info(dev, "using %s for DMA transfers\n", | ||
1461 | dma_chan_name(sha_dd->dma_lch_in.chan)); | ||
1412 | } | 1462 | } |
1413 | 1463 | ||
1414 | spin_lock(&atmel_sha.lock); | 1464 | spin_lock(&atmel_sha.lock); |
@@ -1483,6 +1533,7 @@ static struct platform_driver atmel_sha_driver = { | |||
1483 | .driver = { | 1533 | .driver = { |
1484 | .name = "atmel_sha", | 1534 | .name = "atmel_sha", |
1485 | .owner = THIS_MODULE, | 1535 | .owner = THIS_MODULE, |
1536 | .of_match_table = of_match_ptr(atmel_sha_dt_ids), | ||
1486 | }, | 1537 | }, |
1487 | }; | 1538 | }; |
1488 | 1539 | ||