]>
Commit | Line | Data |
---|---|---|
abefd674 GBY |
1 | /* |
2 | * Copyright (C) 2012-2017 ARM Limited or its affiliates. | |
c8f17865 | 3 | * |
abefd674 GBY |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License version 2 as | |
6 | * published by the Free Software Foundation. | |
c8f17865 | 7 | * |
abefd674 GBY |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
c8f17865 | 12 | * |
abefd674 GBY |
13 | * You should have received a copy of the GNU General Public License |
14 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | ||
18 | #include "ssi_config.h" | |
19 | #include <linux/kernel.h> | |
20 | #include <linux/platform_device.h> | |
21 | #include <linux/interrupt.h> | |
22 | #include <crypto/ctr.h> | |
23 | #include <linux/pm_runtime.h> | |
24 | #include "ssi_driver.h" | |
25 | #include "ssi_buffer_mgr.h" | |
26 | #include "ssi_request_mgr.h" | |
27 | #include "ssi_sram_mgr.h" | |
28 | #include "ssi_sysfs.h" | |
a4d826b9 | 29 | #include "ssi_ivgen.h" |
50cfbbb7 | 30 | #include "ssi_hash.h" |
abefd674 | 31 | #include "ssi_pm.h" |
abefd674 GBY |
32 | |
33 | ||
34 | #if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP) | |
35 | ||
36 | #define POWER_DOWN_ENABLE 0x01 | |
37 | #define POWER_DOWN_DISABLE 0x00 | |
38 | ||
39 | ||
40 | int ssi_power_mgr_runtime_suspend(struct device *dev) | |
41 | { | |
42 | struct ssi_drvdata *drvdata = | |
43 | (struct ssi_drvdata *)dev_get_drvdata(dev); | |
44 | int rc; | |
45 | ||
46 | SSI_LOG_DEBUG("ssi_power_mgr_runtime_suspend: set HOST_POWER_DOWN_EN\n"); | |
47 | WRITE_REGISTER(drvdata->cc_base + CC_REG_OFFSET(HOST_RGF, HOST_POWER_DOWN_EN), POWER_DOWN_ENABLE); | |
48 | rc = ssi_request_mgr_runtime_suspend_queue(drvdata); | |
49 | if (rc != 0) { | |
50 | SSI_LOG_ERR("ssi_request_mgr_runtime_suspend_queue (%x)\n", rc); | |
51 | return rc; | |
52 | } | |
53 | fini_cc_regs(drvdata); | |
675ef02f | 54 | cc_clk_off(drvdata); |
abefd674 GBY |
55 | return 0; |
56 | } | |
57 | ||
58 | int ssi_power_mgr_runtime_resume(struct device *dev) | |
59 | { | |
60 | int rc; | |
61 | struct ssi_drvdata *drvdata = | |
62 | (struct ssi_drvdata *)dev_get_drvdata(dev); | |
63 | ||
64 | SSI_LOG_DEBUG("ssi_power_mgr_runtime_resume , unset HOST_POWER_DOWN_EN\n"); | |
65 | WRITE_REGISTER(drvdata->cc_base + CC_REG_OFFSET(HOST_RGF, HOST_POWER_DOWN_EN), POWER_DOWN_DISABLE); | |
675ef02f GBY |
66 | |
67 | rc = cc_clk_on(drvdata); | |
68 | if (rc) { | |
69 | SSI_LOG_ERR("failed getting clock back on. We're toast.\n"); | |
70 | return rc; | |
71 | } | |
abefd674 GBY |
72 | |
73 | rc = init_cc_regs(drvdata, false); | |
74 | if (rc !=0) { | |
75 | SSI_LOG_ERR("init_cc_regs (%x)\n",rc); | |
76 | return rc; | |
77 | } | |
78 | ||
79 | rc = ssi_request_mgr_runtime_resume_queue(drvdata); | |
80 | if (rc !=0) { | |
81 | SSI_LOG_ERR("ssi_request_mgr_runtime_resume_queue (%x)\n",rc); | |
82 | return rc; | |
83 | } | |
84 | ||
50cfbbb7 GBY |
85 | /* must be after the queue resuming as it uses the HW queue*/ |
86 | ssi_hash_init_sram_digest_consts(drvdata); | |
c8f17865 | 87 | |
a4d826b9 | 88 | ssi_ivgen_init_sram_pool(drvdata); |
abefd674 GBY |
89 | return 0; |
90 | } | |
91 | ||
92 | int ssi_power_mgr_runtime_get(struct device *dev) | |
93 | { | |
94 | int rc = 0; | |
95 | ||
96 | if (ssi_request_mgr_is_queue_runtime_suspend( | |
97 | (struct ssi_drvdata *)dev_get_drvdata(dev))) { | |
98 | rc = pm_runtime_get_sync(dev); | |
99 | } else { | |
100 | pm_runtime_get_noresume(dev); | |
101 | } | |
102 | return rc; | |
103 | } | |
104 | ||
105 | int ssi_power_mgr_runtime_put_suspend(struct device *dev) | |
106 | { | |
107 | int rc = 0; | |
108 | ||
109 | if (!ssi_request_mgr_is_queue_runtime_suspend( | |
110 | (struct ssi_drvdata *)dev_get_drvdata(dev))) { | |
111 | pm_runtime_mark_last_busy(dev); | |
112 | rc = pm_runtime_put_autosuspend(dev); | |
113 | } | |
114 | else { | |
115 | /* Something wrong happens*/ | |
116 | BUG(); | |
117 | } | |
118 | return rc; | |
119 | ||
120 | } | |
121 | ||
122 | #endif | |
123 | ||
124 | ||
125 | ||
126 | int ssi_power_mgr_init(struct ssi_drvdata *drvdata) | |
127 | { | |
128 | int rc = 0; | |
129 | #if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP) | |
130 | struct platform_device *plat_dev = drvdata->plat_dev; | |
131 | /* must be before the enabling to avoid resdundent suspending */ | |
132 | pm_runtime_set_autosuspend_delay(&plat_dev->dev,SSI_SUSPEND_TIMEOUT); | |
133 | pm_runtime_use_autosuspend(&plat_dev->dev); | |
134 | /* activate the PM module */ | |
135 | rc = pm_runtime_set_active(&plat_dev->dev); | |
136 | if (rc != 0) | |
137 | return rc; | |
138 | /* enable the PM module*/ | |
139 | pm_runtime_enable(&plat_dev->dev); | |
140 | #endif | |
141 | return rc; | |
142 | } | |
143 | ||
144 | void ssi_power_mgr_fini(struct ssi_drvdata *drvdata) | |
145 | { | |
146 | #if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP) | |
147 | struct platform_device *plat_dev = drvdata->plat_dev; | |
148 | ||
149 | pm_runtime_disable(&plat_dev->dev); | |
150 | #endif | |
151 | } |