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