diff options
-rw-r--r-- | drivers/crypto/tegra-se.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/drivers/crypto/tegra-se.c b/drivers/crypto/tegra-se.c index a8287a786..e8daaabe5 100644 --- a/drivers/crypto/tegra-se.c +++ b/drivers/crypto/tegra-se.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/clk.h> | 28 | #include <linux/clk.h> |
29 | #include <linux/delay.h> | ||
29 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
30 | #include <linux/scatterlist.h> | 31 | #include <linux/scatterlist.h> |
31 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
@@ -38,6 +39,7 @@ | |||
38 | #include <linux/errno.h> | 39 | #include <linux/errno.h> |
39 | #include <soc/tegra/fuse.h> | 40 | #include <soc/tegra/fuse.h> |
40 | #include <soc/tegra/chip-id.h> | 41 | #include <soc/tegra/chip-id.h> |
42 | #include <soc/tegra/ahb.h> | ||
41 | #include <crypto/scatterwalk.h> | 43 | #include <crypto/scatterwalk.h> |
42 | #include <soc/tegra/pmc.h> | 44 | #include <soc/tegra/pmc.h> |
43 | #include <crypto/algapi.h> | 45 | #include <crypto/algapi.h> |
@@ -112,6 +114,7 @@ struct tegra_se_chipdata { | |||
112 | bool mccif_supported; | 114 | bool mccif_supported; |
113 | bool rsa_key_rw_op; | 115 | bool rsa_key_rw_op; |
114 | u32 aes_keydata_reg_sz; | 116 | u32 aes_keydata_reg_sz; |
117 | bool ahb_ack; | ||
115 | }; | 118 | }; |
116 | 119 | ||
117 | struct tegra_se_dev { | 120 | struct tegra_se_dev { |
@@ -141,6 +144,7 @@ struct tegra_se_dev { | |||
141 | bool work_q_busy; /* Work queue busy status */ | 144 | bool work_q_busy; /* Work queue busy status */ |
142 | bool polling; | 145 | bool polling; |
143 | struct tegra_se_chipdata *chipdata; /* chip specific data */ | 146 | struct tegra_se_chipdata *chipdata; /* chip specific data */ |
147 | u32 ahb_id; | ||
144 | }; | 148 | }; |
145 | 149 | ||
146 | static struct tegra_se_dev *sg_tegra_se_dev; | 150 | static struct tegra_se_dev *sg_tegra_se_dev; |
@@ -711,7 +715,7 @@ static int tegra_se_start_operation(struct tegra_se_dev *se_dev, u32 nbytes, | |||
711 | { | 715 | { |
712 | u32 nblocks = nbytes / TEGRA_SE_AES_BLOCK_SIZE; | 716 | u32 nblocks = nbytes / TEGRA_SE_AES_BLOCK_SIZE; |
713 | int ret = 0, err = 0; | 717 | int ret = 0, err = 0; |
714 | u32 val = 0; | 718 | u32 val = 0, timeout = TEGRA_SE_TIMEOUT_1S; |
715 | 719 | ||
716 | if ((tegra_get_chip_id() == TEGRA114) && | 720 | if ((tegra_get_chip_id() == TEGRA114) && |
717 | nblocks > SE_MAX_LAST_BLOCK_SIZE) | 721 | nblocks > SE_MAX_LAST_BLOCK_SIZE) |
@@ -754,6 +758,7 @@ static int tegra_se_start_operation(struct tegra_se_dev *se_dev, u32 nbytes, | |||
754 | if (!SE_OP_DONE(val, OP_DONE)) { | 758 | if (!SE_OP_DONE(val, OP_DONE)) { |
755 | dev_err(se_dev->dev, "\nAbrupt end of operation\n"); | 759 | dev_err(se_dev->dev, "\nAbrupt end of operation\n"); |
756 | err = -EINVAL; | 760 | err = -EINVAL; |
761 | goto exit; | ||
757 | } | 762 | } |
758 | } else { | 763 | } else { |
759 | ret = wait_for_completion_timeout(&se_dev->complete, | 764 | ret = wait_for_completion_timeout(&se_dev->complete, |
@@ -761,9 +766,37 @@ static int tegra_se_start_operation(struct tegra_se_dev *se_dev, u32 nbytes, | |||
761 | if (ret == 0) { | 766 | if (ret == 0) { |
762 | dev_err(se_dev->dev, "operation timed out no interrupt\n"); | 767 | dev_err(se_dev->dev, "operation timed out no interrupt\n"); |
763 | err = -ETIMEDOUT; | 768 | err = -ETIMEDOUT; |
769 | goto exit; | ||
770 | } | ||
771 | } | ||
772 | |||
773 | if (se_dev->chipdata->ahb_ack) { | ||
774 | /* Ensure data is out from SE using MEM_INTERFACE signal */ | ||
775 | val = se_readl(se_dev, SE_STATUS_REG_OFFSET); | ||
776 | while (val & SE_STATUS_MEM_INTERFACE(MEM_INTERFACE_BUSY)) { | ||
777 | if (!timeout) { | ||
778 | dev_err(se_dev->dev, "mem operation timeout\n"); | ||
779 | err = -ETIMEDOUT; | ||
780 | goto exit; | ||
781 | } | ||
782 | udelay(1); | ||
783 | timeout--; | ||
784 | val = se_readl(se_dev, SE_STATUS_REG_OFFSET); | ||
785 | } | ||
786 | |||
787 | timeout = TEGRA_SE_TIMEOUT_1S; | ||
788 | while (tegra_ahb_is_mem_wrque_busy(se_dev->ahb_id)) { | ||
789 | if (!timeout) { | ||
790 | dev_err(se_dev->dev, "mem operation timeout\n"); | ||
791 | err = -ETIMEDOUT; | ||
792 | goto exit; | ||
793 | } | ||
794 | udelay(1); | ||
795 | timeout--; | ||
764 | } | 796 | } |
765 | } | 797 | } |
766 | 798 | ||
799 | exit: | ||
767 | return err; | 800 | return err; |
768 | } | 801 | } |
769 | 802 | ||
@@ -2468,6 +2501,7 @@ static struct tegra_se_chipdata tegra_se_chipdata = { | |||
2468 | .mccif_supported = false, | 2501 | .mccif_supported = false, |
2469 | .rsa_key_rw_op = true, | 2502 | .rsa_key_rw_op = true, |
2470 | .aes_keydata_reg_sz = 128, | 2503 | .aes_keydata_reg_sz = 128, |
2504 | .ahb_ack = false, | ||
2471 | }; | 2505 | }; |
2472 | 2506 | ||
2473 | static struct tegra_se_chipdata tegra11_se_chipdata = { | 2507 | static struct tegra_se_chipdata tegra11_se_chipdata = { |
@@ -2486,6 +2520,7 @@ static struct tegra_se_chipdata tegra11_se_chipdata = { | |||
2486 | .mccif_supported = false, | 2520 | .mccif_supported = false, |
2487 | .rsa_key_rw_op = true, | 2521 | .rsa_key_rw_op = true, |
2488 | .aes_keydata_reg_sz = 128, | 2522 | .aes_keydata_reg_sz = 128, |
2523 | .ahb_ack = false, | ||
2489 | }; | 2524 | }; |
2490 | 2525 | ||
2491 | static struct tegra_se_chipdata tegra21_se_chipdata = { | 2526 | static struct tegra_se_chipdata tegra21_se_chipdata = { |
@@ -2504,6 +2539,26 @@ static struct tegra_se_chipdata tegra21_se_chipdata = { | |||
2504 | .mccif_supported = true, | 2539 | .mccif_supported = true, |
2505 | .rsa_key_rw_op = false, | 2540 | .rsa_key_rw_op = false, |
2506 | .aes_keydata_reg_sz = 32, | 2541 | .aes_keydata_reg_sz = 32, |
2542 | .ahb_ack = false, | ||
2543 | }; | ||
2544 | |||
2545 | static struct tegra_se_chipdata tegra210b01_se_chipdata = { | ||
2546 | .rsa_supported = true, | ||
2547 | .cprng_supported = false, | ||
2548 | .drbg_supported = true, | ||
2549 | .const_freq = true, | ||
2550 | .aes_freq = 510000000, | ||
2551 | .rng_freq = 510000000, | ||
2552 | .sha1_freq = 510000000, | ||
2553 | .sha224_freq = 510000000, | ||
2554 | .sha256_freq = 510000000, | ||
2555 | .sha384_freq = 510000000, | ||
2556 | .sha512_freq = 510000000, | ||
2557 | .rsa_freq = 510000000, | ||
2558 | .mccif_supported = true, | ||
2559 | .rsa_key_rw_op = false, | ||
2560 | .aes_keydata_reg_sz = 32, | ||
2561 | .ahb_ack = true, | ||
2507 | }; | 2562 | }; |
2508 | 2563 | ||
2509 | static struct of_device_id tegra_se_of_match[] = { | 2564 | static struct of_device_id tegra_se_of_match[] = { |
@@ -2514,6 +2569,10 @@ static struct of_device_id tegra_se_of_match[] = { | |||
2514 | { | 2569 | { |
2515 | .compatible = "nvidia,tegra210-se", | 2570 | .compatible = "nvidia,tegra210-se", |
2516 | .data = &tegra21_se_chipdata, | 2571 | .data = &tegra21_se_chipdata, |
2572 | }, | ||
2573 | { | ||
2574 | .compatible = "nvidia,tegra210b01-se", | ||
2575 | .data = &tegra210b01_se_chipdata, | ||
2517 | }, { | 2576 | }, { |
2518 | } | 2577 | } |
2519 | }; | 2578 | }; |
@@ -2550,6 +2609,16 @@ static int tegra_se_probe(struct platform_device *pdev) | |||
2550 | (struct tegra_se_chipdata *)pdev->id_entry->driver_data; | 2609 | (struct tegra_se_chipdata *)pdev->id_entry->driver_data; |
2551 | } | 2610 | } |
2552 | 2611 | ||
2612 | if (se_dev->chipdata->ahb_ack) { | ||
2613 | val = tegra_ahb_get_master_id(&pdev->dev); | ||
2614 | if (val < 0) { | ||
2615 | err = -EINVAL; | ||
2616 | dev_err(&pdev->dev, "Error: AHB master id not found\n"); | ||
2617 | goto fail; | ||
2618 | } else | ||
2619 | se_dev->ahb_id = val; | ||
2620 | } | ||
2621 | |||
2553 | spin_lock_init(&se_dev->lock); | 2622 | spin_lock_init(&se_dev->lock); |
2554 | crypto_init_queue(&se_dev->queue, TEGRA_SE_CRYPTO_QUEUE_LENGTH); | 2623 | crypto_init_queue(&se_dev->queue, TEGRA_SE_CRYPTO_QUEUE_LENGTH); |
2555 | platform_set_drvdata(pdev, se_dev); | 2624 | platform_set_drvdata(pdev, se_dev); |