brintos

brintos / linux-shallow public Read only

0
0
Text · 11.6 KiB · e0faddb Raw
481 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) STMicroelectronics SA 20174 * 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 <linux/unaligned.h>21 22#define DRIVER_NAME             "stm32-crc32"23#define CHKSUM_DIGEST_SIZE      424#define CHKSUM_BLOCK_SIZE       125 26/* Registers */27#define CRC_DR                  0x0000000028#define CRC_CR                  0x0000000829#define CRC_INIT                0x0000001030#define CRC_POL                 0x0000001431 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     0xFFFFFFFF38 39#define CRC_AUTOSUSPEND_DELAY	5040 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_or_null(&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		else165			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 value172	 * Restore polynomial configuration173	 * 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_ctxsize            = sizeof(struct stm32_crc_ctx),287			.cra_module             = THIS_MODULE,288			.cra_init               = stm32_crc32_cra_init,289		}290	},291	/* CRC-32Castagnoli */292	{293		.setkey         = stm32_crc_setkey,294		.init           = stm32_crc_init,295		.update         = stm32_crc_update,296		.final          = stm32_crc_final,297		.finup          = stm32_crc_finup,298		.digest         = stm32_crc_digest,299		.descsize       = sizeof(struct stm32_crc_desc_ctx),300		.digestsize     = CHKSUM_DIGEST_SIZE,301		.base           = {302			.cra_name               = "crc32c",303			.cra_driver_name        = "stm32-crc32-crc32c",304			.cra_priority           = 200,305			.cra_flags		= CRYPTO_ALG_OPTIONAL_KEY,306			.cra_blocksize          = CHKSUM_BLOCK_SIZE,307			.cra_ctxsize            = sizeof(struct stm32_crc_ctx),308			.cra_module             = THIS_MODULE,309			.cra_init               = stm32_crc32c_cra_init,310		}311	}312};313 314static int stm32_crc_probe(struct platform_device *pdev)315{316	struct device *dev = &pdev->dev;317	struct stm32_crc *crc;318	int ret;319 320	crc = devm_kzalloc(dev, sizeof(*crc), GFP_KERNEL);321	if (!crc)322		return -ENOMEM;323 324	crc->dev = dev;325 326	crc->regs = devm_platform_ioremap_resource(pdev, 0);327	if (IS_ERR(crc->regs)) {328		dev_err(dev, "Cannot map CRC IO\n");329		return PTR_ERR(crc->regs);330	}331 332	crc->clk = devm_clk_get(dev, NULL);333	if (IS_ERR(crc->clk)) {334		dev_err(dev, "Could not get clock\n");335		return PTR_ERR(crc->clk);336	}337 338	ret = clk_prepare_enable(crc->clk);339	if (ret) {340		dev_err(crc->dev, "Failed to enable clock\n");341		return ret;342	}343 344	pm_runtime_set_autosuspend_delay(dev, CRC_AUTOSUSPEND_DELAY);345	pm_runtime_use_autosuspend(dev);346 347	pm_runtime_get_noresume(dev);348	pm_runtime_set_active(dev);349	pm_runtime_irq_safe(dev);350	pm_runtime_enable(dev);351 352	spin_lock_init(&crc->lock);353 354	platform_set_drvdata(pdev, crc);355 356	spin_lock(&crc_list.lock);357	list_add(&crc->list, &crc_list.dev_list);358	spin_unlock(&crc_list.lock);359 360	mutex_lock(&refcnt_lock);361	if (!refcnt) {362		ret = crypto_register_shashes(algs, ARRAY_SIZE(algs));363		if (ret) {364			mutex_unlock(&refcnt_lock);365			dev_err(dev, "Failed to register\n");366			clk_disable_unprepare(crc->clk);367			return ret;368		}369	}370	refcnt++;371	mutex_unlock(&refcnt_lock);372 373	dev_info(dev, "Initialized\n");374 375	pm_runtime_put_sync(dev);376 377	return 0;378}379 380static void stm32_crc_remove(struct platform_device *pdev)381{382	struct stm32_crc *crc = platform_get_drvdata(pdev);383	int ret = pm_runtime_get_sync(crc->dev);384 385	spin_lock(&crc_list.lock);386	list_del(&crc->list);387	spin_unlock(&crc_list.lock);388 389	mutex_lock(&refcnt_lock);390	if (!--refcnt)391		crypto_unregister_shashes(algs, ARRAY_SIZE(algs));392	mutex_unlock(&refcnt_lock);393 394	pm_runtime_disable(crc->dev);395	pm_runtime_put_noidle(crc->dev);396 397	if (ret >= 0)398		clk_disable(crc->clk);399	clk_unprepare(crc->clk);400}401 402static int __maybe_unused stm32_crc_suspend(struct device *dev)403{404	struct stm32_crc *crc = dev_get_drvdata(dev);405	int ret;406 407	ret = pm_runtime_force_suspend(dev);408	if (ret)409		return ret;410 411	clk_unprepare(crc->clk);412 413	return 0;414}415 416static int __maybe_unused stm32_crc_resume(struct device *dev)417{418	struct stm32_crc *crc = dev_get_drvdata(dev);419	int ret;420 421	ret = clk_prepare(crc->clk);422	if (ret) {423		dev_err(crc->dev, "Failed to prepare clock\n");424		return ret;425	}426 427	return pm_runtime_force_resume(dev);428}429 430static int __maybe_unused stm32_crc_runtime_suspend(struct device *dev)431{432	struct stm32_crc *crc = dev_get_drvdata(dev);433 434	clk_disable(crc->clk);435 436	return 0;437}438 439static int __maybe_unused stm32_crc_runtime_resume(struct device *dev)440{441	struct stm32_crc *crc = dev_get_drvdata(dev);442	int ret;443 444	ret = clk_enable(crc->clk);445	if (ret) {446		dev_err(crc->dev, "Failed to enable clock\n");447		return ret;448	}449 450	return 0;451}452 453static const struct dev_pm_ops stm32_crc_pm_ops = {454	SET_SYSTEM_SLEEP_PM_OPS(stm32_crc_suspend,455				stm32_crc_resume)456	SET_RUNTIME_PM_OPS(stm32_crc_runtime_suspend,457			   stm32_crc_runtime_resume, NULL)458};459 460static const struct of_device_id stm32_dt_ids[] = {461	{ .compatible = "st,stm32f7-crc", },462	{},463};464MODULE_DEVICE_TABLE(of, stm32_dt_ids);465 466static struct platform_driver stm32_crc_driver = {467	.probe  = stm32_crc_probe,468	.remove_new = stm32_crc_remove,469	.driver = {470		.name           = DRIVER_NAME,471		.pm		= &stm32_crc_pm_ops,472		.of_match_table = stm32_dt_ids,473	},474};475 476module_platform_driver(stm32_crc_driver);477 478MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");479MODULE_DESCRIPTION("STMicrolectronics STM32 CRC32 hardware driver");480MODULE_LICENSE("GPL");481