Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 87 additions & 18 deletions drivers/crypto/qce/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/pm_clock.h>
#include <linux/types.h>
#include <crypto/internal/hash.h>

Expand Down Expand Up @@ -90,13 +93,17 @@ static int qce_handle_queue(struct qce_device *qce,
struct crypto_async_request *async_req, *backlog;
int ret = 0, err;

ret = pm_runtime_resume_and_get(qce->dev);
if (ret < 0)
return ret;

scoped_guard(mutex, &qce->lock) {
if (req)
ret = crypto_enqueue_request(&qce->queue, req);

/* busy, do not dequeue request */
if (qce->req)
return ret;
goto qce_suspend;

backlog = crypto_get_backlog(&qce->queue);
async_req = crypto_dequeue_request(&qce->queue);
Expand All @@ -105,7 +112,7 @@ static int qce_handle_queue(struct qce_device *qce,
}

if (!async_req)
return ret;
goto qce_suspend;

if (backlog) {
scoped_guard(mutex, &qce->lock)
Expand All @@ -118,6 +125,8 @@ static int qce_handle_queue(struct qce_device *qce,
schedule_work(&qce->done_work);
}

qce_suspend:
pm_runtime_put_autosuspend(qce->dev);
return ret;
}

Expand Down Expand Up @@ -216,37 +225,47 @@ static int qce_crypto_probe(struct platform_device *pdev)
if (ret < 0)
return ret;

qce->core = devm_clk_get_optional_enabled(qce->dev, "core");
if (IS_ERR(qce->core))
return PTR_ERR(qce->core);
/* PM clock helpers: register device clocks */
ret = devm_pm_clk_create(dev);
if (ret)
return ret;

qce->iface = devm_clk_get_optional_enabled(qce->dev, "iface");
if (IS_ERR(qce->iface))
return PTR_ERR(qce->iface);
ret = pm_clk_add(dev, "core");
if (ret)
return ret;

qce->bus = devm_clk_get_optional_enabled(qce->dev, "bus");
if (IS_ERR(qce->bus))
return PTR_ERR(qce->bus);
ret = pm_clk_add(dev, "iface");
if (ret)
return ret;

qce->mem_path = devm_of_icc_get(qce->dev, "memory");
ret = pm_clk_add(dev, "bus");
if (ret)
return ret;

qce->mem_path = devm_of_icc_get(dev, "memory");
if (IS_ERR(qce->mem_path))
return PTR_ERR(qce->mem_path);

ret = icc_set_bw(qce->mem_path, QCE_DEFAULT_MEM_BANDWIDTH, QCE_DEFAULT_MEM_BANDWIDTH);
/* Enable runtime PM after clocks and ICC are acquired */
ret = devm_pm_runtime_enable(dev);
if (ret)
return ret;

ret = devm_qce_dma_request(qce);
ret = pm_runtime_resume_and_get(dev);
if (ret)
return ret;

ret = devm_qce_dma_request(qce);
if (ret)
goto err_pm;

ret = qce_check_version(qce);
if (ret)
return ret;
goto err_pm;

ret = devm_mutex_init(qce->dev, &qce->lock);
if (ret)
return ret;
goto err_pm;

INIT_WORK(&qce->done_work, qce_req_done_work);
crypto_init_queue(&qce->queue, QCE_QUEUE_LENGTH);
Expand All @@ -256,19 +275,68 @@ static int qce_crypto_probe(struct platform_device *pdev)

ret = devm_qce_register_algs(qce);
if (ret)
return ret;
goto err_pm;

qce->dma_size = resource_size(res);
qce->base_dma = dma_map_resource(dev, res->start, qce->dma_size,
DMA_BIDIRECTIONAL, 0);
qce->base_phys = res->start;
ret = dma_mapping_error(dev, qce->base_dma);
if (ret)
goto err_pm;

ret = devm_add_action_or_reset(qce->dev, qce_crypto_unmap_dma, qce);
if (ret)
goto err_pm;

/* Configure autosuspend after successful init */
pm_runtime_set_autosuspend_delay(dev, 100);
pm_runtime_use_autosuspend(dev);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);

return 0;

err_pm:
pm_runtime_put(dev);

return ret;
}

static int __maybe_unused qce_runtime_suspend(struct device *dev)
{
struct qce_device *qce = dev_get_drvdata(dev);

icc_disable(qce->mem_path);

return 0;
}

static int __maybe_unused qce_runtime_resume(struct device *dev)
{
struct qce_device *qce = dev_get_drvdata(dev);
int ret = 0;

ret = icc_enable(qce->mem_path);
if (ret)
return ret;

return devm_add_action_or_reset(qce->dev, qce_crypto_unmap_dma, qce);
ret = icc_set_bw(qce->mem_path, QCE_DEFAULT_MEM_BANDWIDTH, QCE_DEFAULT_MEM_BANDWIDTH);
if (ret)
goto err_icc;

return 0;

err_icc:
icc_disable(qce->mem_path);
return ret;
}

static const struct dev_pm_ops qce_crypto_pm_ops = {
SET_RUNTIME_PM_OPS(qce_runtime_suspend, qce_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};

static const struct of_device_id qce_crypto_of_match[] = {
{ .compatible = "qcom,crypto-v5.1", },
{ .compatible = "qcom,crypto-v5.4", },
Expand All @@ -282,6 +350,7 @@ static struct platform_driver qce_crypto_driver = {
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = qce_crypto_of_match,
.pm = &qce_crypto_pm_ops,
},
};
module_platform_driver(qce_crypto_driver);
Expand Down