cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

stm32-crc32.c (11986B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) STMicroelectronics SA 2017
      4 * Author: Fabien Dessenne <fabien.dessenne@st.com>
      5 */
      6
      7#include <linux/bitrev.h>
      8#include <linux/clk.h>
      9#include <linux/crc32.h>
     10#include <linux/crc32poly.h>
     11#include <linux/io.h>
     12#include <linux/kernel.h>
     13#include <linux/module.h>
     14#include <linux/mod_devicetable.h>
     15#include <linux/platform_device.h>
     16#include <linux/pm_runtime.h>
     17
     18#include <crypto/internal/hash.h>
     19
     20#include <asm/unaligned.h>
     21
     22#define DRIVER_NAME             "stm32-crc32"
     23#define CHKSUM_DIGEST_SIZE      4
     24#define CHKSUM_BLOCK_SIZE       1
     25
     26/* Registers */
     27#define CRC_DR                  0x00000000
     28#define CRC_CR                  0x00000008
     29#define CRC_INIT                0x00000010
     30#define CRC_POL                 0x00000014
     31
     32/* Registers values */
     33#define CRC_CR_RESET            BIT(0)
     34#define CRC_CR_REV_IN_WORD      (BIT(6) | BIT(5))
     35#define CRC_CR_REV_IN_BYTE      BIT(5)
     36#define CRC_CR_REV_OUT          BIT(7)
     37#define CRC32C_INIT_DEFAULT     0xFFFFFFFF
     38
     39#define CRC_AUTOSUSPEND_DELAY	50
     40
     41static unsigned int burst_size;
     42module_param(burst_size, uint, 0644);
     43MODULE_PARM_DESC(burst_size, "Select burst byte size (0 unlimited)");
     44
     45struct stm32_crc {
     46	struct list_head list;
     47	struct device    *dev;
     48	void __iomem     *regs;
     49	struct clk       *clk;
     50	spinlock_t       lock;
     51};
     52
     53struct stm32_crc_list {
     54	struct list_head dev_list;
     55	spinlock_t       lock; /* protect dev_list */
     56};
     57
     58static struct stm32_crc_list crc_list = {
     59	.dev_list = LIST_HEAD_INIT(crc_list.dev_list),
     60	.lock     = __SPIN_LOCK_UNLOCKED(crc_list.lock),
     61};
     62
     63struct stm32_crc_ctx {
     64	u32 key;
     65	u32 poly;
     66};
     67
     68struct stm32_crc_desc_ctx {
     69	u32    partial; /* crc32c: partial in first 4 bytes of that struct */
     70};
     71
     72static int stm32_crc32_cra_init(struct crypto_tfm *tfm)
     73{
     74	struct stm32_crc_ctx *mctx = crypto_tfm_ctx(tfm);
     75
     76	mctx->key = 0;
     77	mctx->poly = CRC32_POLY_LE;
     78	return 0;
     79}
     80
     81static int stm32_crc32c_cra_init(struct crypto_tfm *tfm)
     82{
     83	struct stm32_crc_ctx *mctx = crypto_tfm_ctx(tfm);
     84
     85	mctx->key = CRC32C_INIT_DEFAULT;
     86	mctx->poly = CRC32C_POLY_LE;
     87	return 0;
     88}
     89
     90static int stm32_crc_setkey(struct crypto_shash *tfm, const u8 *key,
     91			    unsigned int keylen)
     92{
     93	struct stm32_crc_ctx *mctx = crypto_shash_ctx(tfm);
     94
     95	if (keylen != sizeof(u32))
     96		return -EINVAL;
     97
     98	mctx->key = get_unaligned_le32(key);
     99	return 0;
    100}
    101
    102static struct stm32_crc *stm32_crc_get_next_crc(void)
    103{
    104	struct stm32_crc *crc;
    105
    106	spin_lock_bh(&crc_list.lock);
    107	crc = list_first_entry(&crc_list.dev_list, struct stm32_crc, list);
    108	if (crc)
    109		list_move_tail(&crc->list, &crc_list.dev_list);
    110	spin_unlock_bh(&crc_list.lock);
    111
    112	return crc;
    113}
    114
    115static int stm32_crc_init(struct shash_desc *desc)
    116{
    117	struct stm32_crc_desc_ctx *ctx = shash_desc_ctx(desc);
    118	struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm);
    119	struct stm32_crc *crc;
    120	unsigned long flags;
    121
    122	crc = stm32_crc_get_next_crc();
    123	if (!crc)
    124		return -ENODEV;
    125
    126	pm_runtime_get_sync(crc->dev);
    127
    128	spin_lock_irqsave(&crc->lock, flags);
    129
    130	/* Reset, set key, poly and configure in bit reverse mode */
    131	writel_relaxed(bitrev32(mctx->key), crc->regs + CRC_INIT);
    132	writel_relaxed(bitrev32(mctx->poly), crc->regs + CRC_POL);
    133	writel_relaxed(CRC_CR_RESET | CRC_CR_REV_IN_WORD | CRC_CR_REV_OUT,
    134		       crc->regs + CRC_CR);
    135
    136	/* Store partial result */
    137	ctx->partial = readl_relaxed(crc->regs + CRC_DR);
    138
    139	spin_unlock_irqrestore(&crc->lock, flags);
    140
    141	pm_runtime_mark_last_busy(crc->dev);
    142	pm_runtime_put_autosuspend(crc->dev);
    143
    144	return 0;
    145}
    146
    147static int burst_update(struct shash_desc *desc, const u8 *d8,
    148			size_t length)
    149{
    150	struct stm32_crc_desc_ctx *ctx = shash_desc_ctx(desc);
    151	struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm);
    152	struct stm32_crc *crc;
    153
    154	crc = stm32_crc_get_next_crc();
    155	if (!crc)
    156		return -ENODEV;
    157
    158	pm_runtime_get_sync(crc->dev);
    159
    160	if (!spin_trylock(&crc->lock)) {
    161		/* Hardware is busy, calculate crc32 by software */
    162		if (mctx->poly == CRC32_POLY_LE)
    163			ctx->partial = crc32_le(ctx->partial, d8, length);
    164		else
    165			ctx->partial = __crc32c_le(ctx->partial, d8, length);
    166
    167		goto pm_out;
    168	}
    169
    170	/*
    171	 * Restore previously calculated CRC for this context as init value
    172	 * Restore polynomial configuration
    173	 * Configure in register for word input data,
    174	 * Configure out register in reversed bit mode data.
    175	 */
    176	writel_relaxed(bitrev32(ctx->partial), crc->regs + CRC_INIT);
    177	writel_relaxed(bitrev32(mctx->poly), crc->regs + CRC_POL);
    178	writel_relaxed(CRC_CR_RESET | CRC_CR_REV_IN_WORD | CRC_CR_REV_OUT,
    179		       crc->regs + CRC_CR);
    180
    181	if (d8 != PTR_ALIGN(d8, sizeof(u32))) {
    182		/* Configure for byte data */
    183		writel_relaxed(CRC_CR_REV_IN_BYTE | CRC_CR_REV_OUT,
    184			       crc->regs + CRC_CR);
    185		while (d8 != PTR_ALIGN(d8, sizeof(u32)) && length) {
    186			writeb_relaxed(*d8++, crc->regs + CRC_DR);
    187			length--;
    188		}
    189		/* Configure for word data */
    190		writel_relaxed(CRC_CR_REV_IN_WORD | CRC_CR_REV_OUT,
    191			       crc->regs + CRC_CR);
    192	}
    193
    194	for (; length >= sizeof(u32); d8 += sizeof(u32), length -= sizeof(u32))
    195		writel_relaxed(*((u32 *)d8), crc->regs + CRC_DR);
    196
    197	if (length) {
    198		/* Configure for byte data */
    199		writel_relaxed(CRC_CR_REV_IN_BYTE | CRC_CR_REV_OUT,
    200			       crc->regs + CRC_CR);
    201		while (length--)
    202			writeb_relaxed(*d8++, crc->regs + CRC_DR);
    203	}
    204
    205	/* Store partial result */
    206	ctx->partial = readl_relaxed(crc->regs + CRC_DR);
    207
    208	spin_unlock(&crc->lock);
    209
    210pm_out:
    211	pm_runtime_mark_last_busy(crc->dev);
    212	pm_runtime_put_autosuspend(crc->dev);
    213
    214	return 0;
    215}
    216
    217static int stm32_crc_update(struct shash_desc *desc, const u8 *d8,
    218			    unsigned int length)
    219{
    220	const unsigned int burst_sz = burst_size;
    221	unsigned int rem_sz;
    222	const u8 *cur;
    223	size_t size;
    224	int ret;
    225
    226	if (!burst_sz)
    227		return burst_update(desc, d8, length);
    228
    229	/* Digest first bytes not 32bit aligned at first pass in the loop */
    230	size = min_t(size_t, length, burst_sz + (size_t)d8 -
    231				     ALIGN_DOWN((size_t)d8, sizeof(u32)));
    232	for (rem_sz = length, cur = d8; rem_sz;
    233	     rem_sz -= size, cur += size, size = min(rem_sz, burst_sz)) {
    234		ret = burst_update(desc, cur, size);
    235		if (ret)
    236			return ret;
    237	}
    238
    239	return 0;
    240}
    241
    242static int stm32_crc_final(struct shash_desc *desc, u8 *out)
    243{
    244	struct stm32_crc_desc_ctx *ctx = shash_desc_ctx(desc);
    245	struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm);
    246
    247	/* Send computed CRC */
    248	put_unaligned_le32(mctx->poly == CRC32C_POLY_LE ?
    249			   ~ctx->partial : ctx->partial, out);
    250
    251	return 0;
    252}
    253
    254static int stm32_crc_finup(struct shash_desc *desc, const u8 *data,
    255			   unsigned int length, u8 *out)
    256{
    257	return stm32_crc_update(desc, data, length) ?:
    258	       stm32_crc_final(desc, out);
    259}
    260
    261static int stm32_crc_digest(struct shash_desc *desc, const u8 *data,
    262			    unsigned int length, u8 *out)
    263{
    264	return stm32_crc_init(desc) ?: stm32_crc_finup(desc, data, length, out);
    265}
    266
    267static unsigned int refcnt;
    268static DEFINE_MUTEX(refcnt_lock);
    269static struct shash_alg algs[] = {
    270	/* CRC-32 */
    271	{
    272		.setkey         = stm32_crc_setkey,
    273		.init           = stm32_crc_init,
    274		.update         = stm32_crc_update,
    275		.final          = stm32_crc_final,
    276		.finup          = stm32_crc_finup,
    277		.digest         = stm32_crc_digest,
    278		.descsize       = sizeof(struct stm32_crc_desc_ctx),
    279		.digestsize     = CHKSUM_DIGEST_SIZE,
    280		.base           = {
    281			.cra_name               = "crc32",
    282			.cra_driver_name        = "stm32-crc32-crc32",
    283			.cra_priority           = 200,
    284			.cra_flags		= CRYPTO_ALG_OPTIONAL_KEY,
    285			.cra_blocksize          = CHKSUM_BLOCK_SIZE,
    286			.cra_alignmask          = 3,
    287			.cra_ctxsize            = sizeof(struct stm32_crc_ctx),
    288			.cra_module             = THIS_MODULE,
    289			.cra_init               = stm32_crc32_cra_init,
    290		}
    291	},
    292	/* CRC-32Castagnoli */
    293	{
    294		.setkey         = stm32_crc_setkey,
    295		.init           = stm32_crc_init,
    296		.update         = stm32_crc_update,
    297		.final          = stm32_crc_final,
    298		.finup          = stm32_crc_finup,
    299		.digest         = stm32_crc_digest,
    300		.descsize       = sizeof(struct stm32_crc_desc_ctx),
    301		.digestsize     = CHKSUM_DIGEST_SIZE,
    302		.base           = {
    303			.cra_name               = "crc32c",
    304			.cra_driver_name        = "stm32-crc32-crc32c",
    305			.cra_priority           = 200,
    306			.cra_flags		= CRYPTO_ALG_OPTIONAL_KEY,
    307			.cra_blocksize          = CHKSUM_BLOCK_SIZE,
    308			.cra_alignmask          = 3,
    309			.cra_ctxsize            = sizeof(struct stm32_crc_ctx),
    310			.cra_module             = THIS_MODULE,
    311			.cra_init               = stm32_crc32c_cra_init,
    312		}
    313	}
    314};
    315
    316static int stm32_crc_probe(struct platform_device *pdev)
    317{
    318	struct device *dev = &pdev->dev;
    319	struct stm32_crc *crc;
    320	int ret;
    321
    322	crc = devm_kzalloc(dev, sizeof(*crc), GFP_KERNEL);
    323	if (!crc)
    324		return -ENOMEM;
    325
    326	crc->dev = dev;
    327
    328	crc->regs = devm_platform_ioremap_resource(pdev, 0);
    329	if (IS_ERR(crc->regs)) {
    330		dev_err(dev, "Cannot map CRC IO\n");
    331		return PTR_ERR(crc->regs);
    332	}
    333
    334	crc->clk = devm_clk_get(dev, NULL);
    335	if (IS_ERR(crc->clk)) {
    336		dev_err(dev, "Could not get clock\n");
    337		return PTR_ERR(crc->clk);
    338	}
    339
    340	ret = clk_prepare_enable(crc->clk);
    341	if (ret) {
    342		dev_err(crc->dev, "Failed to enable clock\n");
    343		return ret;
    344	}
    345
    346	pm_runtime_set_autosuspend_delay(dev, CRC_AUTOSUSPEND_DELAY);
    347	pm_runtime_use_autosuspend(dev);
    348
    349	pm_runtime_get_noresume(dev);
    350	pm_runtime_set_active(dev);
    351	pm_runtime_irq_safe(dev);
    352	pm_runtime_enable(dev);
    353
    354	spin_lock_init(&crc->lock);
    355
    356	platform_set_drvdata(pdev, crc);
    357
    358	spin_lock(&crc_list.lock);
    359	list_add(&crc->list, &crc_list.dev_list);
    360	spin_unlock(&crc_list.lock);
    361
    362	mutex_lock(&refcnt_lock);
    363	if (!refcnt) {
    364		ret = crypto_register_shashes(algs, ARRAY_SIZE(algs));
    365		if (ret) {
    366			mutex_unlock(&refcnt_lock);
    367			dev_err(dev, "Failed to register\n");
    368			clk_disable_unprepare(crc->clk);
    369			return ret;
    370		}
    371	}
    372	refcnt++;
    373	mutex_unlock(&refcnt_lock);
    374
    375	dev_info(dev, "Initialized\n");
    376
    377	pm_runtime_put_sync(dev);
    378
    379	return 0;
    380}
    381
    382static int stm32_crc_remove(struct platform_device *pdev)
    383{
    384	struct stm32_crc *crc = platform_get_drvdata(pdev);
    385	int ret = pm_runtime_get_sync(crc->dev);
    386
    387	if (ret < 0) {
    388		pm_runtime_put_noidle(crc->dev);
    389		return ret;
    390	}
    391
    392	spin_lock(&crc_list.lock);
    393	list_del(&crc->list);
    394	spin_unlock(&crc_list.lock);
    395
    396	mutex_lock(&refcnt_lock);
    397	if (!--refcnt)
    398		crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
    399	mutex_unlock(&refcnt_lock);
    400
    401	pm_runtime_disable(crc->dev);
    402	pm_runtime_put_noidle(crc->dev);
    403
    404	clk_disable_unprepare(crc->clk);
    405
    406	return 0;
    407}
    408
    409static int __maybe_unused stm32_crc_suspend(struct device *dev)
    410{
    411	struct stm32_crc *crc = dev_get_drvdata(dev);
    412	int ret;
    413
    414	ret = pm_runtime_force_suspend(dev);
    415	if (ret)
    416		return ret;
    417
    418	clk_unprepare(crc->clk);
    419
    420	return 0;
    421}
    422
    423static int __maybe_unused stm32_crc_resume(struct device *dev)
    424{
    425	struct stm32_crc *crc = dev_get_drvdata(dev);
    426	int ret;
    427
    428	ret = clk_prepare(crc->clk);
    429	if (ret) {
    430		dev_err(crc->dev, "Failed to prepare clock\n");
    431		return ret;
    432	}
    433
    434	return pm_runtime_force_resume(dev);
    435}
    436
    437static int __maybe_unused stm32_crc_runtime_suspend(struct device *dev)
    438{
    439	struct stm32_crc *crc = dev_get_drvdata(dev);
    440
    441	clk_disable(crc->clk);
    442
    443	return 0;
    444}
    445
    446static int __maybe_unused stm32_crc_runtime_resume(struct device *dev)
    447{
    448	struct stm32_crc *crc = dev_get_drvdata(dev);
    449	int ret;
    450
    451	ret = clk_enable(crc->clk);
    452	if (ret) {
    453		dev_err(crc->dev, "Failed to enable clock\n");
    454		return ret;
    455	}
    456
    457	return 0;
    458}
    459
    460static const struct dev_pm_ops stm32_crc_pm_ops = {
    461	SET_SYSTEM_SLEEP_PM_OPS(stm32_crc_suspend,
    462				stm32_crc_resume)
    463	SET_RUNTIME_PM_OPS(stm32_crc_runtime_suspend,
    464			   stm32_crc_runtime_resume, NULL)
    465};
    466
    467static const struct of_device_id stm32_dt_ids[] = {
    468	{ .compatible = "st,stm32f7-crc", },
    469	{},
    470};
    471MODULE_DEVICE_TABLE(of, stm32_dt_ids);
    472
    473static struct platform_driver stm32_crc_driver = {
    474	.probe  = stm32_crc_probe,
    475	.remove = stm32_crc_remove,
    476	.driver = {
    477		.name           = DRIVER_NAME,
    478		.pm		= &stm32_crc_pm_ops,
    479		.of_match_table = stm32_dt_ids,
    480	},
    481};
    482
    483module_platform_driver(stm32_crc_driver);
    484
    485MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
    486MODULE_DESCRIPTION("STMicrolectronics STM32 CRC32 hardware driver");
    487MODULE_LICENSE("GPL");