14c3f9727SGilad Ben-Yossef // SPDX-License-Identifier: GPL-2.0
203963caeSGilad Ben-Yossef /* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */
34c3f9727SGilad Ben-Yossef
44c3f9727SGilad Ben-Yossef #include <linux/kernel.h>
54c3f9727SGilad Ben-Yossef #include <linux/interrupt.h>
64c3f9727SGilad Ben-Yossef #include <linux/pm_runtime.h>
74c3f9727SGilad Ben-Yossef #include "cc_driver.h"
84c3f9727SGilad Ben-Yossef #include "cc_buffer_mgr.h"
94c3f9727SGilad Ben-Yossef #include "cc_request_mgr.h"
104c3f9727SGilad Ben-Yossef #include "cc_sram_mgr.h"
1163893811SGilad Ben-Yossef #include "cc_hash.h"
124c3f9727SGilad Ben-Yossef #include "cc_pm.h"
137138377cSOfir Drang #include "cc_fips.h"
144c3f9727SGilad Ben-Yossef
154c3f9727SGilad Ben-Yossef #define POWER_DOWN_ENABLE 0x01
164c3f9727SGilad Ben-Yossef #define POWER_DOWN_DISABLE 0x00
174c3f9727SGilad Ben-Yossef
cc_pm_suspend(struct device * dev)18f33d807cSGeert Uytterhoeven static int cc_pm_suspend(struct device *dev)
194c3f9727SGilad Ben-Yossef {
204c3f9727SGilad Ben-Yossef struct cc_drvdata *drvdata = dev_get_drvdata(dev);
214c3f9727SGilad Ben-Yossef
224c3f9727SGilad Ben-Yossef dev_dbg(dev, "set HOST_POWER_DOWN_EN\n");
234c3f9727SGilad Ben-Yossef fini_cc_regs(drvdata);
243499efbeSOfir Drang cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_ENABLE);
252f272ef3SGeert Uytterhoeven clk_disable_unprepare(drvdata->clk);
264c3f9727SGilad Ben-Yossef return 0;
274c3f9727SGilad Ben-Yossef }
284c3f9727SGilad Ben-Yossef
cc_pm_resume(struct device * dev)29f33d807cSGeert Uytterhoeven static int cc_pm_resume(struct device *dev)
304c3f9727SGilad Ben-Yossef {
314c3f9727SGilad Ben-Yossef int rc;
324c3f9727SGilad Ben-Yossef struct cc_drvdata *drvdata = dev_get_drvdata(dev);
334c3f9727SGilad Ben-Yossef
344c3f9727SGilad Ben-Yossef dev_dbg(dev, "unset HOST_POWER_DOWN_EN\n");
357766dd77SOfir Drang /* Enables the device source clk */
362f272ef3SGeert Uytterhoeven rc = clk_prepare_enable(drvdata->clk);
374c3f9727SGilad Ben-Yossef if (rc) {
384c3f9727SGilad Ben-Yossef dev_err(dev, "failed getting clock back on. We're toast.\n");
394c3f9727SGilad Ben-Yossef return rc;
404c3f9727SGilad Ben-Yossef }
41684cf266SHadar Gat /* wait for Cryptocell reset completion */
42d84f6269SOfir Drang if (!cc_wait_for_reset_completion(drvdata)) {
43d84f6269SOfir Drang dev_err(dev, "Cryptocell reset not completed");
44*30fb0343SYuan Can clk_disable_unprepare(drvdata->clk);
45d84f6269SOfir Drang return -EBUSY;
46d84f6269SOfir Drang }
474c3f9727SGilad Ben-Yossef
487766dd77SOfir Drang cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_DISABLE);
4905c2a705SGilad Ben-Yossef rc = init_cc_regs(drvdata);
504c3f9727SGilad Ben-Yossef if (rc) {
514c3f9727SGilad Ben-Yossef dev_err(dev, "init_cc_regs (%x)\n", rc);
52*30fb0343SYuan Can clk_disable_unprepare(drvdata->clk);
534c3f9727SGilad Ben-Yossef return rc;
544c3f9727SGilad Ben-Yossef }
557138377cSOfir Drang /* check if tee fips error occurred during power down */
567138377cSOfir Drang cc_tee_handle_fips_error(drvdata);
574c3f9727SGilad Ben-Yossef
5863893811SGilad Ben-Yossef cc_init_hash_sram(drvdata);
5963893811SGilad Ben-Yossef
604c3f9727SGilad Ben-Yossef return 0;
614c3f9727SGilad Ben-Yossef }
624c3f9727SGilad Ben-Yossef
63f33d807cSGeert Uytterhoeven const struct dev_pm_ops ccree_pm = {
64f33d807cSGeert Uytterhoeven SET_RUNTIME_PM_OPS(cc_pm_suspend, cc_pm_resume, NULL)
65f33d807cSGeert Uytterhoeven };
66f33d807cSGeert Uytterhoeven
cc_pm_get(struct device * dev)674c3f9727SGilad Ben-Yossef int cc_pm_get(struct device *dev)
684c3f9727SGilad Ben-Yossef {
698c7849a3SGeert Uytterhoeven int rc = pm_runtime_get_sync(dev);
70b7b57a56Sdinghao.liu@zju.edu.cn if (rc < 0) {
71b7b57a56Sdinghao.liu@zju.edu.cn pm_runtime_put_noidle(dev);
72b7b57a56Sdinghao.liu@zju.edu.cn return rc;
73b7b57a56Sdinghao.liu@zju.edu.cn }
744c3f9727SGilad Ben-Yossef
75b7b57a56Sdinghao.liu@zju.edu.cn return 0;
764c3f9727SGilad Ben-Yossef }
774c3f9727SGilad Ben-Yossef
cc_pm_put_suspend(struct device * dev)78bc88606aSGilad Ben-Yossef void cc_pm_put_suspend(struct device *dev)
794c3f9727SGilad Ben-Yossef {
804c3f9727SGilad Ben-Yossef pm_runtime_mark_last_busy(dev);
81bc88606aSGilad Ben-Yossef pm_runtime_put_autosuspend(dev);
824c3f9727SGilad Ben-Yossef }
83