GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / crypto / stm32 / stm32_crc32.c
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
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
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
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
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
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
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
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
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
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        = "stm32-crc32-crc32",
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        = "stm32-crc32-crc32c",
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
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
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                 pm_runtime_put_noidle(crc->dev);
339                 return ret;
340         }
341
342         spin_lock(&crc_list.lock);
343         list_del(&crc->list);
344         spin_unlock(&crc_list.lock);
345
346         mutex_lock(&refcnt_lock);
347         if (!--refcnt)
348                 crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
349         mutex_unlock(&refcnt_lock);
350
351         pm_runtime_disable(crc->dev);
352         pm_runtime_put_noidle(crc->dev);
353
354         clk_disable_unprepare(crc->clk);
355
356         return 0;
357 }
358
359 #ifdef CONFIG_PM
360 static int stm32_crc_runtime_suspend(struct device *dev)
361 {
362         struct stm32_crc *crc = dev_get_drvdata(dev);
363
364         clk_disable_unprepare(crc->clk);
365
366         return 0;
367 }
368
369 static int stm32_crc_runtime_resume(struct device *dev)
370 {
371         struct stm32_crc *crc = dev_get_drvdata(dev);
372         int ret;
373
374         ret = clk_prepare_enable(crc->clk);
375         if (ret) {
376                 dev_err(crc->dev, "Failed to prepare_enable clock\n");
377                 return ret;
378         }
379
380         return 0;
381 }
382 #endif
383
384 static const struct dev_pm_ops stm32_crc_pm_ops = {
385         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
386                                 pm_runtime_force_resume)
387         SET_RUNTIME_PM_OPS(stm32_crc_runtime_suspend,
388                            stm32_crc_runtime_resume, NULL)
389 };
390
391 static const struct of_device_id stm32_dt_ids[] = {
392         { .compatible = "st,stm32f7-crc", },
393         {},
394 };
395 MODULE_DEVICE_TABLE(of, stm32_dt_ids);
396
397 static struct platform_driver stm32_crc_driver = {
398         .probe  = stm32_crc_probe,
399         .remove = stm32_crc_remove,
400         .driver = {
401                 .name           = DRIVER_NAME,
402                 .pm             = &stm32_crc_pm_ops,
403                 .of_match_table = stm32_dt_ids,
404         },
405 };
406
407 module_platform_driver(stm32_crc_driver);
408
409 MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
410 MODULE_DESCRIPTION("STMicrolectronics STM32 CRC32 hardware driver");
411 MODULE_LICENSE("GPL");