Path: blob/master/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
29537 views
// SPDX-License-Identifier: GPL-2.01/*2* sun8i-ce-core.c - hardware cryptographic offloader for3* Allwinner H3/A64/H5/H2+/H6/R40 SoC4*5* Copyright (C) 2015-2019 Corentin Labbe <[email protected]>6*7* Core file which registers crypto algorithms supported by the CryptoEngine.8*9* You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst10*/1112#include <crypto/engine.h>13#include <crypto/internal/hash.h>14#include <crypto/internal/rng.h>15#include <crypto/internal/skcipher.h>16#include <linux/clk.h>17#include <linux/delay.h>18#include <linux/dma-mapping.h>19#include <linux/err.h>20#include <linux/interrupt.h>21#include <linux/io.h>22#include <linux/irq.h>23#include <linux/kernel.h>24#include <linux/module.h>25#include <linux/of.h>26#include <linux/platform_device.h>27#include <linux/pm_runtime.h>28#include <linux/reset.h>2930#include "sun8i-ce.h"3132/*33* mod clock is lower on H3 than other SoC due to some DMA timeout occurring34* with high value.35* If you want to tune mod clock, loading driver and passing selftest is36* insufficient, you need to test with some LUKS test (mount and write to it)37*/38static const struct ce_variant ce_h3_variant = {39.alg_cipher = { CE_ALG_AES, CE_ALG_DES, CE_ALG_3DES,40},41.alg_hash = { CE_ALG_MD5, CE_ALG_SHA1, CE_ALG_SHA224, CE_ALG_SHA256,42CE_ALG_SHA384, CE_ALG_SHA51243},44.op_mode = { CE_OP_ECB, CE_OP_CBC45},46.ce_clks = {47{ "bus", 0, 200000000 },48{ "mod", 50000000, 0 },49},50.esr = ESR_H3,51.prng = CE_ALG_PRNG,52.trng = CE_ID_NOTSUPP,53};5455static const struct ce_variant ce_h5_variant = {56.alg_cipher = { CE_ALG_AES, CE_ALG_DES, CE_ALG_3DES,57},58.alg_hash = { CE_ALG_MD5, CE_ALG_SHA1, CE_ALG_SHA224, CE_ALG_SHA256,59CE_ID_NOTSUPP, CE_ID_NOTSUPP60},61.op_mode = { CE_OP_ECB, CE_OP_CBC62},63.ce_clks = {64{ "bus", 0, 200000000 },65{ "mod", 300000000, 0 },66},67.esr = ESR_H5,68.prng = CE_ALG_PRNG,69.trng = CE_ID_NOTSUPP,70};7172static const struct ce_variant ce_h6_variant = {73.alg_cipher = { CE_ALG_AES, CE_ALG_DES, CE_ALG_3DES,74},75.alg_hash = { CE_ALG_MD5, CE_ALG_SHA1, CE_ALG_SHA224, CE_ALG_SHA256,76CE_ALG_SHA384, CE_ALG_SHA51277},78.op_mode = { CE_OP_ECB, CE_OP_CBC79},80.cipher_t_dlen_in_bytes = true,81.hash_t_dlen_in_bits = true,82.prng_t_dlen_in_bytes = true,83.trng_t_dlen_in_bytes = true,84.ce_clks = {85{ "bus", 0, 200000000 },86{ "mod", 300000000, 0 },87{ "ram", 0, 400000000 },88},89.esr = ESR_H6,90.prng = CE_ALG_PRNG_V2,91.trng = CE_ALG_TRNG_V2,92};9394static const struct ce_variant ce_h616_variant = {95.alg_cipher = { CE_ALG_AES, CE_ALG_DES, CE_ALG_3DES,96},97.alg_hash = { CE_ALG_MD5, CE_ALG_SHA1, CE_ALG_SHA224, CE_ALG_SHA256,98CE_ALG_SHA384, CE_ALG_SHA51299},100.op_mode = { CE_OP_ECB, CE_OP_CBC101},102.cipher_t_dlen_in_bytes = true,103.hash_t_dlen_in_bits = true,104.prng_t_dlen_in_bytes = true,105.trng_t_dlen_in_bytes = true,106.needs_word_addresses = true,107.ce_clks = {108{ "bus", 0, 200000000 },109{ "mod", 300000000, 0 },110{ "ram", 0, 400000000 },111{ "trng", 0, 0 },112},113.esr = ESR_H6,114.prng = CE_ALG_PRNG_V2,115.trng = CE_ALG_TRNG_V2,116};117118static const struct ce_variant ce_a64_variant = {119.alg_cipher = { CE_ALG_AES, CE_ALG_DES, CE_ALG_3DES,120},121.alg_hash = { CE_ALG_MD5, CE_ALG_SHA1, CE_ALG_SHA224, CE_ALG_SHA256,122CE_ID_NOTSUPP, CE_ID_NOTSUPP123},124.op_mode = { CE_OP_ECB, CE_OP_CBC125},126.ce_clks = {127{ "bus", 0, 200000000 },128{ "mod", 300000000, 0 },129},130.esr = ESR_A64,131.prng = CE_ALG_PRNG,132.trng = CE_ID_NOTSUPP,133};134135static const struct ce_variant ce_d1_variant = {136.alg_cipher = { CE_ALG_AES, CE_ALG_DES, CE_ALG_3DES,137},138.alg_hash = { CE_ALG_MD5, CE_ALG_SHA1, CE_ALG_SHA224, CE_ALG_SHA256,139CE_ALG_SHA384, CE_ALG_SHA512140},141.op_mode = { CE_OP_ECB, CE_OP_CBC142},143.ce_clks = {144{ "bus", 0, 200000000 },145{ "mod", 300000000, 0 },146{ "ram", 0, 400000000 },147{ "trng", 0, 0 },148},149.esr = ESR_D1,150.prng = CE_ALG_PRNG,151.trng = CE_ALG_TRNG,152};153154static const struct ce_variant ce_r40_variant = {155.alg_cipher = { CE_ALG_AES, CE_ALG_DES, CE_ALG_3DES,156},157.alg_hash = { CE_ALG_MD5, CE_ALG_SHA1, CE_ALG_SHA224, CE_ALG_SHA256,158CE_ID_NOTSUPP, CE_ID_NOTSUPP159},160.op_mode = { CE_OP_ECB, CE_OP_CBC161},162.ce_clks = {163{ "bus", 0, 200000000 },164{ "mod", 300000000, 0 },165},166.esr = ESR_R40,167.prng = CE_ALG_PRNG,168.trng = CE_ID_NOTSUPP,169};170171static void sun8i_ce_dump_task_descriptors(struct sun8i_ce_flow *chan)172{173print_hex_dump(KERN_INFO, "TASK: ", DUMP_PREFIX_NONE, 16, 4,174chan->tl, sizeof(struct ce_task), false);175}176177/*178* sun8i_ce_get_engine_number() get the next channel slot179* This is a simple round-robin way of getting the next channel180* The flow 3 is reserve for xRNG operations181*/182int sun8i_ce_get_engine_number(struct sun8i_ce_dev *ce)183{184return atomic_inc_return(&ce->flow) % (MAXFLOW - 1);185}186187int sun8i_ce_run_task(struct sun8i_ce_dev *ce, int flow, const char *name)188{189u32 v;190int err = 0;191192#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG193ce->chanlist[flow].stat_req++;194#endif195196mutex_lock(&ce->mlock);197198v = readl(ce->base + CE_ICR);199v |= 1 << flow;200writel(v, ce->base + CE_ICR);201202reinit_completion(&ce->chanlist[flow].complete);203writel(desc_addr_val(ce, ce->chanlist[flow].t_phy), ce->base + CE_TDQ);204205ce->chanlist[flow].status = 0;206/* Be sure all data is written before enabling the task */207wmb();208209/* Only H6 needs to write a part of t_common_ctl along with "1", but since it is ignored210* on older SoCs, we have no reason to complicate things.211*/212v = 1 | ((le32_to_cpu(ce->chanlist[flow].tl->t_common_ctl) & 0x7F) << 8);213writel(v, ce->base + CE_TLR);214mutex_unlock(&ce->mlock);215216wait_for_completion_interruptible_timeout(&ce->chanlist[flow].complete,217msecs_to_jiffies(CE_DMA_TIMEOUT_MS));218219if (ce->chanlist[flow].status == 0) {220dev_err(ce->dev, "DMA timeout for %s on flow %d\n", name, flow);221err = -EFAULT;222}223/* No need to lock for this read, the channel is locked so224* nothing could modify the error value for this channel225*/226v = readl(ce->base + CE_ESR);227switch (ce->variant->esr) {228case ESR_H3:229/* Sadly, the error bit is not per flow */230if (v) {231dev_err(ce->dev, "CE ERROR: %x for flow %x\n", v, flow);232sun8i_ce_dump_task_descriptors(&ce->chanlist[flow]);233err = -EFAULT;234}235if (v & CE_ERR_ALGO_NOTSUP)236dev_err(ce->dev, "CE ERROR: algorithm not supported\n");237if (v & CE_ERR_DATALEN)238dev_err(ce->dev, "CE ERROR: data length error\n");239if (v & CE_ERR_KEYSRAM)240dev_err(ce->dev, "CE ERROR: keysram access error for AES\n");241break;242case ESR_A64:243case ESR_D1:244case ESR_H5:245case ESR_R40:246v >>= (flow * 4);247v &= 0xF;248if (v) {249dev_err(ce->dev, "CE ERROR: %x for flow %x\n", v, flow);250sun8i_ce_dump_task_descriptors(&ce->chanlist[flow]);251err = -EFAULT;252}253if (v & CE_ERR_ALGO_NOTSUP)254dev_err(ce->dev, "CE ERROR: algorithm not supported\n");255if (v & CE_ERR_DATALEN)256dev_err(ce->dev, "CE ERROR: data length error\n");257if (v & CE_ERR_KEYSRAM)258dev_err(ce->dev, "CE ERROR: keysram access error for AES\n");259break;260case ESR_H6:261v >>= (flow * 8);262v &= 0xFF;263if (v) {264dev_err(ce->dev, "CE ERROR: %x for flow %x\n", v, flow);265sun8i_ce_dump_task_descriptors(&ce->chanlist[flow]);266err = -EFAULT;267}268if (v & CE_ERR_ALGO_NOTSUP)269dev_err(ce->dev, "CE ERROR: algorithm not supported\n");270if (v & CE_ERR_DATALEN)271dev_err(ce->dev, "CE ERROR: data length error\n");272if (v & CE_ERR_KEYSRAM)273dev_err(ce->dev, "CE ERROR: keysram access error for AES\n");274if (v & CE_ERR_ADDR_INVALID)275dev_err(ce->dev, "CE ERROR: address invalid\n");276if (v & CE_ERR_KEYLADDER)277dev_err(ce->dev, "CE ERROR: key ladder configuration error\n");278break;279}280281return err;282}283284static irqreturn_t ce_irq_handler(int irq, void *data)285{286struct sun8i_ce_dev *ce = (struct sun8i_ce_dev *)data;287int flow = 0;288u32 p;289290p = readl(ce->base + CE_ISR);291for (flow = 0; flow < MAXFLOW; flow++) {292if (p & (BIT(flow))) {293writel(BIT(flow), ce->base + CE_ISR);294ce->chanlist[flow].status = 1;295complete(&ce->chanlist[flow].complete);296}297}298299return IRQ_HANDLED;300}301302static struct sun8i_ce_alg_template ce_algs[] = {303{304.type = CRYPTO_ALG_TYPE_SKCIPHER,305.ce_algo_id = CE_ID_CIPHER_AES,306.ce_blockmode = CE_ID_OP_CBC,307.alg.skcipher.base = {308.base = {309.cra_name = "cbc(aes)",310.cra_driver_name = "cbc-aes-sun8i-ce",311.cra_priority = 400,312.cra_blocksize = AES_BLOCK_SIZE,313.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER |314CRYPTO_ALG_ASYNC |315CRYPTO_ALG_NEED_FALLBACK,316.cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx),317.cra_module = THIS_MODULE,318.cra_alignmask = 0xf,319.cra_init = sun8i_ce_cipher_init,320.cra_exit = sun8i_ce_cipher_exit,321},322.min_keysize = AES_MIN_KEY_SIZE,323.max_keysize = AES_MAX_KEY_SIZE,324.ivsize = AES_BLOCK_SIZE,325.setkey = sun8i_ce_aes_setkey,326.encrypt = sun8i_ce_skencrypt,327.decrypt = sun8i_ce_skdecrypt,328},329.alg.skcipher.op = {330.do_one_request = sun8i_ce_cipher_do_one,331},332},333{334.type = CRYPTO_ALG_TYPE_SKCIPHER,335.ce_algo_id = CE_ID_CIPHER_AES,336.ce_blockmode = CE_ID_OP_ECB,337.alg.skcipher.base = {338.base = {339.cra_name = "ecb(aes)",340.cra_driver_name = "ecb-aes-sun8i-ce",341.cra_priority = 400,342.cra_blocksize = AES_BLOCK_SIZE,343.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER |344CRYPTO_ALG_ASYNC |345CRYPTO_ALG_NEED_FALLBACK,346.cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx),347.cra_module = THIS_MODULE,348.cra_alignmask = 0xf,349.cra_init = sun8i_ce_cipher_init,350.cra_exit = sun8i_ce_cipher_exit,351},352.min_keysize = AES_MIN_KEY_SIZE,353.max_keysize = AES_MAX_KEY_SIZE,354.setkey = sun8i_ce_aes_setkey,355.encrypt = sun8i_ce_skencrypt,356.decrypt = sun8i_ce_skdecrypt,357},358.alg.skcipher.op = {359.do_one_request = sun8i_ce_cipher_do_one,360},361},362{363.type = CRYPTO_ALG_TYPE_SKCIPHER,364.ce_algo_id = CE_ID_CIPHER_DES3,365.ce_blockmode = CE_ID_OP_CBC,366.alg.skcipher.base = {367.base = {368.cra_name = "cbc(des3_ede)",369.cra_driver_name = "cbc-des3-sun8i-ce",370.cra_priority = 400,371.cra_blocksize = DES3_EDE_BLOCK_SIZE,372.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER |373CRYPTO_ALG_ASYNC |374CRYPTO_ALG_NEED_FALLBACK,375.cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx),376.cra_module = THIS_MODULE,377.cra_alignmask = 0xf,378.cra_init = sun8i_ce_cipher_init,379.cra_exit = sun8i_ce_cipher_exit,380},381.min_keysize = DES3_EDE_KEY_SIZE,382.max_keysize = DES3_EDE_KEY_SIZE,383.ivsize = DES3_EDE_BLOCK_SIZE,384.setkey = sun8i_ce_des3_setkey,385.encrypt = sun8i_ce_skencrypt,386.decrypt = sun8i_ce_skdecrypt,387},388.alg.skcipher.op = {389.do_one_request = sun8i_ce_cipher_do_one,390},391},392{393.type = CRYPTO_ALG_TYPE_SKCIPHER,394.ce_algo_id = CE_ID_CIPHER_DES3,395.ce_blockmode = CE_ID_OP_ECB,396.alg.skcipher.base = {397.base = {398.cra_name = "ecb(des3_ede)",399.cra_driver_name = "ecb-des3-sun8i-ce",400.cra_priority = 400,401.cra_blocksize = DES3_EDE_BLOCK_SIZE,402.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER |403CRYPTO_ALG_ASYNC |404CRYPTO_ALG_NEED_FALLBACK,405.cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx),406.cra_module = THIS_MODULE,407.cra_alignmask = 0xf,408.cra_init = sun8i_ce_cipher_init,409.cra_exit = sun8i_ce_cipher_exit,410},411.min_keysize = DES3_EDE_KEY_SIZE,412.max_keysize = DES3_EDE_KEY_SIZE,413.setkey = sun8i_ce_des3_setkey,414.encrypt = sun8i_ce_skencrypt,415.decrypt = sun8i_ce_skdecrypt,416},417.alg.skcipher.op = {418.do_one_request = sun8i_ce_cipher_do_one,419},420},421#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_HASH422{ .type = CRYPTO_ALG_TYPE_AHASH,423.ce_algo_id = CE_ID_HASH_MD5,424.alg.hash.base = {425.init = sun8i_ce_hash_init,426.update = sun8i_ce_hash_update,427.final = sun8i_ce_hash_final,428.finup = sun8i_ce_hash_finup,429.digest = sun8i_ce_hash_digest,430.export = sun8i_ce_hash_export,431.import = sun8i_ce_hash_import,432.init_tfm = sun8i_ce_hash_init_tfm,433.exit_tfm = sun8i_ce_hash_exit_tfm,434.halg = {435.digestsize = MD5_DIGEST_SIZE,436.statesize = sizeof(struct md5_state),437.base = {438.cra_name = "md5",439.cra_driver_name = "md5-sun8i-ce",440.cra_priority = 300,441.cra_flags = CRYPTO_ALG_TYPE_AHASH |442CRYPTO_ALG_ASYNC |443CRYPTO_ALG_NEED_FALLBACK,444.cra_blocksize = MD5_HMAC_BLOCK_SIZE,445.cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx),446.cra_module = THIS_MODULE,447}448}449},450.alg.hash.op = {451.do_one_request = sun8i_ce_hash_run,452},453454},455{ .type = CRYPTO_ALG_TYPE_AHASH,456.ce_algo_id = CE_ID_HASH_SHA1,457.alg.hash.base = {458.init = sun8i_ce_hash_init,459.update = sun8i_ce_hash_update,460.final = sun8i_ce_hash_final,461.finup = sun8i_ce_hash_finup,462.digest = sun8i_ce_hash_digest,463.export = sun8i_ce_hash_export,464.import = sun8i_ce_hash_import,465.init_tfm = sun8i_ce_hash_init_tfm,466.exit_tfm = sun8i_ce_hash_exit_tfm,467.halg = {468.digestsize = SHA1_DIGEST_SIZE,469.statesize = sizeof(struct sha1_state),470.base = {471.cra_name = "sha1",472.cra_driver_name = "sha1-sun8i-ce",473.cra_priority = 300,474.cra_flags = CRYPTO_ALG_TYPE_AHASH |475CRYPTO_ALG_ASYNC |476CRYPTO_ALG_NEED_FALLBACK,477.cra_blocksize = SHA1_BLOCK_SIZE,478.cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx),479.cra_module = THIS_MODULE,480}481}482},483.alg.hash.op = {484.do_one_request = sun8i_ce_hash_run,485},486},487{ .type = CRYPTO_ALG_TYPE_AHASH,488.ce_algo_id = CE_ID_HASH_SHA224,489.alg.hash.base = {490.init = sun8i_ce_hash_init,491.update = sun8i_ce_hash_update,492.final = sun8i_ce_hash_final,493.finup = sun8i_ce_hash_finup,494.digest = sun8i_ce_hash_digest,495.export = sun8i_ce_hash_export,496.import = sun8i_ce_hash_import,497.init_tfm = sun8i_ce_hash_init_tfm,498.exit_tfm = sun8i_ce_hash_exit_tfm,499.halg = {500.digestsize = SHA224_DIGEST_SIZE,501.statesize = sizeof(struct sha256_state),502.base = {503.cra_name = "sha224",504.cra_driver_name = "sha224-sun8i-ce",505.cra_priority = 300,506.cra_flags = CRYPTO_ALG_TYPE_AHASH |507CRYPTO_ALG_ASYNC |508CRYPTO_ALG_NEED_FALLBACK,509.cra_blocksize = SHA224_BLOCK_SIZE,510.cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx),511.cra_module = THIS_MODULE,512}513}514},515.alg.hash.op = {516.do_one_request = sun8i_ce_hash_run,517},518},519{ .type = CRYPTO_ALG_TYPE_AHASH,520.ce_algo_id = CE_ID_HASH_SHA256,521.alg.hash.base = {522.init = sun8i_ce_hash_init,523.update = sun8i_ce_hash_update,524.final = sun8i_ce_hash_final,525.finup = sun8i_ce_hash_finup,526.digest = sun8i_ce_hash_digest,527.export = sun8i_ce_hash_export,528.import = sun8i_ce_hash_import,529.init_tfm = sun8i_ce_hash_init_tfm,530.exit_tfm = sun8i_ce_hash_exit_tfm,531.halg = {532.digestsize = SHA256_DIGEST_SIZE,533.statesize = sizeof(struct sha256_state),534.base = {535.cra_name = "sha256",536.cra_driver_name = "sha256-sun8i-ce",537.cra_priority = 300,538.cra_flags = CRYPTO_ALG_TYPE_AHASH |539CRYPTO_ALG_ASYNC |540CRYPTO_ALG_NEED_FALLBACK,541.cra_blocksize = SHA256_BLOCK_SIZE,542.cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx),543.cra_module = THIS_MODULE,544}545}546},547.alg.hash.op = {548.do_one_request = sun8i_ce_hash_run,549},550},551{ .type = CRYPTO_ALG_TYPE_AHASH,552.ce_algo_id = CE_ID_HASH_SHA384,553.alg.hash.base = {554.init = sun8i_ce_hash_init,555.update = sun8i_ce_hash_update,556.final = sun8i_ce_hash_final,557.finup = sun8i_ce_hash_finup,558.digest = sun8i_ce_hash_digest,559.export = sun8i_ce_hash_export,560.import = sun8i_ce_hash_import,561.init_tfm = sun8i_ce_hash_init_tfm,562.exit_tfm = sun8i_ce_hash_exit_tfm,563.halg = {564.digestsize = SHA384_DIGEST_SIZE,565.statesize = sizeof(struct sha512_state),566.base = {567.cra_name = "sha384",568.cra_driver_name = "sha384-sun8i-ce",569.cra_priority = 300,570.cra_flags = CRYPTO_ALG_TYPE_AHASH |571CRYPTO_ALG_ASYNC |572CRYPTO_ALG_NEED_FALLBACK,573.cra_blocksize = SHA384_BLOCK_SIZE,574.cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx),575.cra_module = THIS_MODULE,576}577}578},579.alg.hash.op = {580.do_one_request = sun8i_ce_hash_run,581},582},583{ .type = CRYPTO_ALG_TYPE_AHASH,584.ce_algo_id = CE_ID_HASH_SHA512,585.alg.hash.base = {586.init = sun8i_ce_hash_init,587.update = sun8i_ce_hash_update,588.final = sun8i_ce_hash_final,589.finup = sun8i_ce_hash_finup,590.digest = sun8i_ce_hash_digest,591.export = sun8i_ce_hash_export,592.import = sun8i_ce_hash_import,593.init_tfm = sun8i_ce_hash_init_tfm,594.exit_tfm = sun8i_ce_hash_exit_tfm,595.halg = {596.digestsize = SHA512_DIGEST_SIZE,597.statesize = sizeof(struct sha512_state),598.base = {599.cra_name = "sha512",600.cra_driver_name = "sha512-sun8i-ce",601.cra_priority = 300,602.cra_flags = CRYPTO_ALG_TYPE_AHASH |603CRYPTO_ALG_ASYNC |604CRYPTO_ALG_NEED_FALLBACK,605.cra_blocksize = SHA512_BLOCK_SIZE,606.cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx),607.cra_module = THIS_MODULE,608}609}610},611.alg.hash.op = {612.do_one_request = sun8i_ce_hash_run,613},614},615#endif616#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG617{618.type = CRYPTO_ALG_TYPE_RNG,619.alg.rng = {620.base = {621.cra_name = "stdrng",622.cra_driver_name = "sun8i-ce-prng",623.cra_priority = 300,624.cra_ctxsize = sizeof(struct sun8i_ce_rng_tfm_ctx),625.cra_module = THIS_MODULE,626.cra_init = sun8i_ce_prng_init,627.cra_exit = sun8i_ce_prng_exit,628},629.generate = sun8i_ce_prng_generate,630.seed = sun8i_ce_prng_seed,631.seedsize = PRNG_SEED_SIZE,632}633},634#endif635};636637static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v)638{639struct sun8i_ce_dev *ce __maybe_unused = seq->private;640unsigned int i;641642for (i = 0; i < MAXFLOW; i++)643seq_printf(seq, "Channel %d: nreq %lu\n", i,644#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG645ce->chanlist[i].stat_req);646#else6470ul);648#endif649650for (i = 0; i < ARRAY_SIZE(ce_algs); i++) {651if (!ce_algs[i].ce)652continue;653switch (ce_algs[i].type) {654case CRYPTO_ALG_TYPE_SKCIPHER:655seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n",656ce_algs[i].alg.skcipher.base.base.cra_driver_name,657ce_algs[i].alg.skcipher.base.base.cra_name,658ce_algs[i].stat_req, ce_algs[i].stat_fb);659seq_printf(seq, "\tLast fallback is: %s\n",660ce_algs[i].fbname);661seq_printf(seq, "\tFallback due to 0 length: %lu\n",662ce_algs[i].stat_fb_len0);663seq_printf(seq, "\tFallback due to length !mod16: %lu\n",664ce_algs[i].stat_fb_mod16);665seq_printf(seq, "\tFallback due to length < IV: %lu\n",666ce_algs[i].stat_fb_leniv);667seq_printf(seq, "\tFallback due to source alignment: %lu\n",668ce_algs[i].stat_fb_srcali);669seq_printf(seq, "\tFallback due to dest alignment: %lu\n",670ce_algs[i].stat_fb_dstali);671seq_printf(seq, "\tFallback due to source length: %lu\n",672ce_algs[i].stat_fb_srclen);673seq_printf(seq, "\tFallback due to dest length: %lu\n",674ce_algs[i].stat_fb_dstlen);675seq_printf(seq, "\tFallback due to SG numbers: %lu\n",676ce_algs[i].stat_fb_maxsg);677break;678case CRYPTO_ALG_TYPE_AHASH:679seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n",680ce_algs[i].alg.hash.base.halg.base.cra_driver_name,681ce_algs[i].alg.hash.base.halg.base.cra_name,682ce_algs[i].stat_req, ce_algs[i].stat_fb);683seq_printf(seq, "\tLast fallback is: %s\n",684ce_algs[i].fbname);685seq_printf(seq, "\tFallback due to 0 length: %lu\n",686ce_algs[i].stat_fb_len0);687seq_printf(seq, "\tFallback due to length: %lu\n",688ce_algs[i].stat_fb_srclen);689seq_printf(seq, "\tFallback due to alignment: %lu\n",690ce_algs[i].stat_fb_srcali);691seq_printf(seq, "\tFallback due to SG numbers: %lu\n",692ce_algs[i].stat_fb_maxsg);693break;694case CRYPTO_ALG_TYPE_RNG:695seq_printf(seq, "%s %s reqs=%lu bytes=%lu\n",696ce_algs[i].alg.rng.base.cra_driver_name,697ce_algs[i].alg.rng.base.cra_name,698ce_algs[i].stat_req, ce_algs[i].stat_bytes);699break;700}701}702#if defined(CONFIG_CRYPTO_DEV_SUN8I_CE_TRNG) && \703defined(CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG)704seq_printf(seq, "HWRNG %lu %lu\n",705ce->hwrng_stat_req, ce->hwrng_stat_bytes);706#endif707return 0;708}709710DEFINE_SHOW_ATTRIBUTE(sun8i_ce_debugfs);711712static void sun8i_ce_free_chanlist(struct sun8i_ce_dev *ce, int i)713{714while (i >= 0) {715crypto_engine_exit(ce->chanlist[i].engine);716if (ce->chanlist[i].tl)717dma_free_coherent(ce->dev, sizeof(struct ce_task),718ce->chanlist[i].tl,719ce->chanlist[i].t_phy);720i--;721}722}723724/*725* Allocate the channel list structure726*/727static int sun8i_ce_allocate_chanlist(struct sun8i_ce_dev *ce)728{729int i, err;730731ce->chanlist = devm_kcalloc(ce->dev, MAXFLOW,732sizeof(struct sun8i_ce_flow), GFP_KERNEL);733if (!ce->chanlist)734return -ENOMEM;735736for (i = 0; i < MAXFLOW; i++) {737init_completion(&ce->chanlist[i].complete);738739ce->chanlist[i].engine = crypto_engine_alloc_init(ce->dev, true);740if (!ce->chanlist[i].engine) {741dev_err(ce->dev, "Cannot allocate engine\n");742i--;743err = -ENOMEM;744goto error_engine;745}746err = crypto_engine_start(ce->chanlist[i].engine);747if (err) {748dev_err(ce->dev, "Cannot start engine\n");749goto error_engine;750}751ce->chanlist[i].tl = dma_alloc_coherent(ce->dev,752sizeof(struct ce_task),753&ce->chanlist[i].t_phy,754GFP_KERNEL);755if (!ce->chanlist[i].tl) {756dev_err(ce->dev, "Cannot get DMA memory for task %d\n",757i);758err = -ENOMEM;759goto error_engine;760}761}762return 0;763error_engine:764sun8i_ce_free_chanlist(ce, i);765return err;766}767768/*769* Power management strategy: The device is suspended unless a TFM exists for770* one of the algorithms proposed by this driver.771*/772static int sun8i_ce_pm_suspend(struct device *dev)773{774struct sun8i_ce_dev *ce = dev_get_drvdata(dev);775int i;776777reset_control_assert(ce->reset);778for (i = 0; i < CE_MAX_CLOCKS; i++)779clk_disable_unprepare(ce->ceclks[i]);780return 0;781}782783static int sun8i_ce_pm_resume(struct device *dev)784{785struct sun8i_ce_dev *ce = dev_get_drvdata(dev);786int err, i;787788for (i = 0; i < CE_MAX_CLOCKS; i++) {789if (!ce->variant->ce_clks[i].name)790continue;791err = clk_prepare_enable(ce->ceclks[i]);792if (err) {793dev_err(ce->dev, "Cannot prepare_enable %s\n",794ce->variant->ce_clks[i].name);795goto error;796}797}798err = reset_control_deassert(ce->reset);799if (err) {800dev_err(ce->dev, "Cannot deassert reset control\n");801goto error;802}803return 0;804error:805sun8i_ce_pm_suspend(dev);806return err;807}808809static const struct dev_pm_ops sun8i_ce_pm_ops = {810SET_RUNTIME_PM_OPS(sun8i_ce_pm_suspend, sun8i_ce_pm_resume, NULL)811};812813static int sun8i_ce_pm_init(struct sun8i_ce_dev *ce)814{815int err;816817pm_runtime_use_autosuspend(ce->dev);818pm_runtime_set_autosuspend_delay(ce->dev, 2000);819820err = pm_runtime_set_suspended(ce->dev);821if (err)822return err;823824err = devm_pm_runtime_enable(ce->dev);825if (err)826return err;827828return 0;829}830831static int sun8i_ce_get_clks(struct sun8i_ce_dev *ce)832{833unsigned long cr;834int err, i;835836for (i = 0; i < CE_MAX_CLOCKS; i++) {837if (!ce->variant->ce_clks[i].name)838continue;839ce->ceclks[i] = devm_clk_get(ce->dev, ce->variant->ce_clks[i].name);840if (IS_ERR(ce->ceclks[i])) {841err = PTR_ERR(ce->ceclks[i]);842dev_err(ce->dev, "Cannot get %s CE clock err=%d\n",843ce->variant->ce_clks[i].name, err);844return err;845}846cr = clk_get_rate(ce->ceclks[i]);847if (!cr)848return -EINVAL;849if (ce->variant->ce_clks[i].freq > 0 &&850cr != ce->variant->ce_clks[i].freq) {851dev_info(ce->dev, "Set %s clock to %lu (%lu Mhz) from %lu (%lu Mhz)\n",852ce->variant->ce_clks[i].name,853ce->variant->ce_clks[i].freq,854ce->variant->ce_clks[i].freq / 1000000,855cr, cr / 1000000);856err = clk_set_rate(ce->ceclks[i], ce->variant->ce_clks[i].freq);857if (err)858dev_err(ce->dev, "Fail to set %s clk speed to %lu hz\n",859ce->variant->ce_clks[i].name,860ce->variant->ce_clks[i].freq);861}862if (ce->variant->ce_clks[i].max_freq > 0 &&863cr > ce->variant->ce_clks[i].max_freq)864dev_warn(ce->dev, "Frequency for %s (%lu hz) is higher than datasheet's recommendation (%lu hz)",865ce->variant->ce_clks[i].name, cr,866ce->variant->ce_clks[i].max_freq);867}868return 0;869}870871static int sun8i_ce_register_algs(struct sun8i_ce_dev *ce)872{873int ce_method, err, id;874unsigned int i;875876for (i = 0; i < ARRAY_SIZE(ce_algs); i++) {877ce_algs[i].ce = ce;878switch (ce_algs[i].type) {879case CRYPTO_ALG_TYPE_SKCIPHER:880id = ce_algs[i].ce_algo_id;881ce_method = ce->variant->alg_cipher[id];882if (ce_method == CE_ID_NOTSUPP) {883dev_dbg(ce->dev,884"DEBUG: Algo of %s not supported\n",885ce_algs[i].alg.skcipher.base.base.cra_name);886ce_algs[i].ce = NULL;887break;888}889id = ce_algs[i].ce_blockmode;890ce_method = ce->variant->op_mode[id];891if (ce_method == CE_ID_NOTSUPP) {892dev_dbg(ce->dev, "DEBUG: Blockmode of %s not supported\n",893ce_algs[i].alg.skcipher.base.base.cra_name);894ce_algs[i].ce = NULL;895break;896}897dev_info(ce->dev, "Register %s\n",898ce_algs[i].alg.skcipher.base.base.cra_name);899err = crypto_engine_register_skcipher(&ce_algs[i].alg.skcipher);900if (err) {901dev_err(ce->dev, "ERROR: Fail to register %s\n",902ce_algs[i].alg.skcipher.base.base.cra_name);903ce_algs[i].ce = NULL;904return err;905}906break;907case CRYPTO_ALG_TYPE_AHASH:908id = ce_algs[i].ce_algo_id;909ce_method = ce->variant->alg_hash[id];910if (ce_method == CE_ID_NOTSUPP) {911dev_info(ce->dev,912"DEBUG: Algo of %s not supported\n",913ce_algs[i].alg.hash.base.halg.base.cra_name);914ce_algs[i].ce = NULL;915break;916}917dev_info(ce->dev, "Register %s\n",918ce_algs[i].alg.hash.base.halg.base.cra_name);919err = crypto_engine_register_ahash(&ce_algs[i].alg.hash);920if (err) {921dev_err(ce->dev, "ERROR: Fail to register %s\n",922ce_algs[i].alg.hash.base.halg.base.cra_name);923ce_algs[i].ce = NULL;924return err;925}926break;927case CRYPTO_ALG_TYPE_RNG:928if (ce->variant->prng == CE_ID_NOTSUPP) {929dev_info(ce->dev,930"DEBUG: Algo of %s not supported\n",931ce_algs[i].alg.rng.base.cra_name);932ce_algs[i].ce = NULL;933break;934}935dev_info(ce->dev, "Register %s\n",936ce_algs[i].alg.rng.base.cra_name);937err = crypto_register_rng(&ce_algs[i].alg.rng);938if (err) {939dev_err(ce->dev, "Fail to register %s\n",940ce_algs[i].alg.rng.base.cra_name);941ce_algs[i].ce = NULL;942}943break;944default:945ce_algs[i].ce = NULL;946dev_err(ce->dev, "ERROR: tried to register an unknown algo\n");947}948}949return 0;950}951952static void sun8i_ce_unregister_algs(struct sun8i_ce_dev *ce)953{954unsigned int i;955956for (i = 0; i < ARRAY_SIZE(ce_algs); i++) {957if (!ce_algs[i].ce)958continue;959switch (ce_algs[i].type) {960case CRYPTO_ALG_TYPE_SKCIPHER:961dev_info(ce->dev, "Unregister %d %s\n", i,962ce_algs[i].alg.skcipher.base.base.cra_name);963crypto_engine_unregister_skcipher(&ce_algs[i].alg.skcipher);964break;965case CRYPTO_ALG_TYPE_AHASH:966dev_info(ce->dev, "Unregister %d %s\n", i,967ce_algs[i].alg.hash.base.halg.base.cra_name);968crypto_engine_unregister_ahash(&ce_algs[i].alg.hash);969break;970case CRYPTO_ALG_TYPE_RNG:971dev_info(ce->dev, "Unregister %d %s\n", i,972ce_algs[i].alg.rng.base.cra_name);973crypto_unregister_rng(&ce_algs[i].alg.rng);974break;975}976}977}978979static int sun8i_ce_probe(struct platform_device *pdev)980{981struct sun8i_ce_dev *ce;982int err, irq;983u32 v;984985ce = devm_kzalloc(&pdev->dev, sizeof(*ce), GFP_KERNEL);986if (!ce)987return -ENOMEM;988989ce->dev = &pdev->dev;990platform_set_drvdata(pdev, ce);991992ce->variant = of_device_get_match_data(&pdev->dev);993if (!ce->variant) {994dev_err(&pdev->dev, "Missing Crypto Engine variant\n");995return -EINVAL;996}997998ce->base = devm_platform_ioremap_resource(pdev, 0);999if (IS_ERR(ce->base))1000return PTR_ERR(ce->base);10011002err = sun8i_ce_get_clks(ce);1003if (err)1004return err;10051006/* Get Non Secure IRQ */1007irq = platform_get_irq(pdev, 0);1008if (irq < 0)1009return irq;10101011ce->reset = devm_reset_control_get(&pdev->dev, NULL);1012if (IS_ERR(ce->reset))1013return dev_err_probe(&pdev->dev, PTR_ERR(ce->reset),1014"No reset control found\n");10151016mutex_init(&ce->mlock);1017mutex_init(&ce->rnglock);10181019err = sun8i_ce_allocate_chanlist(ce);1020if (err)1021return err;10221023err = sun8i_ce_pm_init(ce);1024if (err)1025goto error_pm;10261027err = devm_request_irq(&pdev->dev, irq, ce_irq_handler, 0,1028"sun8i-ce-ns", ce);1029if (err) {1030dev_err(ce->dev, "Cannot request CryptoEngine Non-secure IRQ (err=%d)\n", err);1031goto error_pm;1032}10331034err = sun8i_ce_register_algs(ce);1035if (err)1036goto error_alg;10371038err = pm_runtime_resume_and_get(ce->dev);1039if (err < 0)1040goto error_alg;10411042#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_TRNG1043sun8i_ce_hwrng_register(ce);1044#endif10451046v = readl(ce->base + CE_CTR);1047v >>= CE_DIE_ID_SHIFT;1048v &= CE_DIE_ID_MASK;1049dev_info(&pdev->dev, "CryptoEngine Die ID %x\n", v);10501051pm_runtime_put_sync(ce->dev);10521053if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG)) {1054struct dentry *dbgfs_dir;1055struct dentry *dbgfs_stats __maybe_unused;10561057/* Ignore error of debugfs */1058dbgfs_dir = debugfs_create_dir("sun8i-ce", NULL);1059dbgfs_stats = debugfs_create_file("stats", 0444,1060dbgfs_dir, ce,1061&sun8i_ce_debugfs_fops);10621063#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG1064ce->dbgfs_dir = dbgfs_dir;1065ce->dbgfs_stats = dbgfs_stats;1066#endif1067}10681069return 0;1070error_alg:1071sun8i_ce_unregister_algs(ce);1072error_pm:1073sun8i_ce_free_chanlist(ce, MAXFLOW - 1);1074return err;1075}10761077static void sun8i_ce_remove(struct platform_device *pdev)1078{1079struct sun8i_ce_dev *ce = platform_get_drvdata(pdev);10801081#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_TRNG1082sun8i_ce_hwrng_unregister(ce);1083#endif10841085sun8i_ce_unregister_algs(ce);10861087#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG1088debugfs_remove_recursive(ce->dbgfs_dir);1089#endif10901091sun8i_ce_free_chanlist(ce, MAXFLOW - 1);1092}10931094static const struct of_device_id sun8i_ce_crypto_of_match_table[] = {1095{ .compatible = "allwinner,sun8i-h3-crypto",1096.data = &ce_h3_variant },1097{ .compatible = "allwinner,sun8i-r40-crypto",1098.data = &ce_r40_variant },1099{ .compatible = "allwinner,sun20i-d1-crypto",1100.data = &ce_d1_variant },1101{ .compatible = "allwinner,sun50i-a64-crypto",1102.data = &ce_a64_variant },1103{ .compatible = "allwinner,sun50i-h5-crypto",1104.data = &ce_h5_variant },1105{ .compatible = "allwinner,sun50i-h6-crypto",1106.data = &ce_h6_variant },1107{ .compatible = "allwinner,sun50i-h616-crypto",1108.data = &ce_h616_variant },1109{}1110};1111MODULE_DEVICE_TABLE(of, sun8i_ce_crypto_of_match_table);11121113static struct platform_driver sun8i_ce_driver = {1114.probe = sun8i_ce_probe,1115.remove = sun8i_ce_remove,1116.driver = {1117.name = "sun8i-ce",1118.pm = &sun8i_ce_pm_ops,1119.of_match_table = sun8i_ce_crypto_of_match_table,1120},1121};11221123module_platform_driver(sun8i_ce_driver);11241125MODULE_DESCRIPTION("Allwinner Crypto Engine cryptographic offloader");1126MODULE_LICENSE("GPL");1127MODULE_AUTHOR("Corentin Labbe <[email protected]>");112811291130