Lines Matching full:ss
3 * sun8i-ss-core.c - hardware cryptographic offloader for
30 #include "sun8i-ss.h"
62 int sun8i_ss_get_engine_number(struct sun8i_ss_dev *ss) in sun8i_ss_get_engine_number() argument
64 return atomic_inc_return(&ss->flow) % MAXFLOW; in sun8i_ss_get_engine_number()
67 int sun8i_ss_run_task(struct sun8i_ss_dev *ss, struct sun8i_cipher_req_ctx *rctx, in sun8i_ss_run_task() argument
76 ss->flows[flow].stat_req++; in sun8i_ss_run_task()
107 mutex_lock(&ss->mlock); in sun8i_ss_run_task()
108 writel(rctx->p_key, ss->base + SS_KEY_ADR_REG); in sun8i_ss_run_task()
113 writel(rctx->p_iv[0], ss->base + SS_IV_ADR_REG); in sun8i_ss_run_task()
115 writel(rctx->t_dst[i - 1].addr + rctx->t_dst[i - 1].len * 4 - ivlen, ss->base + SS_IV_ADR_REG); in sun8i_ss_run_task()
117 writel(rctx->p_iv[i], ss->base + SS_IV_ADR_REG); in sun8i_ss_run_task()
121 dev_dbg(ss->dev, in sun8i_ss_run_task()
128 writel(rctx->t_src[i].addr, ss->base + SS_SRC_ADR_REG); in sun8i_ss_run_task()
129 writel(rctx->t_dst[i].addr, ss->base + SS_DST_ADR_REG); in sun8i_ss_run_task()
130 writel(rctx->t_src[i].len, ss->base + SS_LEN_ADR_REG); in sun8i_ss_run_task()
132 reinit_completion(&ss->flows[flow].complete); in sun8i_ss_run_task()
133 ss->flows[flow].status = 0; in sun8i_ss_run_task()
136 writel(v, ss->base + SS_CTL_REG); in sun8i_ss_run_task()
137 mutex_unlock(&ss->mlock); in sun8i_ss_run_task()
138 wait_for_completion_interruptible_timeout(&ss->flows[flow].complete, in sun8i_ss_run_task()
140 if (ss->flows[flow].status == 0) { in sun8i_ss_run_task()
141 dev_err(ss->dev, "DMA timeout for %s\n", name); in sun8i_ss_run_task()
151 struct sun8i_ss_dev *ss = (struct sun8i_ss_dev *)data; in ss_irq_handler() local
155 p = readl(ss->base + SS_INT_STA_REG); in ss_irq_handler()
158 writel(BIT(flow), ss->base + SS_INT_STA_REG); in ss_irq_handler()
159 ss->flows[flow].status = 1; in ss_irq_handler()
160 complete(&ss->flows[flow].complete); in ss_irq_handler()
175 .cra_driver_name = "cbc-aes-sun8i-ss",
205 .cra_driver_name = "ecb-aes-sun8i-ss",
234 .cra_driver_name = "cbc-des3-sun8i-ss",
264 .cra_driver_name = "ecb-des3-sun8i-ss",
292 .cra_driver_name = "sun8i-ss-prng",
323 .cra_driver_name = "md5-sun8i-ss",
355 .cra_driver_name = "sha1-sun8i-ss",
387 .cra_driver_name = "sha224-sun8i-ss",
419 .cra_driver_name = "sha256-sun8i-ss",
452 .cra_driver_name = "hmac-sha1-sun8i-ss",
472 struct sun8i_ss_dev *ss __maybe_unused = seq->private; in sun8i_ss_debugfs_show()
478 ss->flows[i].stat_req); in sun8i_ss_debugfs_show()
484 if (!ss_algs[i].ss) in sun8i_ss_debugfs_show()
533 static void sun8i_ss_free_flows(struct sun8i_ss_dev *ss, int i) in sun8i_ss_free_flows() argument
536 crypto_engine_exit(ss->flows[i].engine); in sun8i_ss_free_flows()
544 static int allocate_flows(struct sun8i_ss_dev *ss) in allocate_flows() argument
548 ss->flows = devm_kcalloc(ss->dev, MAXFLOW, sizeof(struct sun8i_ss_flow), in allocate_flows()
550 if (!ss->flows) in allocate_flows()
554 init_completion(&ss->flows[i].complete); in allocate_flows()
556 ss->flows[i].biv = devm_kmalloc(ss->dev, AES_BLOCK_SIZE, in allocate_flows()
558 if (!ss->flows[i].biv) { in allocate_flows()
564 ss->flows[i].iv[j] = devm_kmalloc(ss->dev, AES_BLOCK_SIZE, in allocate_flows()
566 if (!ss->flows[i].iv[j]) { in allocate_flows()
573 ss->flows[i].pad = devm_kmalloc(ss->dev, MAX_PAD_SIZE, in allocate_flows()
575 if (!ss->flows[i].pad) { in allocate_flows()
579 ss->flows[i].result = in allocate_flows()
580 devm_kmalloc(ss->dev, max(SHA256_DIGEST_SIZE, in allocate_flows()
583 if (!ss->flows[i].result) { in allocate_flows()
588 ss->flows[i].engine = crypto_engine_alloc_init(ss->dev, true); in allocate_flows()
589 if (!ss->flows[i].engine) { in allocate_flows()
590 dev_err(ss->dev, "Cannot allocate engine\n"); in allocate_flows()
595 err = crypto_engine_start(ss->flows[i].engine); in allocate_flows()
597 dev_err(ss->dev, "Cannot start engine\n"); in allocate_flows()
603 sun8i_ss_free_flows(ss, i); in allocate_flows()
613 struct sun8i_ss_dev *ss = dev_get_drvdata(dev); in sun8i_ss_pm_suspend() local
616 reset_control_assert(ss->reset); in sun8i_ss_pm_suspend()
618 clk_disable_unprepare(ss->ssclks[i]); in sun8i_ss_pm_suspend()
624 struct sun8i_ss_dev *ss = dev_get_drvdata(dev); in sun8i_ss_pm_resume() local
628 if (!ss->variant->ss_clks[i].name) in sun8i_ss_pm_resume()
630 err = clk_prepare_enable(ss->ssclks[i]); in sun8i_ss_pm_resume()
632 dev_err(ss->dev, "Cannot prepare_enable %s\n", in sun8i_ss_pm_resume()
633 ss->variant->ss_clks[i].name); in sun8i_ss_pm_resume()
637 err = reset_control_deassert(ss->reset); in sun8i_ss_pm_resume()
639 dev_err(ss->dev, "Cannot deassert reset control\n"); in sun8i_ss_pm_resume()
643 writel(BIT(0) | BIT(1), ss->base + SS_INT_CTL_REG); in sun8i_ss_pm_resume()
655 static int sun8i_ss_pm_init(struct sun8i_ss_dev *ss) in sun8i_ss_pm_init() argument
659 pm_runtime_use_autosuspend(ss->dev); in sun8i_ss_pm_init()
660 pm_runtime_set_autosuspend_delay(ss->dev, 2000); in sun8i_ss_pm_init()
662 err = pm_runtime_set_suspended(ss->dev); in sun8i_ss_pm_init()
665 pm_runtime_enable(ss->dev); in sun8i_ss_pm_init()
669 static void sun8i_ss_pm_exit(struct sun8i_ss_dev *ss) in sun8i_ss_pm_exit() argument
671 pm_runtime_disable(ss->dev); in sun8i_ss_pm_exit()
674 static int sun8i_ss_register_algs(struct sun8i_ss_dev *ss) in sun8i_ss_register_algs() argument
680 ss_algs[i].ss = ss; in sun8i_ss_register_algs()
684 ss_method = ss->variant->alg_cipher[id]; in sun8i_ss_register_algs()
686 dev_info(ss->dev, in sun8i_ss_register_algs()
689 ss_algs[i].ss = NULL; in sun8i_ss_register_algs()
693 ss_method = ss->variant->op_mode[id]; in sun8i_ss_register_algs()
695 dev_info(ss->dev, "DEBUG: Blockmode of %s not supported\n", in sun8i_ss_register_algs()
697 ss_algs[i].ss = NULL; in sun8i_ss_register_algs()
700 dev_info(ss->dev, "DEBUG: Register %s\n", in sun8i_ss_register_algs()
704 dev_err(ss->dev, "Fail to register %s\n", in sun8i_ss_register_algs()
706 ss_algs[i].ss = NULL; in sun8i_ss_register_algs()
713 dev_err(ss->dev, "Fail to register %s\n", in sun8i_ss_register_algs()
715 ss_algs[i].ss = NULL; in sun8i_ss_register_algs()
720 ss_method = ss->variant->alg_hash[id]; in sun8i_ss_register_algs()
722 dev_info(ss->dev, in sun8i_ss_register_algs()
725 ss_algs[i].ss = NULL; in sun8i_ss_register_algs()
728 dev_info(ss->dev, "Register %s\n", in sun8i_ss_register_algs()
732 dev_err(ss->dev, "ERROR: Fail to register %s\n", in sun8i_ss_register_algs()
734 ss_algs[i].ss = NULL; in sun8i_ss_register_algs()
739 ss_algs[i].ss = NULL; in sun8i_ss_register_algs()
740 dev_err(ss->dev, "ERROR: tried to register an unknown algo\n"); in sun8i_ss_register_algs()
746 static void sun8i_ss_unregister_algs(struct sun8i_ss_dev *ss) in sun8i_ss_unregister_algs() argument
751 if (!ss_algs[i].ss) in sun8i_ss_unregister_algs()
755 dev_info(ss->dev, "Unregister %d %s\n", i, in sun8i_ss_unregister_algs()
760 dev_info(ss->dev, "Unregister %d %s\n", i, in sun8i_ss_unregister_algs()
765 dev_info(ss->dev, "Unregister %d %s\n", i, in sun8i_ss_unregister_algs()
773 static int sun8i_ss_get_clks(struct sun8i_ss_dev *ss) in sun8i_ss_get_clks() argument
779 if (!ss->variant->ss_clks[i].name) in sun8i_ss_get_clks()
781 ss->ssclks[i] = devm_clk_get(ss->dev, ss->variant->ss_clks[i].name); in sun8i_ss_get_clks()
782 if (IS_ERR(ss->ssclks[i])) { in sun8i_ss_get_clks()
783 err = PTR_ERR(ss->ssclks[i]); in sun8i_ss_get_clks()
784 dev_err(ss->dev, "Cannot get %s SS clock err=%d\n", in sun8i_ss_get_clks()
785 ss->variant->ss_clks[i].name, err); in sun8i_ss_get_clks()
788 cr = clk_get_rate(ss->ssclks[i]); in sun8i_ss_get_clks()
791 if (ss->variant->ss_clks[i].freq > 0 && in sun8i_ss_get_clks()
792 cr != ss->variant->ss_clks[i].freq) { in sun8i_ss_get_clks()
793 dev_info(ss->dev, "Set %s clock to %lu (%lu Mhz) from %lu (%lu Mhz)\n", in sun8i_ss_get_clks()
794 ss->variant->ss_clks[i].name, in sun8i_ss_get_clks()
795 ss->variant->ss_clks[i].freq, in sun8i_ss_get_clks()
796 ss->variant->ss_clks[i].freq / 1000000, in sun8i_ss_get_clks()
798 err = clk_set_rate(ss->ssclks[i], ss->variant->ss_clks[i].freq); in sun8i_ss_get_clks()
800 dev_err(ss->dev, "Fail to set %s clk speed to %lu hz\n", in sun8i_ss_get_clks()
801 ss->variant->ss_clks[i].name, in sun8i_ss_get_clks()
802 ss->variant->ss_clks[i].freq); in sun8i_ss_get_clks()
804 if (ss->variant->ss_clks[i].max_freq > 0 && in sun8i_ss_get_clks()
805 cr > ss->variant->ss_clks[i].max_freq) in sun8i_ss_get_clks()
806 dev_warn(ss->dev, "Frequency for %s (%lu hz) is higher than datasheet's recommendation (%lu hz)", in sun8i_ss_get_clks()
807 ss->variant->ss_clks[i].name, cr, in sun8i_ss_get_clks()
808 ss->variant->ss_clks[i].max_freq); in sun8i_ss_get_clks()
815 struct sun8i_ss_dev *ss; in sun8i_ss_probe() local
819 ss = devm_kzalloc(&pdev->dev, sizeof(*ss), GFP_KERNEL); in sun8i_ss_probe()
820 if (!ss) in sun8i_ss_probe()
823 ss->dev = &pdev->dev; in sun8i_ss_probe()
824 platform_set_drvdata(pdev, ss); in sun8i_ss_probe()
826 ss->variant = of_device_get_match_data(&pdev->dev); in sun8i_ss_probe()
827 if (!ss->variant) { in sun8i_ss_probe()
832 ss->base = devm_platform_ioremap_resource(pdev, 0); in sun8i_ss_probe()
833 if (IS_ERR(ss->base)) in sun8i_ss_probe()
834 return PTR_ERR(ss->base); in sun8i_ss_probe()
836 err = sun8i_ss_get_clks(ss); in sun8i_ss_probe()
844 ss->reset = devm_reset_control_get(&pdev->dev, NULL); in sun8i_ss_probe()
845 if (IS_ERR(ss->reset)) in sun8i_ss_probe()
846 return dev_err_probe(&pdev->dev, PTR_ERR(ss->reset), in sun8i_ss_probe()
849 mutex_init(&ss->mlock); in sun8i_ss_probe()
851 err = allocate_flows(ss); in sun8i_ss_probe()
855 err = sun8i_ss_pm_init(ss); in sun8i_ss_probe()
859 err = devm_request_irq(&pdev->dev, irq, ss_irq_handler, 0, "sun8i-ss", ss); in sun8i_ss_probe()
861 dev_err(ss->dev, "Cannot request SecuritySystem IRQ (err=%d)\n", err); in sun8i_ss_probe()
865 err = sun8i_ss_register_algs(ss); in sun8i_ss_probe()
869 err = pm_runtime_resume_and_get(ss->dev); in sun8i_ss_probe()
873 v = readl(ss->base + SS_CTL_REG); in sun8i_ss_probe()
878 pm_runtime_put_sync(ss->dev); in sun8i_ss_probe()
885 dbgfs_dir = debugfs_create_dir("sun8i-ss", NULL); in sun8i_ss_probe()
887 dbgfs_dir, ss, in sun8i_ss_probe()
891 ss->dbgfs_dir = dbgfs_dir; in sun8i_ss_probe()
892 ss->dbgfs_stats = dbgfs_stats; in sun8i_ss_probe()
898 sun8i_ss_unregister_algs(ss); in sun8i_ss_probe()
900 sun8i_ss_pm_exit(ss); in sun8i_ss_probe()
902 sun8i_ss_free_flows(ss, MAXFLOW - 1); in sun8i_ss_probe()
908 struct sun8i_ss_dev *ss = platform_get_drvdata(pdev); in sun8i_ss_remove() local
910 sun8i_ss_unregister_algs(ss); in sun8i_ss_remove()
913 debugfs_remove_recursive(ss->dbgfs_dir); in sun8i_ss_remove()
916 sun8i_ss_free_flows(ss, MAXFLOW - 1); in sun8i_ss_remove()
918 sun8i_ss_pm_exit(ss); in sun8i_ss_remove()
934 .name = "sun8i-ss",