Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: atmel-sha - 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>

+97 -24
+22
Documentation/devicetree/bindings/crypto/atmel-crypto.txt
··· 44 44 <&dma1 2 21>; 45 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 + };
+75 -24
drivers/crypto/atmel-sha.c
··· 30 30 #include <linux/irq.h> 31 31 #include <linux/scatterlist.h> 32 32 #include <linux/dma-mapping.h> 33 + #include <linux/of_device.h> 33 34 #include <linux/delay.h> 34 35 #include <linux/crypto.h> 35 36 #include <linux/cryptohash.h> ··· 1264 1263 int err = -ENOMEM; 1265 1264 dma_cap_mask_t mask_in; 1266 1265 1267 - if (pdata && pdata->dma_slave->rxdata.dma_dev) { 1268 - /* Try to grab DMA channel */ 1269 - dma_cap_zero(mask_in); 1270 - dma_cap_set(DMA_SLAVE, mask_in); 1266 + /* Try to grab DMA channel */ 1267 + dma_cap_zero(mask_in); 1268 + dma_cap_set(DMA_SLAVE, mask_in); 1271 1269 1272 - dd->dma_lch_in.chan = dma_request_channel(mask_in, 1273 - atmel_sha_filter, &pdata->dma_slave->rxdata); 1274 - 1275 - if (!dd->dma_lch_in.chan) 1276 - return err; 1277 - 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; 1270 + dd->dma_lch_in.chan = dma_request_slave_channel_compat(mask_in, 1271 + atmel_sha_filter, &pdata->dma_slave->rxdata, dd->dev, "tx"); 1272 + if (!dd->dma_lch_in.chan) { 1273 + dev_warn(dd->dev, "no DMA channel available\n"); 1274 + return err; 1290 1275 } 1291 1276 1292 - return -ENODEV; 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; 1293 1289 } 1294 1290 1295 1291 static void atmel_sha_dma_cleanup(struct atmel_sha_dev *dd) ··· 1323 1325 break; 1324 1326 } 1325 1327 } 1328 + 1329 + #if defined(CONFIG_OF) 1330 + static const struct of_device_id atmel_sha_dt_ids[] = { 1331 + { .compatible = "atmel,at91sam9g46-sha" }, 1332 + { /* sentinel */ } 1333 + }; 1334 + 1335 + MODULE_DEVICE_TABLE(of, atmel_sha_dt_ids); 1336 + 1337 + static struct crypto_platform_data *atmel_sha_of_init(struct platform_device *pdev) 1338 + { 1339 + struct device_node *np = pdev->dev.of_node; 1340 + struct crypto_platform_data *pdata; 1341 + 1342 + if (!np) { 1343 + dev_err(&pdev->dev, "device node not found\n"); 1344 + return ERR_PTR(-EINVAL); 1345 + } 1346 + 1347 + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 1348 + if (!pdata) { 1349 + dev_err(&pdev->dev, "could not allocate memory for pdata\n"); 1350 + return ERR_PTR(-ENOMEM); 1351 + } 1352 + 1353 + pdata->dma_slave = devm_kzalloc(&pdev->dev, 1354 + sizeof(*(pdata->dma_slave)), 1355 + GFP_KERNEL); 1356 + if (!pdata->dma_slave) { 1357 + dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); 1358 + devm_kfree(&pdev->dev, pdata); 1359 + return ERR_PTR(-ENOMEM); 1360 + } 1361 + 1362 + return pdata; 1363 + } 1364 + #else /* CONFIG_OF */ 1365 + static inline struct crypto_platform_data *atmel_sha_of_init(struct platform_device *dev) 1366 + { 1367 + return ERR_PTR(-EINVAL); 1368 + } 1369 + #endif 1326 1370 1327 1371 static int atmel_sha_probe(struct platform_device *pdev) 1328 1372 { ··· 1442 1402 if (sha_dd->caps.has_dma) { 1443 1403 pdata = pdev->dev.platform_data; 1444 1404 if (!pdata) { 1445 - dev_err(&pdev->dev, "platform data not available\n"); 1405 + pdata = atmel_sha_of_init(pdev); 1406 + if (IS_ERR(pdata)) { 1407 + dev_err(&pdev->dev, "platform data not available\n"); 1408 + err = PTR_ERR(pdata); 1409 + goto err_pdata; 1410 + } 1411 + } 1412 + if (!pdata->dma_slave) { 1446 1413 err = -ENXIO; 1447 1414 goto err_pdata; 1448 1415 } 1449 1416 err = atmel_sha_dma_init(sha_dd, pdata); 1450 1417 if (err) 1451 1418 goto err_sha_dma; 1419 + 1420 + dev_info(dev, "using %s for DMA transfers\n", 1421 + dma_chan_name(sha_dd->dma_lch_in.chan)); 1452 1422 } 1453 1423 1454 1424 spin_lock(&atmel_sha.lock); ··· 1533 1483 .driver = { 1534 1484 .name = "atmel_sha", 1535 1485 .owner = THIS_MODULE, 1486 + .of_match_table = of_match_ptr(atmel_sha_dt_ids), 1536 1487 }, 1537 1488 }; 1538 1489