148fe583fSCorentin Labbe // SPDX-License-Identifier: GPL-2.0 248fe583fSCorentin Labbe /* 348fe583fSCorentin Labbe * amlgoic-core.c - hardware cryptographic offloader for Amlogic GXL SoC 448fe583fSCorentin Labbe * 548fe583fSCorentin Labbe * Copyright (C) 2018-2019 Corentin Labbe <clabbe@baylibre.com> 648fe583fSCorentin Labbe * 748fe583fSCorentin Labbe * Core file which registers crypto algorithms supported by the hardware. 848fe583fSCorentin Labbe */ 948fe583fSCorentin Labbe #include <linux/clk.h> 1048fe583fSCorentin Labbe #include <linux/crypto.h> 1148fe583fSCorentin Labbe #include <linux/io.h> 1248fe583fSCorentin Labbe #include <linux/interrupt.h> 1348fe583fSCorentin Labbe #include <linux/irq.h> 1448fe583fSCorentin Labbe #include <linux/module.h> 1548fe583fSCorentin Labbe #include <linux/of.h> 1648fe583fSCorentin Labbe #include <linux/of_device.h> 1748fe583fSCorentin Labbe #include <linux/platform_device.h> 1848fe583fSCorentin Labbe #include <crypto/internal/skcipher.h> 1948fe583fSCorentin Labbe #include <linux/dma-mapping.h> 2048fe583fSCorentin Labbe 2148fe583fSCorentin Labbe #include "amlogic-gxl.h" 2248fe583fSCorentin Labbe 2348fe583fSCorentin Labbe static irqreturn_t meson_irq_handler(int irq, void *data) 2448fe583fSCorentin Labbe { 2548fe583fSCorentin Labbe struct meson_dev *mc = (struct meson_dev *)data; 2648fe583fSCorentin Labbe int flow; 2748fe583fSCorentin Labbe u32 p; 2848fe583fSCorentin Labbe 2948fe583fSCorentin Labbe for (flow = 0; flow < MAXFLOW; flow++) { 3048fe583fSCorentin Labbe if (mc->irqs[flow] == irq) { 3148fe583fSCorentin Labbe p = readl(mc->base + ((0x04 + flow) << 2)); 3248fe583fSCorentin Labbe if (p) { 3348fe583fSCorentin Labbe writel_relaxed(0xF, mc->base + ((0x4 + flow) << 2)); 3448fe583fSCorentin Labbe mc->chanlist[flow].status = 1; 3548fe583fSCorentin Labbe complete(&mc->chanlist[flow].complete); 3648fe583fSCorentin Labbe return IRQ_HANDLED; 3748fe583fSCorentin Labbe } 3848fe583fSCorentin Labbe dev_err(mc->dev, "%s %d Got irq for flow %d but ctrl is empty\n", __func__, irq, flow); 3948fe583fSCorentin Labbe } 4048fe583fSCorentin Labbe } 4148fe583fSCorentin Labbe 4248fe583fSCorentin Labbe dev_err(mc->dev, "%s %d from unknown irq\n", __func__, irq); 4348fe583fSCorentin Labbe return IRQ_HANDLED; 4448fe583fSCorentin Labbe } 4548fe583fSCorentin Labbe 4648fe583fSCorentin Labbe static struct meson_alg_template mc_algs[] = { 4748fe583fSCorentin Labbe { 4848fe583fSCorentin Labbe .type = CRYPTO_ALG_TYPE_SKCIPHER, 4948fe583fSCorentin Labbe .blockmode = MESON_OPMODE_CBC, 5048fe583fSCorentin Labbe .alg.skcipher = { 5148fe583fSCorentin Labbe .base = { 5248fe583fSCorentin Labbe .cra_name = "cbc(aes)", 5348fe583fSCorentin Labbe .cra_driver_name = "cbc-aes-gxl", 5448fe583fSCorentin Labbe .cra_priority = 400, 5548fe583fSCorentin Labbe .cra_blocksize = AES_BLOCK_SIZE, 5648fe583fSCorentin Labbe .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | 5748fe583fSCorentin Labbe CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, 5848fe583fSCorentin Labbe .cra_ctxsize = sizeof(struct meson_cipher_tfm_ctx), 5948fe583fSCorentin Labbe .cra_module = THIS_MODULE, 6048fe583fSCorentin Labbe .cra_alignmask = 0xf, 6148fe583fSCorentin Labbe .cra_init = meson_cipher_init, 6248fe583fSCorentin Labbe .cra_exit = meson_cipher_exit, 6348fe583fSCorentin Labbe }, 6448fe583fSCorentin Labbe .min_keysize = AES_MIN_KEY_SIZE, 6548fe583fSCorentin Labbe .max_keysize = AES_MAX_KEY_SIZE, 6648fe583fSCorentin Labbe .ivsize = AES_BLOCK_SIZE, 6748fe583fSCorentin Labbe .setkey = meson_aes_setkey, 6848fe583fSCorentin Labbe .encrypt = meson_skencrypt, 6948fe583fSCorentin Labbe .decrypt = meson_skdecrypt, 7048fe583fSCorentin Labbe } 7148fe583fSCorentin Labbe }, 7248fe583fSCorentin Labbe { 7348fe583fSCorentin Labbe .type = CRYPTO_ALG_TYPE_SKCIPHER, 7448fe583fSCorentin Labbe .blockmode = MESON_OPMODE_ECB, 7548fe583fSCorentin Labbe .alg.skcipher = { 7648fe583fSCorentin Labbe .base = { 7748fe583fSCorentin Labbe .cra_name = "ecb(aes)", 7848fe583fSCorentin Labbe .cra_driver_name = "ecb-aes-gxl", 7948fe583fSCorentin Labbe .cra_priority = 400, 8048fe583fSCorentin Labbe .cra_blocksize = AES_BLOCK_SIZE, 8148fe583fSCorentin Labbe .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | 8248fe583fSCorentin Labbe CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, 8348fe583fSCorentin Labbe .cra_ctxsize = sizeof(struct meson_cipher_tfm_ctx), 8448fe583fSCorentin Labbe .cra_module = THIS_MODULE, 8548fe583fSCorentin Labbe .cra_alignmask = 0xf, 8648fe583fSCorentin Labbe .cra_init = meson_cipher_init, 8748fe583fSCorentin Labbe .cra_exit = meson_cipher_exit, 8848fe583fSCorentin Labbe }, 8948fe583fSCorentin Labbe .min_keysize = AES_MIN_KEY_SIZE, 9048fe583fSCorentin Labbe .max_keysize = AES_MAX_KEY_SIZE, 9148fe583fSCorentin Labbe .setkey = meson_aes_setkey, 9248fe583fSCorentin Labbe .encrypt = meson_skencrypt, 9348fe583fSCorentin Labbe .decrypt = meson_skdecrypt, 9448fe583fSCorentin Labbe } 9548fe583fSCorentin Labbe }, 9648fe583fSCorentin Labbe }; 9748fe583fSCorentin Labbe 9848fe583fSCorentin Labbe #ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG 9948fe583fSCorentin Labbe static int meson_dbgfs_read(struct seq_file *seq, void *v) 10048fe583fSCorentin Labbe { 10148fe583fSCorentin Labbe struct meson_dev *mc = seq->private; 10248fe583fSCorentin Labbe int i; 10348fe583fSCorentin Labbe 10448fe583fSCorentin Labbe for (i = 0; i < MAXFLOW; i++) 10548fe583fSCorentin Labbe seq_printf(seq, "Channel %d: nreq %lu\n", i, mc->chanlist[i].stat_req); 10648fe583fSCorentin Labbe 10748fe583fSCorentin Labbe for (i = 0; i < ARRAY_SIZE(mc_algs); i++) { 10848fe583fSCorentin Labbe switch (mc_algs[i].type) { 10948fe583fSCorentin Labbe case CRYPTO_ALG_TYPE_SKCIPHER: 11048fe583fSCorentin Labbe seq_printf(seq, "%s %s %lu %lu\n", 11148fe583fSCorentin Labbe mc_algs[i].alg.skcipher.base.cra_driver_name, 11248fe583fSCorentin Labbe mc_algs[i].alg.skcipher.base.cra_name, 11348fe583fSCorentin Labbe mc_algs[i].stat_req, mc_algs[i].stat_fb); 11448fe583fSCorentin Labbe break; 11548fe583fSCorentin Labbe } 11648fe583fSCorentin Labbe } 11748fe583fSCorentin Labbe return 0; 11848fe583fSCorentin Labbe } 11948fe583fSCorentin Labbe 12048fe583fSCorentin Labbe static int meson_dbgfs_open(struct inode *inode, struct file *file) 12148fe583fSCorentin Labbe { 12248fe583fSCorentin Labbe return single_open(file, meson_dbgfs_read, inode->i_private); 12348fe583fSCorentin Labbe } 12448fe583fSCorentin Labbe 12548fe583fSCorentin Labbe static const struct file_operations meson_debugfs_fops = { 12648fe583fSCorentin Labbe .owner = THIS_MODULE, 12748fe583fSCorentin Labbe .open = meson_dbgfs_open, 12848fe583fSCorentin Labbe .read = seq_read, 12948fe583fSCorentin Labbe .llseek = seq_lseek, 13048fe583fSCorentin Labbe .release = single_release, 13148fe583fSCorentin Labbe }; 13248fe583fSCorentin Labbe #endif 13348fe583fSCorentin Labbe 13448fe583fSCorentin Labbe static void meson_free_chanlist(struct meson_dev *mc, int i) 13548fe583fSCorentin Labbe { 13648fe583fSCorentin Labbe while (i >= 0) { 13748fe583fSCorentin Labbe crypto_engine_exit(mc->chanlist[i].engine); 13848fe583fSCorentin Labbe if (mc->chanlist[i].tl) 13948fe583fSCorentin Labbe dma_free_coherent(mc->dev, sizeof(struct meson_desc) * MAXDESC, 14048fe583fSCorentin Labbe mc->chanlist[i].tl, 14148fe583fSCorentin Labbe mc->chanlist[i].t_phy); 14248fe583fSCorentin Labbe i--; 14348fe583fSCorentin Labbe } 14448fe583fSCorentin Labbe } 14548fe583fSCorentin Labbe 14648fe583fSCorentin Labbe /* 14748fe583fSCorentin Labbe * Allocate the channel list structure 14848fe583fSCorentin Labbe */ 14948fe583fSCorentin Labbe static int meson_allocate_chanlist(struct meson_dev *mc) 15048fe583fSCorentin Labbe { 15148fe583fSCorentin Labbe int i, err; 15248fe583fSCorentin Labbe 15348fe583fSCorentin Labbe mc->chanlist = devm_kcalloc(mc->dev, MAXFLOW, 15448fe583fSCorentin Labbe sizeof(struct meson_flow), GFP_KERNEL); 15548fe583fSCorentin Labbe if (!mc->chanlist) 15648fe583fSCorentin Labbe return -ENOMEM; 15748fe583fSCorentin Labbe 15848fe583fSCorentin Labbe for (i = 0; i < MAXFLOW; i++) { 15948fe583fSCorentin Labbe init_completion(&mc->chanlist[i].complete); 16048fe583fSCorentin Labbe 16148fe583fSCorentin Labbe mc->chanlist[i].engine = crypto_engine_alloc_init(mc->dev, true); 16248fe583fSCorentin Labbe if (!mc->chanlist[i].engine) { 16348fe583fSCorentin Labbe dev_err(mc->dev, "Cannot allocate engine\n"); 16448fe583fSCorentin Labbe i--; 165a9704293SColin Ian King err = -ENOMEM; 16648fe583fSCorentin Labbe goto error_engine; 16748fe583fSCorentin Labbe } 16848fe583fSCorentin Labbe err = crypto_engine_start(mc->chanlist[i].engine); 16948fe583fSCorentin Labbe if (err) { 17048fe583fSCorentin Labbe dev_err(mc->dev, "Cannot start engine\n"); 17148fe583fSCorentin Labbe goto error_engine; 17248fe583fSCorentin Labbe } 17348fe583fSCorentin Labbe mc->chanlist[i].tl = dma_alloc_coherent(mc->dev, 17448fe583fSCorentin Labbe sizeof(struct meson_desc) * MAXDESC, 17548fe583fSCorentin Labbe &mc->chanlist[i].t_phy, 17648fe583fSCorentin Labbe GFP_KERNEL); 17748fe583fSCorentin Labbe if (!mc->chanlist[i].tl) { 17848fe583fSCorentin Labbe err = -ENOMEM; 17948fe583fSCorentin Labbe goto error_engine; 18048fe583fSCorentin Labbe } 18148fe583fSCorentin Labbe } 18248fe583fSCorentin Labbe return 0; 18348fe583fSCorentin Labbe error_engine: 18448fe583fSCorentin Labbe meson_free_chanlist(mc, i); 18548fe583fSCorentin Labbe return err; 18648fe583fSCorentin Labbe } 18748fe583fSCorentin Labbe 18848fe583fSCorentin Labbe static int meson_register_algs(struct meson_dev *mc) 18948fe583fSCorentin Labbe { 19048fe583fSCorentin Labbe int err, i; 19148fe583fSCorentin Labbe 19248fe583fSCorentin Labbe for (i = 0; i < ARRAY_SIZE(mc_algs); i++) { 19348fe583fSCorentin Labbe mc_algs[i].mc = mc; 19448fe583fSCorentin Labbe switch (mc_algs[i].type) { 19548fe583fSCorentin Labbe case CRYPTO_ALG_TYPE_SKCIPHER: 19648fe583fSCorentin Labbe err = crypto_register_skcipher(&mc_algs[i].alg.skcipher); 19748fe583fSCorentin Labbe if (err) { 19848fe583fSCorentin Labbe dev_err(mc->dev, "Fail to register %s\n", 19948fe583fSCorentin Labbe mc_algs[i].alg.skcipher.base.cra_name); 20048fe583fSCorentin Labbe mc_algs[i].mc = NULL; 20148fe583fSCorentin Labbe return err; 20248fe583fSCorentin Labbe } 20348fe583fSCorentin Labbe break; 20448fe583fSCorentin Labbe } 20548fe583fSCorentin Labbe } 20648fe583fSCorentin Labbe 20748fe583fSCorentin Labbe return 0; 20848fe583fSCorentin Labbe } 20948fe583fSCorentin Labbe 21048fe583fSCorentin Labbe static void meson_unregister_algs(struct meson_dev *mc) 21148fe583fSCorentin Labbe { 21248fe583fSCorentin Labbe int i; 21348fe583fSCorentin Labbe 21448fe583fSCorentin Labbe for (i = 0; i < ARRAY_SIZE(mc_algs); i++) { 21548fe583fSCorentin Labbe if (!mc_algs[i].mc) 21648fe583fSCorentin Labbe continue; 21748fe583fSCorentin Labbe switch (mc_algs[i].type) { 21848fe583fSCorentin Labbe case CRYPTO_ALG_TYPE_SKCIPHER: 21948fe583fSCorentin Labbe crypto_unregister_skcipher(&mc_algs[i].alg.skcipher); 22048fe583fSCorentin Labbe break; 22148fe583fSCorentin Labbe } 22248fe583fSCorentin Labbe } 22348fe583fSCorentin Labbe } 22448fe583fSCorentin Labbe 22548fe583fSCorentin Labbe static int meson_crypto_probe(struct platform_device *pdev) 22648fe583fSCorentin Labbe { 22748fe583fSCorentin Labbe struct meson_dev *mc; 22848fe583fSCorentin Labbe int err, i; 22948fe583fSCorentin Labbe 23048fe583fSCorentin Labbe if (!pdev->dev.of_node) 23148fe583fSCorentin Labbe return -ENODEV; 23248fe583fSCorentin Labbe 23348fe583fSCorentin Labbe mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); 23448fe583fSCorentin Labbe if (!mc) 23548fe583fSCorentin Labbe return -ENOMEM; 23648fe583fSCorentin Labbe 23748fe583fSCorentin Labbe mc->dev = &pdev->dev; 23848fe583fSCorentin Labbe platform_set_drvdata(pdev, mc); 23948fe583fSCorentin Labbe 24048fe583fSCorentin Labbe mc->base = devm_platform_ioremap_resource(pdev, 0); 24148fe583fSCorentin Labbe if (IS_ERR(mc->base)) { 24248fe583fSCorentin Labbe err = PTR_ERR(mc->base); 24348fe583fSCorentin Labbe dev_err(&pdev->dev, "Cannot request MMIO err=%d\n", err); 24448fe583fSCorentin Labbe return err; 24548fe583fSCorentin Labbe } 24648fe583fSCorentin Labbe mc->busclk = devm_clk_get(&pdev->dev, "blkmv"); 24748fe583fSCorentin Labbe if (IS_ERR(mc->busclk)) { 24848fe583fSCorentin Labbe err = PTR_ERR(mc->busclk); 24948fe583fSCorentin Labbe dev_err(&pdev->dev, "Cannot get core clock err=%d\n", err); 25048fe583fSCorentin Labbe return err; 25148fe583fSCorentin Labbe } 25248fe583fSCorentin Labbe 25348fe583fSCorentin Labbe mc->irqs = devm_kcalloc(mc->dev, MAXFLOW, sizeof(int), GFP_KERNEL); 25448fe583fSCorentin Labbe for (i = 0; i < MAXFLOW; i++) { 25548fe583fSCorentin Labbe mc->irqs[i] = platform_get_irq(pdev, i); 25656e0b627STang Bin if (mc->irqs[i] < 0) 25748fe583fSCorentin Labbe return mc->irqs[i]; 25848fe583fSCorentin Labbe 25948fe583fSCorentin Labbe err = devm_request_irq(&pdev->dev, mc->irqs[i], meson_irq_handler, 0, 26048fe583fSCorentin Labbe "gxl-crypto", mc); 26148fe583fSCorentin Labbe if (err < 0) { 26248fe583fSCorentin Labbe dev_err(mc->dev, "Cannot request IRQ for flow %d\n", i); 26348fe583fSCorentin Labbe return err; 26448fe583fSCorentin Labbe } 26548fe583fSCorentin Labbe } 26648fe583fSCorentin Labbe 26748fe583fSCorentin Labbe err = clk_prepare_enable(mc->busclk); 26848fe583fSCorentin Labbe if (err != 0) { 26948fe583fSCorentin Labbe dev_err(&pdev->dev, "Cannot prepare_enable busclk\n"); 27048fe583fSCorentin Labbe return err; 27148fe583fSCorentin Labbe } 27248fe583fSCorentin Labbe 27348fe583fSCorentin Labbe err = meson_allocate_chanlist(mc); 27448fe583fSCorentin Labbe if (err) 27548fe583fSCorentin Labbe goto error_flow; 27648fe583fSCorentin Labbe 27748fe583fSCorentin Labbe err = meson_register_algs(mc); 27848fe583fSCorentin Labbe if (err) 27948fe583fSCorentin Labbe goto error_alg; 28048fe583fSCorentin Labbe 28148fe583fSCorentin Labbe #ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG 28248fe583fSCorentin Labbe mc->dbgfs_dir = debugfs_create_dir("gxl-crypto", NULL); 28348fe583fSCorentin Labbe debugfs_create_file("stats", 0444, mc->dbgfs_dir, mc, &meson_debugfs_fops); 28448fe583fSCorentin Labbe #endif 28548fe583fSCorentin Labbe 28648fe583fSCorentin Labbe return 0; 28748fe583fSCorentin Labbe error_alg: 28848fe583fSCorentin Labbe meson_unregister_algs(mc); 28948fe583fSCorentin Labbe error_flow: 29024775ac2SCorentin Labbe meson_free_chanlist(mc, MAXFLOW - 1); 29148fe583fSCorentin Labbe clk_disable_unprepare(mc->busclk); 29248fe583fSCorentin Labbe return err; 29348fe583fSCorentin Labbe } 29448fe583fSCorentin Labbe 29548fe583fSCorentin Labbe static int meson_crypto_remove(struct platform_device *pdev) 29648fe583fSCorentin Labbe { 29748fe583fSCorentin Labbe struct meson_dev *mc = platform_get_drvdata(pdev); 29848fe583fSCorentin Labbe 29948fe583fSCorentin Labbe #ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG 30048fe583fSCorentin Labbe debugfs_remove_recursive(mc->dbgfs_dir); 30148fe583fSCorentin Labbe #endif 30248fe583fSCorentin Labbe 30348fe583fSCorentin Labbe meson_unregister_algs(mc); 30448fe583fSCorentin Labbe 30524775ac2SCorentin Labbe meson_free_chanlist(mc, MAXFLOW - 1); 30648fe583fSCorentin Labbe 30748fe583fSCorentin Labbe clk_disable_unprepare(mc->busclk); 30848fe583fSCorentin Labbe return 0; 30948fe583fSCorentin Labbe } 31048fe583fSCorentin Labbe 31148fe583fSCorentin Labbe static const struct of_device_id meson_crypto_of_match_table[] = { 31248fe583fSCorentin Labbe { .compatible = "amlogic,gxl-crypto", }, 31348fe583fSCorentin Labbe {} 31448fe583fSCorentin Labbe }; 31548fe583fSCorentin Labbe MODULE_DEVICE_TABLE(of, meson_crypto_of_match_table); 31648fe583fSCorentin Labbe 31748fe583fSCorentin Labbe static struct platform_driver meson_crypto_driver = { 31848fe583fSCorentin Labbe .probe = meson_crypto_probe, 31948fe583fSCorentin Labbe .remove = meson_crypto_remove, 32048fe583fSCorentin Labbe .driver = { 32148fe583fSCorentin Labbe .name = "gxl-crypto", 32248fe583fSCorentin Labbe .of_match_table = meson_crypto_of_match_table, 32348fe583fSCorentin Labbe }, 32448fe583fSCorentin Labbe }; 32548fe583fSCorentin Labbe 32648fe583fSCorentin Labbe module_platform_driver(meson_crypto_driver); 32748fe583fSCorentin Labbe 32848fe583fSCorentin Labbe MODULE_DESCRIPTION("Amlogic GXL cryptographic offloader"); 32948fe583fSCorentin Labbe MODULE_LICENSE("GPL"); 33048fe583fSCorentin Labbe MODULE_AUTHOR("Corentin Labbe <clabbe@baylibre.com>"); 331