1212#include <linux/module.h>
1313#include <linux/mod_devicetable.h>
1414#include <linux/platform_device.h>
15+ #include <linux/pm.h>
16+ #include <linux/pm_runtime.h>
17+ #include <linux/pm_clock.h>
1518#include <linux/types.h>
1619#include <crypto/internal/hash.h>
1720
@@ -90,13 +93,17 @@ static int qce_handle_queue(struct qce_device *qce,
9093 struct crypto_async_request * async_req , * backlog ;
9194 int ret = 0 , err ;
9295
96+ ret = pm_runtime_resume_and_get (qce -> dev );
97+ if (ret < 0 )
98+ return ret ;
99+
93100 scoped_guard (mutex , & qce -> lock ) {
94101 if (req )
95102 ret = crypto_enqueue_request (& qce -> queue , req );
96103
97104 /* busy, do not dequeue request */
98105 if (qce -> req )
99- return ret ;
106+ goto qce_suspend ;
100107
101108 backlog = crypto_get_backlog (& qce -> queue );
102109 async_req = crypto_dequeue_request (& qce -> queue );
@@ -105,7 +112,7 @@ static int qce_handle_queue(struct qce_device *qce,
105112 }
106113
107114 if (!async_req )
108- return ret ;
115+ goto qce_suspend ;
109116
110117 if (backlog ) {
111118 scoped_guard (mutex , & qce -> lock )
@@ -118,6 +125,8 @@ static int qce_handle_queue(struct qce_device *qce,
118125 schedule_work (& qce -> done_work );
119126 }
120127
128+ qce_suspend :
129+ pm_runtime_put_autosuspend (qce -> dev );
121130 return ret ;
122131}
123132
@@ -216,37 +225,47 @@ static int qce_crypto_probe(struct platform_device *pdev)
216225 if (ret < 0 )
217226 return ret ;
218227
219- qce -> core = devm_clk_get_optional_enabled (qce -> dev , "core" );
220- if (IS_ERR (qce -> core ))
221- return PTR_ERR (qce -> core );
228+ /* PM clock helpers: register device clocks */
229+ ret = devm_pm_clk_create (dev );
230+ if (ret )
231+ return ret ;
222232
223- qce -> iface = devm_clk_get_optional_enabled ( qce -> dev , "iface " );
224- if (IS_ERR ( qce -> iface ) )
225- return PTR_ERR ( qce -> iface ) ;
233+ ret = pm_clk_add ( dev , "core " );
234+ if (ret )
235+ return ret ;
226236
227- qce -> bus = devm_clk_get_optional_enabled ( qce -> dev , "bus " );
228- if (IS_ERR ( qce -> bus ) )
229- return PTR_ERR ( qce -> bus ) ;
237+ ret = pm_clk_add ( dev , "iface " );
238+ if (ret )
239+ return ret ;
230240
231- qce -> mem_path = devm_of_icc_get (qce -> dev , "memory" );
241+ ret = pm_clk_add (dev , "bus" );
242+ if (ret )
243+ return ret ;
244+
245+ qce -> mem_path = devm_of_icc_get (dev , "memory" );
232246 if (IS_ERR (qce -> mem_path ))
233247 return PTR_ERR (qce -> mem_path );
234248
235- ret = icc_set_bw (qce -> mem_path , QCE_DEFAULT_MEM_BANDWIDTH , QCE_DEFAULT_MEM_BANDWIDTH );
249+ /* Enable runtime PM after clocks and ICC are acquired */
250+ ret = devm_pm_runtime_enable (dev );
236251 if (ret )
237252 return ret ;
238253
239- ret = devm_qce_dma_request ( qce );
254+ ret = pm_runtime_resume_and_get ( dev );
240255 if (ret )
241256 return ret ;
242257
258+ ret = devm_qce_dma_request (qce );
259+ if (ret )
260+ goto err_pm ;
261+
243262 ret = qce_check_version (qce );
244263 if (ret )
245- return ret ;
264+ goto err_pm ;
246265
247266 ret = devm_mutex_init (qce -> dev , & qce -> lock );
248267 if (ret )
249- return ret ;
268+ goto err_pm ;
250269
251270 INIT_WORK (& qce -> done_work , qce_req_done_work );
252271 crypto_init_queue (& qce -> queue , QCE_QUEUE_LENGTH );
@@ -256,19 +275,68 @@ static int qce_crypto_probe(struct platform_device *pdev)
256275
257276 ret = devm_qce_register_algs (qce );
258277 if (ret )
259- return ret ;
278+ goto err_pm ;
260279
261280 qce -> dma_size = resource_size (res );
262281 qce -> base_dma = dma_map_resource (dev , res -> start , qce -> dma_size ,
263282 DMA_BIDIRECTIONAL , 0 );
264283 qce -> base_phys = res -> start ;
265284 ret = dma_mapping_error (dev , qce -> base_dma );
285+ if (ret )
286+ goto err_pm ;
287+
288+ ret = devm_add_action_or_reset (qce -> dev , qce_crypto_unmap_dma , qce );
289+ if (ret )
290+ goto err_pm ;
291+
292+ /* Configure autosuspend after successful init */
293+ pm_runtime_set_autosuspend_delay (dev , 100 );
294+ pm_runtime_use_autosuspend (dev );
295+ pm_runtime_mark_last_busy (dev );
296+ pm_runtime_put_autosuspend (dev );
297+
298+ return 0 ;
299+
300+ err_pm :
301+ pm_runtime_put (dev );
302+
303+ return ret ;
304+ }
305+
306+ static int __maybe_unused qce_runtime_suspend (struct device * dev )
307+ {
308+ struct qce_device * qce = dev_get_drvdata (dev );
309+
310+ icc_disable (qce -> mem_path );
311+
312+ return 0 ;
313+ }
314+
315+ static int __maybe_unused qce_runtime_resume (struct device * dev )
316+ {
317+ struct qce_device * qce = dev_get_drvdata (dev );
318+ int ret = 0 ;
319+
320+ ret = icc_enable (qce -> mem_path );
266321 if (ret )
267322 return ret ;
268323
269- return devm_add_action_or_reset (qce -> dev , qce_crypto_unmap_dma , qce );
324+ ret = icc_set_bw (qce -> mem_path , QCE_DEFAULT_MEM_BANDWIDTH , QCE_DEFAULT_MEM_BANDWIDTH );
325+ if (ret )
326+ goto err_icc ;
327+
328+ return 0 ;
329+
330+ err_icc :
331+ icc_disable (qce -> mem_path );
332+ return ret ;
270333}
271334
335+ static const struct dev_pm_ops qce_crypto_pm_ops = {
336+ SET_RUNTIME_PM_OPS (qce_runtime_suspend , qce_runtime_resume , NULL )
337+ SET_SYSTEM_SLEEP_PM_OPS (pm_runtime_force_suspend , pm_runtime_force_resume )
338+ };
339+
272340static const struct of_device_id qce_crypto_of_match [] = {
273341 { .compatible = "qcom,crypto-v5.1" , },
274342 { .compatible = "qcom,crypto-v5.4" , },
@@ -282,6 +350,7 @@ static struct platform_driver qce_crypto_driver = {
282350 .driver = {
283351 .name = KBUILD_MODNAME ,
284352 .of_match_table = qce_crypto_of_match ,
353+ .pm = & qce_crypto_pm_ops ,
285354 },
286355};
287356module_platform_driver (qce_crypto_driver );
0 commit comments