Hi Rob, Thanks for the review and comments. I will update and push the patches based on your inputs. Warm regards, PK On Fri, Sep 6, 2024 at 1:30 AM Rob Herring <robh@xxxxxxxxxx> wrote: > > On Thu, Sep 05, 2024 at 05:00:45PM +0530, Pavitrakumar M wrote: > > Add SPAcc Skcipher support to Synopsys Protocol Accelerator(SPAcc) IP, > > which is a crypto accelerator engine. > > SPAcc supports ciphers, hashes and AEAD algorithms such as > > AES in different modes, SHA variants, AES-GCM, Chacha-poly1305 etc. > > > > Signed-off-by: Bhoomika K <bhoomikak@xxxxxxxxxxxxxxx> > > Signed-off-by: Pavitrakumar M <pavitrakumarm@xxxxxxxxxxxxxxx> > > Acked-by: Ruud Derwig <Ruud.Derwig@xxxxxxxxxxxx> > > --- > > drivers/crypto/dwc-spacc/spacc_core.c | 1130 ++++++++++++++++++++ > > drivers/crypto/dwc-spacc/spacc_core.h | 819 ++++++++++++++ > > drivers/crypto/dwc-spacc/spacc_device.c | 304 ++++++ > > drivers/crypto/dwc-spacc/spacc_device.h | 228 ++++ > > drivers/crypto/dwc-spacc/spacc_hal.c | 367 +++++++ > > drivers/crypto/dwc-spacc/spacc_hal.h | 114 ++ > > drivers/crypto/dwc-spacc/spacc_interrupt.c | 317 ++++++ > > drivers/crypto/dwc-spacc/spacc_manager.c | 658 ++++++++++++ > > drivers/crypto/dwc-spacc/spacc_skcipher.c | 716 +++++++++++++ > > 9 files changed, 4653 insertions(+) > > create mode 100644 drivers/crypto/dwc-spacc/spacc_core.c > > create mode 100644 drivers/crypto/dwc-spacc/spacc_core.h > > create mode 100644 drivers/crypto/dwc-spacc/spacc_device.c > > create mode 100644 drivers/crypto/dwc-spacc/spacc_device.h > > create mode 100644 drivers/crypto/dwc-spacc/spacc_hal.c > > create mode 100644 drivers/crypto/dwc-spacc/spacc_hal.h > > create mode 100644 drivers/crypto/dwc-spacc/spacc_interrupt.c > > create mode 100644 drivers/crypto/dwc-spacc/spacc_manager.c > > create mode 100644 drivers/crypto/dwc-spacc/spacc_skcipher.c > > > > diff --git a/drivers/crypto/dwc-spacc/spacc_device.c b/drivers/crypto/dwc-spacc/spacc_device.c > > new file mode 100644 > > index 000000000000..b9b6495fb5e3 > > --- /dev/null > > +++ b/drivers/crypto/dwc-spacc/spacc_device.c > > @@ -0,0 +1,304 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +#include <linux/module.h> > > +#include <linux/interrupt.h> > > +#include <linux/dma-mapping.h> > > +#include <linux/platform_device.h> > > +#include "spacc_device.h" > > + > > +static struct platform_device *spacc_pdev[MAX_DEVICES]; > > Generally drivers aren't limited to some number of instances (except 1 > perhaps). PK: Agreed, will remove this as it's not needed anymore. > > > + > > +#define VSPACC_PRIORITY_MAX 15 > > + > > +void spacc_cmd_process(struct spacc_device *spacc, int x) > > +{ > > + struct spacc_priv *priv = container_of(spacc, struct spacc_priv, spacc); > > + > > + /* run tasklet to pop jobs off fifo */ > > + tasklet_schedule(&priv->pop_jobs); > > +} > > +void spacc_stat_process(struct spacc_device *spacc) > > +{ > > + struct spacc_priv *priv = container_of(spacc, struct spacc_priv, spacc); > > + > > + /* run tasklet to pop jobs off fifo */ > > + tasklet_schedule(&priv->pop_jobs); > > +} > > + > > > +static const struct of_device_id snps_spacc_id[] = { > > + {.compatible = "snps,dwc-spacc" }, > > + { /*sentinel */ } > > +}; > > + > > +MODULE_DEVICE_TABLE(of, snps_spacc_id); > > You can move the table to where it is used since you no longer use it in > spacc_init_device. PK: Will move it. > > > + > > +static int spacc_init_device(struct platform_device *pdev) > > +{ > > + int vspacc_idx = -1; > > + struct resource *mem; > > + void __iomem *baseaddr; > > + struct pdu_info info; > > + int vspacc_priority = -1; > > + struct spacc_priv *priv; > > + int x = 0, err, oldmode, irq_num; > > + u64 oldtimer = 100000, timer = 100000; > > + > > + /* Initialize DDT DMA pools based on this device's resources */ > > + if (pdu_mem_init(&pdev->dev)) { > > + dev_err(&pdev->dev, "Could not initialize DMA pools\n"); > > + return -ENOMEM; > > + } > > + > > + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > You don't need this as devm_platform_get_and_ioremap_resource() does > this and more. PK: Will fix it. > > > + if (!mem) { > > + dev_err(&pdev->dev, "no memory resource for spacc\n"); > > + err = -ENXIO; > > + goto free_ddt_mem_pool; > > + } > > + > > + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); > > + if (!priv) { > > + err = -ENOMEM; > > + goto free_ddt_mem_pool; > > + } > > + > > + /* Read spacc priority and index and save inside priv.spacc.config */ > > + if (of_property_read_u32(pdev->dev.of_node, "vspacc-priority", > > + &vspacc_priority)) { > > + dev_err(&pdev->dev, "No virtual spacc priority specified\n"); > > + err = -EINVAL; > > + goto free_ddt_mem_pool; > > + } > > + > > + if (vspacc_priority < 0 && vspacc_priority > VSPACC_PRIORITY_MAX) { > > + dev_err(&pdev->dev, "Invalid virtual spacc priority\n"); > > + err = -EINVAL; > > + goto free_ddt_mem_pool; > > + } > > + priv->spacc.config.priority = vspacc_priority; > > + > > + if (of_property_read_u32(pdev->dev.of_node, "vspacc-index", > > + &vspacc_idx)) { > > + dev_err(&pdev->dev, "No virtual spacc index specified\n"); > > This property was not required in the binding, so why does the driver > require it? PK: I will change it to virtual spacc ID (vspacc-id) as explained in DT bindings patch > > > + err = -EINVAL; > > + goto free_ddt_mem_pool; > > + } > > + priv->spacc.config.idx = vspacc_idx; > > + > > + priv->spacc.config.spacc_endian = of_property_read_bool( > > + pdev->dev.of_node, "little-endian"); > > Lack of "little-endian" doesn't equal BE. PK: Agreed. All testing is done on Little endian CPUs. Will add BE support based on the platforms. > > > > + > > + priv->spacc.config.oldtimer = oldtimer; > > + > > + if (of_property_read_u64(pdev->dev.of_node, "spacc-wdtimer", &timer)) { > > + dev_dbg(&pdev->dev, "No spacc wdtimer specified\n"); > > + dev_dbg(&pdev->dev, "Default wdtimer: (100000)\n"); > > + timer = 100000; > > + } > > + priv->spacc.config.timer = timer; > > + > > + baseaddr = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); > > You never use 'mem' that I see, so use devm_platform_ioremap_resource() > instead. PK: Will fix it. > > > + if (IS_ERR(baseaddr)) { > > + dev_err(&pdev->dev, "unable to map iomem\n"); > > + err = PTR_ERR(baseaddr); > > + goto free_ddt_mem_pool; > > + } > > + > > + pdu_get_version(baseaddr, &info); > > + > > + dev_dbg(&pdev->dev, "EPN %04X : virt [%d]\n", > > + info.spacc_version.project, > > + info.spacc_version.vspacc_idx); > > + > > + /* Validate virtual spacc index with vspacc count read from > > + * VERSION_EXT.VSPACC_CNT. Thus vspacc count=3, gives valid index 0,1,2 > > + */ > > + if (vspacc_idx != info.spacc_version.vspacc_idx) { > > + dev_err(&pdev->dev, "DTS vspacc_idx mismatch read value\n"); > > + err = -EINVAL; > > + goto free_ddt_mem_pool; > > + } > > + > > + if (vspacc_idx < 0 || vspacc_idx > (info.spacc_config.num_vspacc - 1)) { > > + dev_err(&pdev->dev, "Invalid vspacc index specified\n"); > > + err = -EINVAL; > > + goto free_ddt_mem_pool; > > + } > > + > > + err = spacc_init(baseaddr, &priv->spacc, &info); > > + if (err != CRYPTO_OK) { > > + dev_err(&pdev->dev, "Failed to initialize device %d\n", x); > > + err = -ENXIO; > > + goto free_ddt_mem_pool; > > + } > > + > > + spin_lock_init(&priv->hw_lock); > > + spacc_irq_glbl_disable(&priv->spacc); > > + tasklet_init(&priv->pop_jobs, spacc_pop_jobs, (unsigned long)priv); > > + > > + priv->spacc.dptr = &pdev->dev; > > + platform_set_drvdata(pdev, priv); > > + > > + irq_num = platform_get_irq(pdev, 0); > > + if (irq_num < 0) { > > + dev_err(&pdev->dev, "no irq resource for spacc\n"); > > + err = -ENXIO; > > + goto free_ddt_mem_pool; > > + } > > + > > + /* Determine configured maximum message length. */ > > + priv->max_msg_len = priv->spacc.config.max_msg_size; > > + > > + if (devm_request_irq(&pdev->dev, irq_num, spacc_irq_handler, > > + IRQF_SHARED, dev_name(&pdev->dev), > > + &pdev->dev)) { > > + dev_err(&pdev->dev, "failed to request IRQ\n"); > > + err = -EBUSY; > > + goto err_tasklet_kill; > > + } > > + > > + priv->spacc.irq_cb_stat = spacc_stat_process; > > + priv->spacc.irq_cb_cmdx = spacc_cmd_process; > > + oldmode = priv->spacc.op_mode; > > + priv->spacc.op_mode = SPACC_OP_MODE_IRQ; > > + > > + spacc_irq_stat_enable(&priv->spacc, 1); > > + spacc_irq_cmdx_enable(&priv->spacc, 0, 1); > > + spacc_irq_stat_wd_disable(&priv->spacc); > > + spacc_irq_glbl_enable(&priv->spacc); > > + > > + > > +#if IS_ENABLED(CONFIG_CRYPTO_DEV_SPACC_AUTODETECT) > > + err = spacc_autodetect(&priv->spacc); > > + if (err < 0) { > > + spacc_irq_glbl_disable(&priv->spacc); > > + goto err_tasklet_kill; > > + } > > +#else > > + err = spacc_static_config(&priv->spacc); > > + if (err < 0) { > > + spacc_irq_glbl_disable(&priv->spacc); > > + goto err_tasklet_kill; > > + } > > +#endif > > + > > + priv->spacc.op_mode = oldmode; > > + > > + if (priv->spacc.op_mode == SPACC_OP_MODE_IRQ) { > > + priv->spacc.irq_cb_stat = spacc_stat_process; > > + priv->spacc.irq_cb_cmdx = spacc_cmd_process; > > + > > + spacc_irq_stat_enable(&priv->spacc, 1); > > + spacc_irq_cmdx_enable(&priv->spacc, 0, 1); > > + spacc_irq_glbl_enable(&priv->spacc); > > + } else { > > + priv->spacc.irq_cb_stat = spacc_stat_process; > > + priv->spacc.irq_cb_stat_wd = spacc_stat_process; > > + > > + spacc_irq_stat_enable(&priv->spacc, > > + priv->spacc.config.ideal_stat_level); > > + > > + spacc_irq_cmdx_disable(&priv->spacc, 0); > > + spacc_irq_stat_wd_enable(&priv->spacc); > > + spacc_irq_glbl_enable(&priv->spacc); > > + > > + /* enable the wd by setting the wd_timer = 100000 */ > > + spacc_set_wd_count(&priv->spacc, > > + priv->spacc.config.wd_timer = > > + priv->spacc.config.timer); > > + } > > + > > + /* unlock normal*/ > > + if (priv->spacc.config.is_secure_port) { > > + u32 t; > > + > > + t = readl(baseaddr + SPACC_REG_SECURE_CTRL); > > + t &= ~(1UL << 31); > > + writel(t, baseaddr + SPACC_REG_SECURE_CTRL); > > + } > > + > > + /* unlock device by default */ > > + writel(0, baseaddr + SPACC_REG_SECURE_CTRL); > > So writel/readl are always little endian (because PCI is always LE). > Either you aren't handling endianness or you are using "little-endian" > to refer to something else besides the registers? PK: The internal "sg DMA" and the "Context Memory" needs to know the endianness. We will default to little endian. If the big-endian support comes, it will come with a "big-endian" property in DT bindings. > > > + > > + return err; > > + > > +err_tasklet_kill: > > + tasklet_kill(&priv->pop_jobs); > > + spacc_fini(&priv->spacc); > > + > > +free_ddt_mem_pool: > > + pdu_mem_deinit(&pdev->dev); > > + > > + return err; > > +} > > + > > +static void spacc_unregister_algs(void) > > +{ > > +#if IS_ENABLED(CONFIG_CRYPTO_DEV_SPACC_HASH) > > + spacc_unregister_hash_algs(); > > +#endif > > +#if IS_ENABLED(CONFIG_CRYPTO_DEV_SPACC_AEAD) > > + spacc_unregister_aead_algs(); > > +#endif > > +#if IS_ENABLED(CONFIG_CRYPTO_DEV_SPACC_CIPHER) > > + spacc_unregister_cipher_algs(); > > +#endif > > +} > > + > > + > > +static int spacc_crypto_probe(struct platform_device *pdev) > > +{ > > + int rc; > > + > > + rc = spacc_init_device(pdev); > > + if (rc < 0) > > + goto err; > > + > > + spacc_pdev[0] = pdev; > > You have an array of devices, but always write to index 0? PK: This array will be removed, its a stale design. The vSPAccs are handled differently. > > > + > > +#if IS_ENABLED(CONFIG_CRYPTO_DEV_SPACC_HASH) > > + rc = probe_hashes(pdev); > > + if (rc < 0) > > + goto err; > > +#endif > > + > > +#if IS_ENABLED(CONFIG_CRYPTO_DEV_SPACC_CIPHER) > > + rc = probe_ciphers(pdev); > > + if (rc < 0) > > + goto err; > > +#endif > > + > > +#if IS_ENABLED(CONFIG_CRYPTO_DEV_SPACC_AEAD) > > + rc = probe_aeads(pdev); > > + if (rc < 0) > > + goto err; > > +#endif > > + > > + return 0; > > +err: > > + spacc_unregister_algs(); > > + > > + return rc; > > +} > > + > > +static void spacc_crypto_remove(struct platform_device *pdev) > > +{ > > + spacc_unregister_algs(); > > + spacc_remove(pdev); > > +} > > + > > +static struct platform_driver spacc_driver = { > > + .probe = spacc_crypto_probe, > > + .remove = spacc_crypto_remove, > > + .driver = { > > + .name = "spacc", > > + .of_match_table = snps_spacc_id, > > + .owner = THIS_MODULE, > > + }, > > +}; > > + > > +module_platform_driver(spacc_driver); > > + > > +MODULE_LICENSE("GPL"); > > +MODULE_AUTHOR("Synopsys, Inc."); > > +MODULE_DESCRIPTION("SPAcc Crypto Accelerator Driver"); > > diff --git a/drivers/crypto/dwc-spacc/spacc_device.h b/drivers/crypto/dwc-spacc/spacc_device.h > > new file mode 100644 > > index 000000000000..2223c3cfcf18 > > --- /dev/null > > +++ b/drivers/crypto/dwc-spacc/spacc_device.h > > @@ -0,0 +1,228 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > + > > +#ifndef SPACC_DEVICE_H_ > > +#define SPACC_DEVICE_H_ > > + > > +#include <crypto/hash.h> > > +#include <crypto/ctr.h> > > +#include <crypto/internal/aead.h> > > +#include <linux/of.h> > > +#include "spacc_core.h" > > + > > +#define MODE_TAB_AEAD(_name, _ciph, _hash, _hashlen, _ivlen, _blocklen) \ > > + .name = _name, .aead = { .ciph = _ciph, .hash = _hash }, \ > > + .hashlen = _hashlen, .ivlen = _ivlen, .blocklen = _blocklen > > + > > +/* Helper macros for initializing the hash/cipher tables. */ > > +#define MODE_TAB_COMMON(_name, _id_name, _blocklen) \ > > + .name = _name, .id = CRYPTO_MODE_##_id_name, .blocklen = _blocklen > > + > > +#define MODE_TAB_HASH(_name, _id_name, _hashlen, _blocklen) \ > > + MODE_TAB_COMMON(_name, _id_name, _blocklen), \ > > + .hashlen = _hashlen, .testlen = _hashlen > > + > > +#define MODE_TAB_CIPH(_name, _id_name, _ivlen, _blocklen) \ > > + MODE_TAB_COMMON(_name, _id_name, _blocklen), \ > > + .ivlen = _ivlen > > + > > +#define MODE_TAB_HASH_XCBC 0x8000 > > + > > +#define SPACC_MAX_DIGEST_SIZE 64 > > +#define SPACC_MAX_KEY_SIZE 32 > > +#define SPACC_MAX_IV_SIZE 16 > > + > > +#define SPACC_DMA_ALIGN 4 > > +#define SPACC_DMA_BOUNDARY 0x10000 > > + > > +#define MAX_DEVICES 2 > > +/* flag means the IV is computed from setkey and crypt*/ > > +#define SPACC_MANGLE_IV_FLAG 0x8000 > > + > > +/* we're doing a CTR mangle (for RFC3686/IPsec)*/ > > +#define SPACC_MANGLE_IV_RFC3686 0x0100 > > + > > +/* we're doing GCM */ > > +#define SPACC_MANGLE_IV_RFC4106 0x0200 > > + > > +/* we're doing GMAC */ > > +#define SPACC_MANGLE_IV_RFC4543 0x0300 > > + > > +/* we're doing CCM */ > > +#define SPACC_MANGLE_IV_RFC4309 0x0400 > > + > > +/* we're doing SM4 GCM/CCM */ > > +#define SPACC_MANGLE_IV_RFC8998 0x0500 > > + > > +#define CRYPTO_MODE_AES_CTR_RFC3686 (CRYPTO_MODE_AES_CTR \ > > + | SPACC_MANGLE_IV_FLAG \ > > + | SPACC_MANGLE_IV_RFC3686) > > +#define CRYPTO_MODE_AES_GCM_RFC4106 (CRYPTO_MODE_AES_GCM \ > > + | SPACC_MANGLE_IV_FLAG \ > > + | SPACC_MANGLE_IV_RFC4106) > > +#define CRYPTO_MODE_AES_GCM_RFC4543 (CRYPTO_MODE_AES_GCM \ > > + | SPACC_MANGLE_IV_FLAG \ > > + | SPACC_MANGLE_IV_RFC4543) > > +#define CRYPTO_MODE_AES_CCM_RFC4309 (CRYPTO_MODE_AES_CCM \ > > + | SPACC_MANGLE_IV_FLAG \ > > + | SPACC_MANGLE_IV_RFC4309) > > +#define CRYPTO_MODE_SM4_GCM_RFC8998 (CRYPTO_MODE_SM4_GCM) > > +#define CRYPTO_MODE_SM4_CCM_RFC8998 (CRYPTO_MODE_SM4_CCM) > > + > > +struct spacc_crypto_ctx { > > + struct device *dev; > > + > > + spinlock_t lock; > > + struct list_head jobs; > > + int handle, mode, auth_size, key_len; > > + unsigned char *cipher_key; > > + > > + /* > > + * Indicates that the H/W context has been setup and can be used for > > + * crypto; otherwise, the software fallback will be used. > > + */ > > + bool ctx_valid; > > + unsigned int flag_ppp; > > + > > + /* salt used for rfc3686/givencrypt mode */ > > + unsigned char csalt[16]; > > + u8 ipad[128] __aligned(sizeof(u32)); > > + u8 digest_ctx_buf[128] __aligned(sizeof(u32)); > > + u8 tmp_buffer[128] __aligned(sizeof(u32)); > > + > > + /* Save keylen from setkey */ > > + int keylen; > > + u8 key[256]; > > + int zero_key; > > + unsigned char *tmp_sgl_buff; > > + struct scatterlist *tmp_sgl; > > + > > + union{ > > + struct crypto_ahash *hash; > > + struct crypto_aead *aead; > > + struct crypto_skcipher *cipher; > > + } fb; > > +}; > > + > > +struct spacc_crypto_reqctx { > > + struct pdu_ddt src, dst; > > + void *digest_buf, *iv_buf; > > + dma_addr_t digest_dma; > > + int dst_nents, src_nents, aead_nents, total_nents; > > + int encrypt_op, mode, single_shot; > > + unsigned int spacc_cipher_cryptlen, rem_nents; > > + > > + struct aead_cb_data { > > + int new_handle; > > + struct spacc_crypto_ctx *tctx; > > + struct spacc_crypto_reqctx *ctx; > > + struct aead_request *req; > > + struct spacc_device *spacc; > > + } cb; > > + > > + struct ahash_cb_data { > > + int new_handle; > > + struct spacc_crypto_ctx *tctx; > > + struct spacc_crypto_reqctx *ctx; > > + struct ahash_request *req; > > + struct spacc_device *spacc; > > + } acb; > > + > > + struct cipher_cb_data { > > + int new_handle; > > + struct spacc_crypto_ctx *tctx; > > + struct spacc_crypto_reqctx *ctx; > > + struct skcipher_request *req; > > + struct spacc_device *spacc; > > + } ccb; > > + > > + union { > > + struct ahash_request hash_req; > > + struct skcipher_request cipher_req; > > + struct aead_request aead_req; > > + } fb; > > +}; > > + > > +struct mode_tab { > > + char name[128]; > > + > > + int valid; > > + > > + /* mode ID used in hash/cipher mode but not aead*/ > > + int id; > > + > > + /* ciph/hash mode used in aead */ > > + struct { > > + int ciph, hash; > > + } aead; > > + > > + unsigned int hashlen, ivlen, blocklen, keylen[3]; > > + unsigned int keylen_mask, testlen; > > + unsigned int chunksize, walksize, min_keysize, max_keysize; > > + > > + bool sw_fb; > > + > > + union { > > + unsigned char hash_test[SPACC_MAX_DIGEST_SIZE]; > > + unsigned char ciph_test[3][2 * SPACC_MAX_IV_SIZE]; > > + }; > > +}; > > + > > +struct spacc_alg { > > + struct mode_tab *mode; > > + unsigned int keylen_mask; > > + > > + struct device *dev[MAX_DEVICES]; > > + > > + struct list_head list; > > + struct crypto_alg *calg; > > + struct crypto_tfm *tfm; > > + > > + union { > > + struct ahash_alg hash; > > + struct aead_alg aead; > > + struct skcipher_alg skcipher; > > + } alg; > > +}; > > + > > +static inline const struct spacc_alg *spacc_tfm_ahash(struct crypto_tfm *tfm) > > +{ > > + const struct crypto_alg *calg = tfm->__crt_alg; > > + > > + if ((calg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH) > > + return container_of(calg, struct spacc_alg, alg.hash.halg.base); > > + > > + return NULL; > > +} > > + > > +static inline const struct spacc_alg *spacc_tfm_skcipher(struct crypto_tfm *tfm) > > +{ > > + const struct crypto_alg *calg = tfm->__crt_alg; > > + > > + if ((calg->cra_flags & CRYPTO_ALG_TYPE_MASK) == > > + CRYPTO_ALG_TYPE_SKCIPHER) > > + return container_of(calg, struct spacc_alg, alg.skcipher.base); > > + > > + return NULL; > > +} > > + > > +static inline const struct spacc_alg *spacc_tfm_aead(struct crypto_tfm *tfm) > > +{ > > + const struct crypto_alg *calg = tfm->__crt_alg; > > + > > + if ((calg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AEAD) > > + return container_of(calg, struct spacc_alg, alg.aead.base); > > + > > + return NULL; > > +} > > + > > +int probe_hashes(struct platform_device *spacc_pdev); > > +int spacc_unregister_hash_algs(void); > > + > > +int probe_aeads(struct platform_device *spacc_pdev); > > +int spacc_unregister_aead_algs(void); > > + > > +int probe_ciphers(struct platform_device *spacc_pdev); > > +int spacc_unregister_cipher_algs(void); > > + > > +irqreturn_t spacc_irq_handler(int irq, void *dev); > > +#endif > > diff --git a/drivers/crypto/dwc-spacc/spacc_hal.c b/drivers/crypto/dwc-spacc/spacc_hal.c > > new file mode 100644 > > index 000000000000..0d460c4df542 > > --- /dev/null > > +++ b/drivers/crypto/dwc-spacc/spacc_hal.c > > @@ -0,0 +1,367 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +#include <linux/dmapool.h> > > +#include <linux/dma-mapping.h> > > +#include "spacc_hal.h" > > + > > +static struct dma_pool *ddt_pool, *ddt16_pool, *ddt4_pool; > > +static struct device *ddt_device; > > + > > +#define PDU_REG_SPACC_VERSION 0x00180UL > > +#define PDU_REG_SPACC_CONFIG 0x00184UL > > +#define PDU_REG_SPACC_CONFIG2 0x00190UL > > +#define PDU_REG_SPACC_IV_OFFSET 0x00040UL > > +#define PDU_REG_PDU_CONFIG 0x00188UL > > +#define PDU_REG_SECURE_LOCK 0x001C0UL > > + > > +int pdu_get_version(void __iomem *dev, struct pdu_info *inf) > > +{ > > + unsigned long tmp; > > + > > + if (!inf) > > + return -1; > > + > > + memset(inf, 0, sizeof(*inf)); > > + tmp = readl(dev + PDU_REG_SPACC_VERSION); > > + > > + /* Read the SPAcc version block this tells us the revision, > > + * project, and a few other feature bits > > + * > > + * layout for v6.5+ > > + */ > > + inf->spacc_version = (struct spacc_version_block) { > > + .minor = SPACC_ID_MINOR(tmp), > > + .major = SPACC_ID_MAJOR(tmp), > > + .version = (SPACC_ID_MAJOR(tmp) << 4) | SPACC_ID_MINOR(tmp), > > + .qos = SPACC_ID_QOS(tmp), > > + .is_spacc = SPACC_ID_TYPE(tmp) == SPACC_TYPE_SPACCQOS, > > + .is_pdu = SPACC_ID_TYPE(tmp) == SPACC_TYPE_PDU, > > + .aux = SPACC_ID_AUX(tmp), > > + .vspacc_idx = SPACC_ID_VIDX(tmp), > > + .partial = SPACC_ID_PARTIAL(tmp), > > + .project = SPACC_ID_PROJECT(tmp), > > + }; > > + > > + /* try to autodetect */ > > + writel(0x80000000, dev + PDU_REG_SPACC_IV_OFFSET); > > + > > + if (readl(dev + PDU_REG_SPACC_IV_OFFSET) == 0x80000000) > > + inf->spacc_version.ivimport = 1; > > + else > > + inf->spacc_version.ivimport = 0; > > + > > + > > + /* Read the SPAcc config block (v6.5+) which tells us how many > > + * contexts there are and context page sizes > > + * this register is only available in v6.5 and up > > + */ > > + tmp = readl(dev + PDU_REG_SPACC_CONFIG); > > + inf->spacc_config = (struct spacc_config_block) { > > + SPACC_CFG_CTX_CNT(tmp), > > + SPACC_CFG_VSPACC_CNT(tmp), > > + SPACC_CFG_CIPH_CTX_SZ(tmp), > > + SPACC_CFG_HASH_CTX_SZ(tmp), > > + SPACC_CFG_DMA_TYPE(tmp), > > + 0, 0, 0, 0 > > + }; > > + > > + /* CONFIG2 only present in v6.5+ cores */ > > + tmp = readl(dev + PDU_REG_SPACC_CONFIG2); > > + if (inf->spacc_version.qos) { > > + inf->spacc_config.cmd0_fifo_depth = > > + SPACC_CFG_CMD0_FIFO_QOS(tmp); > > + inf->spacc_config.cmd1_fifo_depth = > > + SPACC_CFG_CMD1_FIFO(tmp); > > + inf->spacc_config.cmd2_fifo_depth = > > + SPACC_CFG_CMD2_FIFO(tmp); > > + inf->spacc_config.stat_fifo_depth = > > + SPACC_CFG_STAT_FIFO_QOS(tmp); > > + } else { > > + inf->spacc_config.cmd0_fifo_depth = > > + SPACC_CFG_CMD0_FIFO(tmp); > > + inf->spacc_config.stat_fifo_depth = > > + SPACC_CFG_STAT_FIFO(tmp); > > + } > > + > > + /* only read PDU config if it's actually a PDU engine */ > > + if (inf->spacc_version.is_pdu) { > > + tmp = readl(dev + PDU_REG_PDU_CONFIG); > > + inf->pdu_config = (struct pdu_config_block) > > + {SPACC_PDU_CFG_MINOR(tmp), > > + SPACC_PDU_CFG_MAJOR(tmp)}; > > + > > + /* unlock all cores by default */ > > + writel(0, dev + PDU_REG_SECURE_LOCK); > > + } > > + > > + return 0; > > +} > > + > > +void pdu_to_dev(void __iomem *addr_, uint32_t *src, unsigned long nword) > > +{ > > + void __iomem *addr = addr_; > > + > > + while (nword--) { > > + writel(*src++, addr); > > + addr += 4; > > + } > > +} > > + > > +void pdu_from_dev(u32 *dst, void __iomem *addr_, unsigned long nword) > > +{ > > + void __iomem *addr = addr_; > > + > > + while (nword--) { > > + *dst++ = readl(addr); > > + addr += 4; > > + } > > +} > > + > > +static void pdu_to_dev_big(void __iomem *addr_, const unsigned char *src, > > + unsigned long nword) > > +{ > > + unsigned long v; > > + void __iomem *addr = addr_; > > + > > + while (nword--) { > > + v = 0; > > + v = (v << 8) | ((unsigned long)*src++); > > + v = (v << 8) | ((unsigned long)*src++); > > + v = (v << 8) | ((unsigned long)*src++); > > + v = (v << 8) | ((unsigned long)*src++); > > The kernel has helpers for endian conversion and types that define > endianness of buffers (e.g. __be32). Use them. PK: Will fix it. > > > + writel(v, addr); > > + addr += 4; > > + } > > +}