for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { if (!ss_algs[i].ss) continue; switch (ss_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER:
seq_printf(seq, "%s %s reqs=%lu opti=%lu fallback=%lu tsize=%lu\n",
ss_algs[i].alg.crypto.base.cra_driver_name,
ss_algs[i].alg.crypto.base.cra_name,
ss_algs[i].stat_req, ss_algs[i].stat_opti, ss_algs[i].stat_fb,
ss_algs[i].stat_bytes); break; case CRYPTO_ALG_TYPE_RNG:
seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n",
ss_algs[i].alg.rng.base.cra_driver_name,
ss_algs[i].alg.rng.base.cra_name,
ss_algs[i].stat_req, ss_algs[i].stat_bytes); break; case CRYPTO_ALG_TYPE_AHASH:
seq_printf(seq, "%s %s reqs=%lu\n",
ss_algs[i].alg.hash.halg.base.cra_driver_name,
ss_algs[i].alg.hash.halg.base.cra_name,
ss_algs[i].stat_req); break;
}
} return 0;
}
DEFINE_SHOW_ATTRIBUTE(sun4i_ss_debugfs);
/* * Power management strategy: The device is suspended unless a TFM exists for * one of the algorithms proposed by this driver.
*/ staticint sun4i_ss_pm_suspend(struct device *dev)
{ struct sun4i_ss_ctx *ss = dev_get_drvdata(dev);
/* * When power management is enabled, this function enables the PM and set the * device as suspended * When power management is disabled, this function just enables the device
*/ staticint sun4i_ss_pm_init(struct sun4i_ss_ctx *ss)
{ int err;
ss->variant = of_device_get_match_data(&pdev->dev); if (!ss->variant) {
dev_err(&pdev->dev, "Missing Security System variant\n"); return -EINVAL;
}
ss->ssclk = devm_clk_get(&pdev->dev, "mod"); if (IS_ERR(ss->ssclk)) {
err = PTR_ERR(ss->ssclk);
dev_err(&pdev->dev, "Cannot get SS clock err=%d\n", err); return err;
}
dev_dbg(&pdev->dev, "clock ss acquired\n");
ss->busclk = devm_clk_get(&pdev->dev, "ahb"); if (IS_ERR(ss->busclk)) {
err = PTR_ERR(ss->busclk);
dev_err(&pdev->dev, "Cannot get AHB SS clock err=%d\n", err); return err;
}
dev_dbg(&pdev->dev, "clock ahb_ss acquired\n");
ss->reset = devm_reset_control_get_optional(&pdev->dev, "ahb"); if (IS_ERR(ss->reset)) return PTR_ERR(ss->reset); if (!ss->reset)
dev_info(&pdev->dev, "no reset control found\n");
/* * Check that clock have the correct rates given in the datasheet * Try to set the clock to the maximum allowed
*/
err = clk_set_rate(ss->ssclk, cr_mod); if (err) {
dev_err(&pdev->dev, "Cannot set clock rate to ssclk\n"); return err;
}
/* * The only impact on clocks below requirement are bad performance, * so do not print "errors" * warn on Overclocked clocks
*/
cr = clk_get_rate(ss->busclk); if (cr >= cr_ahb)
dev_dbg(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
cr, cr / 1000000, cr_ahb); else
dev_warn(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
cr, cr / 1000000, cr_ahb);
cr = clk_get_rate(ss->ssclk); if (cr <= cr_mod) if (cr < cr_mod)
dev_warn(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
cr, cr / 1000000, cr_mod); else
dev_dbg(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
cr, cr / 1000000, cr_mod); else
dev_warn(&pdev->dev, "Clock ss is at %lu (%lu MHz) (must be <= %lu)\n",
cr, cr / 1000000, cr_mod);
/* * Datasheet named it "Die Bonding ID" * I expect to be a sort of Security System Revision number. * Since the A80 seems to have an other version of SS * this info could be useful
*/
err = pm_runtime_resume_and_get(ss->dev); if (err < 0) goto error_pm;
writel(SS_ENABLED, ss->base + SS_CTL);
v = readl(ss->base + SS_CTL);
v >>= 16;
v &= 0x07;
dev_info(&pdev->dev, "Die ID %d\n", v);
writel(0, ss->base + SS_CTL);
pm_runtime_put_sync(ss->dev);
for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
ss_algs[i].ss = ss; switch (ss_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER:
err = crypto_register_skcipher(&ss_algs[i].alg.crypto); if (err) {
dev_err(ss->dev, "Fail to register %s\n",
ss_algs[i].alg.crypto.base.cra_name); goto error_alg;
} break; case CRYPTO_ALG_TYPE_AHASH:
err = crypto_register_ahash(&ss_algs[i].alg.hash); if (err) {
dev_err(ss->dev, "Fail to register %s\n",
ss_algs[i].alg.hash.halg.base.cra_name); goto error_alg;
} break; case CRYPTO_ALG_TYPE_RNG:
err = crypto_register_rng(&ss_algs[i].alg.rng); if (err) {
dev_err(ss->dev, "Fail to register %s\n",
ss_algs[i].alg.rng.base.cra_name);
} break;
}
}
for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { switch (ss_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER:
crypto_unregister_skcipher(&ss_algs[i].alg.crypto); break; case CRYPTO_ALG_TYPE_AHASH:
crypto_unregister_ahash(&ss_algs[i].alg.hash); break; case CRYPTO_ALG_TYPE_RNG:
crypto_unregister_rng(&ss_algs[i].alg.rng); break;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.