Commit | Line | Data |
---|---|---|
4c3f9727 | 1 | // SPDX-License-Identifier: GPL-2.0 |
03963cae | 2 | /* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */ |
4c3f9727 GBY |
3 | |
4 | #include <linux/kernel.h> | |
5 | #include <linux/interrupt.h> | |
6 | #include <linux/pm_runtime.h> | |
7 | #include "cc_driver.h" | |
8 | #include "cc_buffer_mgr.h" | |
9 | #include "cc_request_mgr.h" | |
10 | #include "cc_sram_mgr.h" | |
63893811 | 11 | #include "cc_hash.h" |
4c3f9727 | 12 | #include "cc_pm.h" |
7138377c | 13 | #include "cc_fips.h" |
4c3f9727 GBY |
14 | |
15 | #define POWER_DOWN_ENABLE 0x01 | |
16 | #define POWER_DOWN_DISABLE 0x00 | |
17 | ||
f33d807c | 18 | static int cc_pm_suspend(struct device *dev) |
4c3f9727 GBY |
19 | { |
20 | struct cc_drvdata *drvdata = dev_get_drvdata(dev); | |
4c3f9727 GBY |
21 | |
22 | dev_dbg(dev, "set HOST_POWER_DOWN_EN\n"); | |
4c3f9727 | 23 | fini_cc_regs(drvdata); |
3499efbe | 24 | cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_ENABLE); |
2f272ef3 | 25 | clk_disable_unprepare(drvdata->clk); |
4c3f9727 GBY |
26 | return 0; |
27 | } | |
28 | ||
f33d807c | 29 | static int cc_pm_resume(struct device *dev) |
4c3f9727 GBY |
30 | { |
31 | int rc; | |
32 | struct cc_drvdata *drvdata = dev_get_drvdata(dev); | |
33 | ||
34 | dev_dbg(dev, "unset HOST_POWER_DOWN_EN\n"); | |
7766dd77 | 35 | /* Enables the device source clk */ |
2f272ef3 | 36 | rc = clk_prepare_enable(drvdata->clk); |
4c3f9727 GBY |
37 | if (rc) { |
38 | dev_err(dev, "failed getting clock back on. We're toast.\n"); | |
39 | return rc; | |
40 | } | |
684cf266 | 41 | /* wait for Cryptocell reset completion */ |
d84f6269 OD |
42 | if (!cc_wait_for_reset_completion(drvdata)) { |
43 | dev_err(dev, "Cryptocell reset not completed"); | |
30fb0343 | 44 | clk_disable_unprepare(drvdata->clk); |
d84f6269 OD |
45 | return -EBUSY; |
46 | } | |
4c3f9727 | 47 | |
7766dd77 | 48 | cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_DISABLE); |
05c2a705 | 49 | rc = init_cc_regs(drvdata); |
4c3f9727 GBY |
50 | if (rc) { |
51 | dev_err(dev, "init_cc_regs (%x)\n", rc); | |
30fb0343 | 52 | clk_disable_unprepare(drvdata->clk); |
4c3f9727 GBY |
53 | return rc; |
54 | } | |
7138377c OD |
55 | /* check if tee fips error occurred during power down */ |
56 | cc_tee_handle_fips_error(drvdata); | |
4c3f9727 | 57 | |
63893811 GBY |
58 | cc_init_hash_sram(drvdata); |
59 | ||
4c3f9727 GBY |
60 | return 0; |
61 | } | |
62 | ||
f33d807c GU |
63 | const struct dev_pm_ops ccree_pm = { |
64 | SET_RUNTIME_PM_OPS(cc_pm_suspend, cc_pm_resume, NULL) | |
65 | }; | |
66 | ||
4c3f9727 GBY |
67 | int cc_pm_get(struct device *dev) |
68 | { | |
8c7849a3 | 69 | int rc = pm_runtime_get_sync(dev); |
b7b57a56 | 70 | if (rc < 0) { |
71 | pm_runtime_put_noidle(dev); | |
72 | return rc; | |
73 | } | |
4c3f9727 | 74 | |
b7b57a56 | 75 | return 0; |
4c3f9727 GBY |
76 | } |
77 | ||
bc88606a | 78 | void cc_pm_put_suspend(struct device *dev) |
4c3f9727 | 79 | { |
8c7849a3 GU |
80 | pm_runtime_mark_last_busy(dev); |
81 | pm_runtime_put_autosuspend(dev); | |
4c3f9727 | 82 | } |