projects/linux·blob master · refs

353 lines · 7.6 KiB

1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/cleanup.h>
7#include <linux/clk.h>
8#include <linux/device.h>
9#include <linux/dma-mapping.h>
10#include <linux/interconnect.h>
11#include <linux/interrupt.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/pm.h>
15#include <linux/pm_runtime.h>
16#include <linux/types.h>
17#include <crypto/algapi.h>
18#include <crypto/internal/hash.h>
19
20#include "core.h"
21#include "cipher.h"
22#include "sha.h"
23#include "aead.h"
24
25#define QCE_QUEUE_LENGTH 1
26
27#define QCE_DEFAULT_MEM_BANDWIDTH 393600
28
29static const struct qce_algo_ops *qce_ops[] = {
30#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER
31 &skcipher_ops,
32#endif
33#ifdef CONFIG_CRYPTO_DEV_QCE_SHA
34 &ahash_ops,
35#endif
36#ifdef CONFIG_CRYPTO_DEV_QCE_AEAD
37 &aead_ops,
38#endif
39};
40
41static void qce_unregister_algs(void *data)
42{
43 const struct qce_algo_ops *ops;
44 struct qce_device *qce = data;
45 int i;
46
47 for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
48 ops = qce_ops[i];
49 ops->unregister_algs(qce);
50 }
51}
52
53static int devm_qce_register_algs(struct qce_device *qce)
54{
55 const struct qce_algo_ops *ops;
56 int i, ret;
57
58 for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
59 ops = qce_ops[i];
60 ret = ops->register_algs(qce);
61 if (ret) {
62 while (i--)
63 qce_ops[i]->unregister_algs(qce);
64 return ret;
65 }
66 }
67
68 return devm_add_action_or_reset(qce->dev, qce_unregister_algs, qce);
69}
70
71static int qce_handle_request(struct crypto_async_request *async_req)
72{
73 int i;
74 const struct qce_algo_ops *ops;
75 u32 type = crypto_tfm_alg_type(async_req->tfm);
76
77 for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
78 ops = qce_ops[i];
79 if (type == ops->type)
80 return ops->async_req_handle(async_req);
81 }
82
83 return -EINVAL;
84}
85
86static int qce_handle_queue(struct qce_device *qce,
87 struct crypto_async_request *req)
88{
89 struct crypto_async_request *async_req, *backlog;
90 int ret, err;
91
92 PM_RUNTIME_ACQUIRE_AUTOSUSPEND(qce->dev, pm);
93 ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
94 if (ret)
95 return ret;
96
97 scoped_guard(mutex, &qce->lock) {
98 if (req)
99 ret = crypto_enqueue_request(&qce->queue, req);
100
101 /* busy, do not dequeue request */
102 if (qce->req)
103 return ret;
104
105 backlog = crypto_get_backlog(&qce->queue);
106 async_req = crypto_dequeue_request(&qce->queue);
107 if (async_req)
108 qce->req = async_req;
109 }
110
111 if (!async_req)
112 return ret;
113
114 if (backlog) {
115 scoped_guard(mutex, &qce->lock)
116 crypto_request_complete(backlog, -EINPROGRESS);
117 }
118
119 err = qce_handle_request(async_req);
120 if (err) {
121 qce->result = err;
122 schedule_work(&qce->done_work);
123 }
124
125 return ret;
126}
127
128static void qce_req_done_work(struct work_struct *work)
129{
130 struct qce_device *qce = container_of(work, struct qce_device,
131 done_work);
132 struct crypto_async_request *req;
133
134 scoped_guard(mutex, &qce->lock) {
135 req = qce->req;
136 qce->req = NULL;
137 }
138
139 if (req)
140 crypto_request_complete(req, qce->result);
141
142 qce_handle_queue(qce, NULL);
143}
144
145static int qce_async_request_enqueue(struct qce_device *qce,
146 struct crypto_async_request *req)
147{
148 return qce_handle_queue(qce, req);
149}
150
151static void qce_async_request_done(struct qce_device *qce, int ret)
152{
153 qce->result = ret;
154 schedule_work(&qce->done_work);
155}
156
157static int qce_check_version(struct qce_device *qce)
158{
159 u32 major, minor, step;
160
161 qce_get_version(qce, &major, &minor, &step);
162
163 /*
164 * the driver does not support v5 with minor 0 because it has special
165 * alignment requirements.
166 */
167 if (major == 5 && minor == 0)
168 return -ENODEV;
169
170 qce->burst_size = QCE_BAM_BURST_SIZE;
171
172 /*
173 * Rx and tx pipes are treated as a pair inside CE.
174 * Pipe pair number depends on the actual BAM dma pipe
175 * that is used for transfers. The BAM dma pipes are passed
176 * from the device tree and used to derive the pipe pair
177 * id in the CE driver as follows.
178 * BAM dma pipes(rx, tx) CE pipe pair id
179 * 0,1 0
180 * 2,3 1
181 * 4,5 2
182 * 6,7 3
183 * ...
184 */
185 qce->pipe_pair_id = qce->dma.rxchan->chan_id >> 1;
186
187 dev_dbg(qce->dev, "Crypto device found, version %d.%d.%d\n",
188 major, minor, step);
189
190 return 0;
191}
192
193static int qce_crypto_probe(struct platform_device *pdev)
194{
195 struct device *dev = &pdev->dev;
196 struct qce_device *qce;
197 int ret;
198
199 qce = devm_kzalloc(dev, sizeof(*qce), GFP_KERNEL);
200 if (!qce)
201 return -ENOMEM;
202
203 qce->dev = dev;
204 platform_set_drvdata(pdev, qce);
205
206 qce->base = devm_platform_ioremap_resource(pdev, 0);
207 if (IS_ERR(qce->base))
208 return PTR_ERR(qce->base);
209
210 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
211 if (ret < 0)
212 return ret;
213
214 qce->core = devm_clk_get_optional(qce->dev, "core");
215 if (IS_ERR(qce->core))
216 return PTR_ERR(qce->core);
217
218 qce->iface = devm_clk_get_optional(qce->dev, "iface");
219 if (IS_ERR(qce->iface))
220 return PTR_ERR(qce->iface);
221
222 qce->bus = devm_clk_get_optional(qce->dev, "bus");
223 if (IS_ERR(qce->bus))
224 return PTR_ERR(qce->bus);
225
226 qce->mem_path = devm_of_icc_get(dev, "memory");
227 if (IS_ERR(qce->mem_path))
228 return PTR_ERR(qce->mem_path);
229
230 /*
231 * Enable runtime PM after clocks and ICC path are acquired so that
232 * the resume callback can enable clocks and apply the ICC bandwidth
233 * vote before any hardware access takes place.
234 */
235 ret = devm_pm_runtime_enable(dev);
236 if (ret)
237 return ret;
238
239 PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
240 ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
241 if (ret)
242 return ret;
243
244 ret = devm_qce_dma_request(qce->dev, &qce->dma);
245 if (ret)
246 return ret;
247
248 ret = qce_check_version(qce);
249 if (ret)
250 return ret;
251
252 ret = devm_mutex_init(qce->dev, &qce->lock);
253 if (ret)
254 return ret;
255
256 INIT_WORK(&qce->done_work, qce_req_done_work);
257 crypto_init_queue(&qce->queue, QCE_QUEUE_LENGTH);
258
259 qce->async_req_enqueue = qce_async_request_enqueue;
260 qce->async_req_done = qce_async_request_done;
261
262 ret = devm_qce_register_algs(qce);
263 if (ret)
264 return ret;
265
266 /* Configure autosuspend after successful init */
267 pm_runtime_set_autosuspend_delay(dev, 100);
268 pm_runtime_use_autosuspend(dev);
269 pm_runtime_mark_last_busy(dev);
270
271 return 0;
272}
273
274static int qce_runtime_suspend(struct device *dev)
275{
276 struct qce_device *qce = dev_get_drvdata(dev);
277 int ret;
278
279 clk_disable_unprepare(qce->core);
280 clk_disable_unprepare(qce->iface);
281 clk_disable_unprepare(qce->bus);
282
283 ret = icc_set_bw(qce->mem_path, 0, 0);
284 if (ret) {
285 clk_prepare_enable(qce->bus);
286 clk_prepare_enable(qce->iface);
287 clk_prepare_enable(qce->core);
288 return ret;
289 }
290
291 return 0;
292}
293
294static int qce_runtime_resume(struct device *dev)
295{
296 struct qce_device *qce = dev_get_drvdata(dev);
297 int ret;
298
299 ret = icc_set_bw(qce->mem_path, QCE_DEFAULT_MEM_BANDWIDTH,
300 QCE_DEFAULT_MEM_BANDWIDTH);
301 if (ret)
302 return ret;
303
304 ret = clk_prepare_enable(qce->core);
305 if (ret)
306 goto err_core;
307
308 ret = clk_prepare_enable(qce->iface);
309 if (ret)
310 goto err_iface;
311
312 ret = clk_prepare_enable(qce->bus);
313 if (ret)
314 goto err_bus;
315
316 return 0;
317
318err_bus:
319 clk_disable_unprepare(qce->iface);
320err_iface:
321 clk_disable_unprepare(qce->core);
322err_core:
323 icc_set_bw(qce->mem_path, 0, 0);
324 return ret;
325}
326
327static const struct dev_pm_ops qce_crypto_pm_ops = {
328 RUNTIME_PM_OPS(qce_runtime_suspend, qce_runtime_resume, NULL)
329 SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
330};
331
332static const struct of_device_id qce_crypto_of_match[] = {
333 { .compatible = "qcom,crypto-v5.1", },
334 { .compatible = "qcom,crypto-v5.4", },
335 { .compatible = "qcom,qce", },
336 {}
337};
338MODULE_DEVICE_TABLE(of, qce_crypto_of_match);
339
340static struct platform_driver qce_crypto_driver = {
341 .probe = qce_crypto_probe,
342 .driver = {
343 .name = KBUILD_MODNAME,
344 .of_match_table = qce_crypto_of_match,
345 .pm = pm_ptr(&qce_crypto_pm_ops),
346 },
347};
348module_platform_driver(qce_crypto_driver);
349
350MODULE_LICENSE("GPL v2");
351MODULE_DESCRIPTION("Qualcomm crypto engine driver");
352MODULE_ALIAS("platform:" KBUILD_MODNAME);
353MODULE_AUTHOR("The Linux Foundation");