| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * This file is part of STM32 Crypto driver for Linux. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2017, STMicroelectronics - All Rights Reserved |
|---|
| 5 | 6 | * Author(s): Lionel DEBIEVE <lionel.debieve@st.com> for STMicroelectronics. |
|---|
| 6 | | - * |
|---|
| 7 | | - * License terms: GPL V2.0. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 10 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 11 | | - * the Free Software Foundation. |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 14 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 15 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
|---|
| 16 | | - * details. |
|---|
| 17 | | - * |
|---|
| 18 | | - * You should have received a copy of the GNU General Public License along with |
|---|
| 19 | | - * this program. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 20 | | - * |
|---|
| 21 | 7 | */ |
|---|
| 22 | 8 | |
|---|
| 23 | 9 | #include <linux/clk.h> |
|---|
| 24 | 10 | #include <linux/crypto.h> |
|---|
| 25 | 11 | #include <linux/delay.h> |
|---|
| 12 | +#include <linux/dma-mapping.h> |
|---|
| 26 | 13 | #include <linux/dmaengine.h> |
|---|
| 27 | 14 | #include <linux/interrupt.h> |
|---|
| 28 | 15 | #include <linux/io.h> |
|---|
| .. | .. |
|---|
| 180 | 167 | phys_addr_t phys_base; |
|---|
| 181 | 168 | u32 dma_mode; |
|---|
| 182 | 169 | u32 dma_maxburst; |
|---|
| 183 | | - |
|---|
| 184 | | - spinlock_t lock; /* lock to protect queue */ |
|---|
| 185 | 170 | |
|---|
| 186 | 171 | struct ahash_request *req; |
|---|
| 187 | 172 | struct crypto_engine *engine; |
|---|
| .. | .. |
|---|
| 354 | 339 | |
|---|
| 355 | 340 | len32 = DIV_ROUND_UP(length, sizeof(u32)); |
|---|
| 356 | 341 | |
|---|
| 357 | | - dev_dbg(hdev->dev, "%s: length: %d, final: %x len32 %i\n", |
|---|
| 342 | + dev_dbg(hdev->dev, "%s: length: %zd, final: %x len32 %i\n", |
|---|
| 358 | 343 | __func__, length, final, len32); |
|---|
| 359 | 344 | |
|---|
| 360 | 345 | hdev->flags |= HASH_FLAGS_CPU; |
|---|
| .. | .. |
|---|
| 463 | 448 | |
|---|
| 464 | 449 | dma_async_issue_pending(hdev->dma_lch); |
|---|
| 465 | 450 | |
|---|
| 466 | | - if (!wait_for_completion_interruptible_timeout(&hdev->dma_completion, |
|---|
| 467 | | - msecs_to_jiffies(100))) |
|---|
| 451 | + if (!wait_for_completion_timeout(&hdev->dma_completion, |
|---|
| 452 | + msecs_to_jiffies(100))) |
|---|
| 468 | 453 | err = -ETIMEDOUT; |
|---|
| 469 | 454 | |
|---|
| 470 | 455 | if (dma_async_is_tx_complete(hdev->dma_lch, cookie, |
|---|
| .. | .. |
|---|
| 523 | 508 | static int stm32_hash_dma_init(struct stm32_hash_dev *hdev) |
|---|
| 524 | 509 | { |
|---|
| 525 | 510 | struct dma_slave_config dma_conf; |
|---|
| 511 | + struct dma_chan *chan; |
|---|
| 526 | 512 | int err; |
|---|
| 527 | 513 | |
|---|
| 528 | 514 | memset(&dma_conf, 0, sizeof(dma_conf)); |
|---|
| .. | .. |
|---|
| 534 | 520 | dma_conf.dst_maxburst = hdev->dma_maxburst; |
|---|
| 535 | 521 | dma_conf.device_fc = false; |
|---|
| 536 | 522 | |
|---|
| 537 | | - hdev->dma_lch = dma_request_slave_channel(hdev->dev, "in"); |
|---|
| 538 | | - if (!hdev->dma_lch) { |
|---|
| 539 | | - dev_err(hdev->dev, "Couldn't acquire a slave DMA channel.\n"); |
|---|
| 540 | | - return -EBUSY; |
|---|
| 541 | | - } |
|---|
| 523 | + chan = dma_request_chan(hdev->dev, "in"); |
|---|
| 524 | + if (IS_ERR(chan)) |
|---|
| 525 | + return PTR_ERR(chan); |
|---|
| 526 | + |
|---|
| 527 | + hdev->dma_lch = chan; |
|---|
| 542 | 528 | |
|---|
| 543 | 529 | err = dmaengine_slave_config(hdev->dma_lch, &dma_conf); |
|---|
| 544 | 530 | if (err) { |
|---|
| .. | .. |
|---|
| 578 | 564 | } |
|---|
| 579 | 565 | |
|---|
| 580 | 566 | for_each_sg(rctx->sg, tsg, rctx->nents, i) { |
|---|
| 567 | + sg[0] = *tsg; |
|---|
| 581 | 568 | len = sg->length; |
|---|
| 582 | 569 | |
|---|
| 583 | | - sg[0] = *tsg; |
|---|
| 584 | 570 | if (sg_is_last(sg)) { |
|---|
| 585 | 571 | if (hdev->dma_mode == 1) { |
|---|
| 586 | 572 | len = (ALIGN(sg->length, 16) - 16); |
|---|
| .. | .. |
|---|
| 763 | 749 | static void stm32_hash_copy_hash(struct ahash_request *req) |
|---|
| 764 | 750 | { |
|---|
| 765 | 751 | struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); |
|---|
| 766 | | - u32 *hash = (u32 *)rctx->digest; |
|---|
| 752 | + __be32 *hash = (void *)rctx->digest; |
|---|
| 767 | 753 | unsigned int i, hashsize; |
|---|
| 768 | 754 | |
|---|
| 769 | 755 | switch (rctx->flags & HASH_FLAGS_ALGO_MASK) { |
|---|
| .. | .. |
|---|
| 784 | 770 | } |
|---|
| 785 | 771 | |
|---|
| 786 | 772 | for (i = 0; i < hashsize / sizeof(u32); i++) |
|---|
| 787 | | - hash[i] = be32_to_cpu(stm32_hash_read(rctx->hdev, |
|---|
| 773 | + hash[i] = cpu_to_be32(stm32_hash_read(rctx->hdev, |
|---|
| 788 | 774 | HASH_HREG(i))); |
|---|
| 789 | 775 | } |
|---|
| 790 | 776 | |
|---|
| .. | .. |
|---|
| 977 | 963 | |
|---|
| 978 | 964 | pm_runtime_get_sync(hdev->dev); |
|---|
| 979 | 965 | |
|---|
| 980 | | - while (!(stm32_hash_read(hdev, HASH_SR) & HASH_SR_DATA_INPUT_READY)) |
|---|
| 966 | + while ((stm32_hash_read(hdev, HASH_SR) & HASH_SR_BUSY)) |
|---|
| 981 | 967 | cpu_relax(); |
|---|
| 982 | 968 | |
|---|
| 983 | 969 | rctx->hw_context = kmalloc_array(3 + HASH_CSR_REGISTER_NUMBER, |
|---|
| .. | .. |
|---|
| 1466 | 1452 | return ret; |
|---|
| 1467 | 1453 | |
|---|
| 1468 | 1454 | irq = platform_get_irq(pdev, 0); |
|---|
| 1469 | | - if (irq < 0) { |
|---|
| 1470 | | - dev_err(dev, "Cannot get IRQ resource\n"); |
|---|
| 1455 | + if (irq < 0) |
|---|
| 1471 | 1456 | return irq; |
|---|
| 1472 | | - } |
|---|
| 1473 | 1457 | |
|---|
| 1474 | 1458 | ret = devm_request_threaded_irq(dev, irq, stm32_hash_irq_handler, |
|---|
| 1475 | 1459 | stm32_hash_irq_thread, IRQF_ONESHOT, |
|---|
| .. | .. |
|---|
| 1480 | 1464 | } |
|---|
| 1481 | 1465 | |
|---|
| 1482 | 1466 | hdev->clk = devm_clk_get(&pdev->dev, NULL); |
|---|
| 1483 | | - if (IS_ERR(hdev->clk)) { |
|---|
| 1484 | | - dev_err(dev, "failed to get clock for hash (%lu)\n", |
|---|
| 1485 | | - PTR_ERR(hdev->clk)); |
|---|
| 1486 | | - return PTR_ERR(hdev->clk); |
|---|
| 1487 | | - } |
|---|
| 1467 | + if (IS_ERR(hdev->clk)) |
|---|
| 1468 | + return dev_err_probe(dev, PTR_ERR(hdev->clk), |
|---|
| 1469 | + "failed to get clock for hash\n"); |
|---|
| 1488 | 1470 | |
|---|
| 1489 | 1471 | ret = clk_prepare_enable(hdev->clk); |
|---|
| 1490 | 1472 | if (ret) { |
|---|
| .. | .. |
|---|
| 1500 | 1482 | pm_runtime_enable(dev); |
|---|
| 1501 | 1483 | |
|---|
| 1502 | 1484 | hdev->rst = devm_reset_control_get(&pdev->dev, NULL); |
|---|
| 1503 | | - if (!IS_ERR(hdev->rst)) { |
|---|
| 1485 | + if (IS_ERR(hdev->rst)) { |
|---|
| 1486 | + if (PTR_ERR(hdev->rst) == -EPROBE_DEFER) { |
|---|
| 1487 | + ret = -EPROBE_DEFER; |
|---|
| 1488 | + goto err_reset; |
|---|
| 1489 | + } |
|---|
| 1490 | + } else { |
|---|
| 1504 | 1491 | reset_control_assert(hdev->rst); |
|---|
| 1505 | 1492 | udelay(2); |
|---|
| 1506 | 1493 | reset_control_deassert(hdev->rst); |
|---|
| .. | .. |
|---|
| 1511 | 1498 | platform_set_drvdata(pdev, hdev); |
|---|
| 1512 | 1499 | |
|---|
| 1513 | 1500 | ret = stm32_hash_dma_init(hdev); |
|---|
| 1514 | | - if (ret) |
|---|
| 1501 | + switch (ret) { |
|---|
| 1502 | + case 0: |
|---|
| 1503 | + break; |
|---|
| 1504 | + case -ENOENT: |
|---|
| 1515 | 1505 | dev_dbg(dev, "DMA mode not available\n"); |
|---|
| 1506 | + break; |
|---|
| 1507 | + default: |
|---|
| 1508 | + goto err_dma; |
|---|
| 1509 | + } |
|---|
| 1516 | 1510 | |
|---|
| 1517 | 1511 | spin_lock(&stm32_hash.lock); |
|---|
| 1518 | 1512 | list_add_tail(&hdev->list, &stm32_hash.dev_list); |
|---|
| .. | .. |
|---|
| 1550 | 1544 | spin_lock(&stm32_hash.lock); |
|---|
| 1551 | 1545 | list_del(&hdev->list); |
|---|
| 1552 | 1546 | spin_unlock(&stm32_hash.lock); |
|---|
| 1553 | | - |
|---|
| 1547 | +err_dma: |
|---|
| 1554 | 1548 | if (hdev->dma_lch) |
|---|
| 1555 | 1549 | dma_release_channel(hdev->dma_lch); |
|---|
| 1556 | | - |
|---|
| 1550 | +err_reset: |
|---|
| 1557 | 1551 | pm_runtime_disable(dev); |
|---|
| 1558 | 1552 | pm_runtime_put_noidle(dev); |
|---|
| 1559 | 1553 | |
|---|
| .. | .. |
|---|
| 1564 | 1558 | |
|---|
| 1565 | 1559 | static int stm32_hash_remove(struct platform_device *pdev) |
|---|
| 1566 | 1560 | { |
|---|
| 1567 | | - static struct stm32_hash_dev *hdev; |
|---|
| 1561 | + struct stm32_hash_dev *hdev; |
|---|
| 1568 | 1562 | int ret; |
|---|
| 1569 | 1563 | |
|---|
| 1570 | 1564 | hdev = platform_get_drvdata(pdev); |
|---|
| .. | .. |
|---|
| 1572 | 1566 | return -ENODEV; |
|---|
| 1573 | 1567 | |
|---|
| 1574 | 1568 | ret = pm_runtime_get_sync(hdev->dev); |
|---|
| 1575 | | - if (ret < 0) |
|---|
| 1576 | | - return ret; |
|---|
| 1577 | 1569 | |
|---|
| 1578 | 1570 | stm32_hash_unregister_algs(hdev); |
|---|
| 1579 | 1571 | |
|---|
| .. | .. |
|---|
| 1589 | 1581 | pm_runtime_disable(hdev->dev); |
|---|
| 1590 | 1582 | pm_runtime_put_noidle(hdev->dev); |
|---|
| 1591 | 1583 | |
|---|
| 1592 | | - clk_disable_unprepare(hdev->clk); |
|---|
| 1584 | + if (ret >= 0) |
|---|
| 1585 | + clk_disable_unprepare(hdev->clk); |
|---|
| 1593 | 1586 | |
|---|
| 1594 | 1587 | return 0; |
|---|
| 1595 | 1588 | } |
|---|