blob: f87bcb3beaa25440836a690dfd5c1bd8d786b921 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -04002/*
3 * Keystone: PSC configuration module
4 *
5 * (C) Copyright 2012-2014
6 * Texas Instruments Incorporated, <www.ti.com>
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -04007 */
8
9#include <common.h>
Masahiro Yamada64e4f7f2016-09-21 11:28:57 +090010#include <linux/errno.h>
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -040011#include <asm/io.h>
12#include <asm/processor.h>
13#include <asm/arch/psc_defs.h>
14
Nishanth Menonb3ec5de2016-02-25 12:53:42 -060015/**
16 * psc_delay() - delay for psc
17 *
18 * Return: 10
19 */
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -040020int psc_delay(void)
21{
22 udelay(10);
23 return 10;
24}
25
Nishanth Menonb3ec5de2016-02-25 12:53:42 -060026/**
27 * psc_wait() - Wait for end of transitional state
28 * @domain_num: GPSC domain number
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -040029 *
Nishanth Menonb3ec5de2016-02-25 12:53:42 -060030 * Polls pstat for the selected domain and waits for transitions to be complete.
31 * Since this is boot loader code it is *ASSUMED* that interrupts are disabled
32 * and no other core is mucking around with the psc at the same time.
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -040033 *
Nishanth Menonb3ec5de2016-02-25 12:53:42 -060034 * Return: 0 when the domain is free. Returns -1 if a timeout occurred waiting
35 * for the completion.
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -040036 */
37int psc_wait(u32 domain_num)
38{
39 u32 retry;
40 u32 ptstat;
41
42 /*
43 * Do nothing if the power domain is in transition. This should never
44 * happen since the boot code is the only software accesses psc.
45 * It's still remotely possible that the hardware state machines
46 * initiate transitions.
47 * Don't trap if the domain (or a module in this domain) is
48 * stuck in transition.
49 */
50 retry = 0;
51
52 do {
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +030053 ptstat = __raw_readl(KS2_PSC_BASE + PSC_REG_PSTAT);
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -040054 ptstat = ptstat & (1 << domain_num);
55 } while ((ptstat != 0) && ((retry += psc_delay()) <
56 PSC_PTSTAT_TIMEOUT_LIMIT));
57
58 if (retry >= PSC_PTSTAT_TIMEOUT_LIMIT)
59 return -1;
60
61 return 0;
62}
63
Nishanth Menonb3ec5de2016-02-25 12:53:42 -060064/**
65 * psc_get_domain_num() - Get the domain number
66 * @mod_num: LPSC module number
67 */
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -040068u32 psc_get_domain_num(u32 mod_num)
69{
70 u32 domain_num;
71
72 /* Get the power domain associated with the module number */
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +030073 domain_num = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCFG(mod_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -040074 domain_num = PSC_REG_MDCFG_GET_PD(domain_num);
75
76 return domain_num;
77}
78
Nishanth Menonb3ec5de2016-02-25 12:53:42 -060079/**
80 * psc_set_state() - powers up/down a module
81 * @mod_num: LPSC module number
82 * @state: 1 to enable, 0 to disable.
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -040083 *
Nishanth Menonb3ec5de2016-02-25 12:53:42 -060084 * Powers up/down the requested module and the associated power domain if
85 * required. No action is taken it the module is already powered up/down.
86 * This only controls modules. The domain in which the module resides will
87 * be left in the power on state. Multiple modules can exist in a power
88 * domain, so powering down the domain based on a single module is not done.
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -040089 *
Nishanth Menonb3ec5de2016-02-25 12:53:42 -060090 * Return: 0 on success, -1 if the module can't be powered up, or if there is a
91 * timeout waiting for the transition.
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -040092 */
93int psc_set_state(u32 mod_num, u32 state)
94{
95 u32 domain_num;
96 u32 pdctl;
97 u32 mdctl;
98 u32 ptcmd;
99 u32 reset_iso;
100 u32 v;
101
102 /*
103 * Get the power domain associated with the module number, and reset
104 * isolation functionality
105 */
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300106 v = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCFG(mod_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400107 domain_num = PSC_REG_MDCFG_GET_PD(v);
108 reset_iso = PSC_REG_MDCFG_GET_RESET_ISO(v);
109
110 /* Wait for the status of the domain/module to be non-transitional */
111 if (psc_wait(domain_num) != 0)
112 return -1;
113
114 /*
115 * Perform configuration even if the current status matches the
116 * existing state
117 *
118 * Set the next state of the power domain to on. It's OK if the domain
119 * is always on. This code will not ever power down a domain, so no
120 * change is made if the new state is power down.
121 */
122 if (state == PSC_REG_VAL_MDCTL_NEXT_ON) {
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300123 pdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_PDCTL(domain_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400124 pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl,
125 PSC_REG_VAL_PDCTL_NEXT_ON);
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300126 __raw_writel(pdctl, KS2_PSC_BASE + PSC_REG_PDCTL(domain_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400127 }
128
129 /* Set the next state for the module to enabled/disabled */
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300130 mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400131 mdctl = PSC_REG_MDCTL_SET_NEXT(mdctl, state);
132 mdctl = PSC_REG_MDCTL_SET_RESET_ISO(mdctl, reset_iso);
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300133 __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400134
135 /* Trigger the enable */
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300136 ptcmd = __raw_readl(KS2_PSC_BASE + PSC_REG_PTCMD);
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400137 ptcmd |= (u32)(1<<domain_num);
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300138 __raw_writel(ptcmd, KS2_PSC_BASE + PSC_REG_PTCMD);
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400139
140 /* Wait on the complete */
141 return psc_wait(domain_num);
142}
143
Nishanth Menonb3ec5de2016-02-25 12:53:42 -0600144/**
145 * psc_enable_module() - power up a module
146 * @mod_num: LPSC module number
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400147 *
Nishanth Menonb3ec5de2016-02-25 12:53:42 -0600148 * Powers up the requested module and the associated power domain
149 * if required. No action is taken it the module is already powered up.
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400150 *
Nishanth Menonb3ec5de2016-02-25 12:53:42 -0600151 * Return: 0 on success, -1 if the module can't be powered up, or
152 * if there is a timeout waiting for the transition.
153 *
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400154 */
155int psc_enable_module(u32 mod_num)
156{
157 u32 mdctl;
158
159 /* Set the bit to apply reset */
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300160 mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400161 if ((mdctl & 0x3f) == PSC_REG_VAL_MDSTAT_STATE_ON)
162 return 0;
163
164 return psc_set_state(mod_num, PSC_REG_VAL_MDCTL_NEXT_ON);
165}
166
Nishanth Menonb3ec5de2016-02-25 12:53:42 -0600167/**
168 * psc_disable_module() - Power down a module
169 * @mod_num: LPSC module number
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400170 *
Nishanth Menonb3ec5de2016-02-25 12:53:42 -0600171 * Return: 0 on success, -1 on failure or timeout.
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400172 */
173int psc_disable_module(u32 mod_num)
174{
175 u32 mdctl;
176
177 /* Set the bit to apply reset */
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300178 mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400179 if ((mdctl & 0x3f) == 0)
180 return 0;
181 mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl, 0);
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300182 __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400183
184 return psc_set_state(mod_num, PSC_REG_VAL_MDCTL_NEXT_SWRSTDISABLE);
185}
186
Nishanth Menonb3ec5de2016-02-25 12:53:42 -0600187/**
188 * psc_set_reset_iso() - Set the reset isolation bit in mdctl
189 * @mod_num: LPSC module number
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400190 *
Nishanth Menonb3ec5de2016-02-25 12:53:42 -0600191 * The reset isolation enable bit is set. The state of the module is not
192 * changed.
193 *
194 * Return: 0 if the module config showed that reset isolation is supported.
195 * Returns 1 otherwise. This is not an error, but setting the bit in mdctl
196 * has no effect.
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400197 */
198int psc_set_reset_iso(u32 mod_num)
199{
200 u32 v;
201 u32 mdctl;
202
203 /* Set the reset isolation bit */
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300204 mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400205 mdctl = PSC_REG_MDCTL_SET_RESET_ISO(mdctl, 1);
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300206 __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400207
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300208 v = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCFG(mod_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400209 if (PSC_REG_MDCFG_GET_RESET_ISO(v) == 1)
210 return 0;
211
212 return 1;
213}
214
Nishanth Menonb3ec5de2016-02-25 12:53:42 -0600215/**
216 * psc_disable_domain() - Disable a power domain
217 * @domain_num: GPSC domain number
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400218 */
219int psc_disable_domain(u32 domain_num)
220{
221 u32 pdctl;
222 u32 ptcmd;
223
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300224 pdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_PDCTL(domain_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400225 pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl, PSC_REG_VAL_PDCTL_NEXT_OFF);
226 pdctl = PSC_REG_PDCTL_SET_PDMODE(pdctl, PSC_REG_VAL_PDCTL_PDMODE_SLEEP);
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300227 __raw_writel(pdctl, KS2_PSC_BASE + PSC_REG_PDCTL(domain_num));
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400228
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300229 ptcmd = __raw_readl(KS2_PSC_BASE + PSC_REG_PTCMD);
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400230 ptcmd |= (u32)(1 << domain_num);
Khoronzhuk, Ivan49d39a22014-08-28 16:07:45 +0300231 __raw_writel(ptcmd, KS2_PSC_BASE + PSC_REG_PTCMD);
Vitaly Andrianov7bcf4d62014-04-04 13:16:53 -0400232
233 return psc_wait(domain_num);
234}
Nishanth Menon06a10872016-02-25 12:53:44 -0600235
236/**
237 * psc_module_keep_in_reset_enabled() - Keep module in enabled,in-reset state
238 * @mod_num: LPSC module number
239 * @gate_clocks: Can the clocks be gated on this module?
240 *
241 * Enable the module, but do not release the module from local reset. This is
242 * necessary for many processor systems on keystone SoCs to allow for system
243 * initialization from a master processor prior to releasing the processor
244 * from reset.
245 */
246int psc_module_keep_in_reset_enabled(u32 mod_num, bool gate_clocks)
247{
248 u32 mdctl, ptcmd, mdstat;
249 u32 next_state;
250 int domain_num = psc_get_domain_num(mod_num);
251 int timeout = 100000;
252
253 /* Wait for any previous transitions to complete */
254 psc_wait(domain_num);
255 mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
256 /* Should be set 0 to assert Local reset */
257 if ((mdctl & PSC_REG_MDCTL_SET_LRSTZ(mdctl, 1))) {
258 mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl, 0);
259 __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
260 /* Wait for transition to take place */
261 psc_wait(domain_num);
262 }
263
264 /* Clear Module reset */
265 mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
266 next_state = gate_clocks ? PSC_REG_VAL_MDCTL_NEXT_OFF :
267 PSC_REG_VAL_MDCTL_NEXT_ON;
268 mdctl = PSC_REG_MDCTL_SET_NEXT(mdctl, next_state);
269 __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
270 /* Trigger PD transition */
271 ptcmd = __raw_readl(KS2_PSC_BASE + PSC_REG_PTCMD);
272 ptcmd |= (u32)(1 << domain_num);
273 __raw_writel(ptcmd, KS2_PSC_BASE + PSC_REG_PTCMD);
274 psc_wait(domain_num);
275
276 mdstat = __raw_readl(KS2_PSC_BASE + PSC_REG_MDSTAT(mod_num));
277 while (timeout) {
278 mdstat = __raw_readl(KS2_PSC_BASE + PSC_REG_MDSTAT(mod_num));
279
280 if (!(PSC_REG_MDSTAT_GET_STATUS(mdstat) & 0x30) &&
281 PSC_REG_MDSTAT_GET_MRSTDONE(mdstat) &&
282 PSC_REG_MDSTAT_GET_LRSTDONE(mdstat))
283 break;
284 timeout--;
285 }
286
287 if (!timeout) {
288 printf("%s: Timedout waiting for mdstat(0x%08x) to change\n",
289 __func__, mdstat);
290 return -ETIMEDOUT;
291 }
292 return 0;
293}
294
295/**
296 * psc_module_release_from_reset() - Release the module from reset
297 * @mod_num: LPSC module number
298 *
299 * This is the follow through for the command 'psc_module_keep_in_reset_enabled'
300 * Allowing the module to be released from reset once all required inits are
301 * complete for the module. Typically, this allows the processor module to start
302 * execution.
303 */
304int psc_module_release_from_reset(u32 mod_num)
305{
306 u32 mdctl, mdstat;
307 int domain_num = psc_get_domain_num(mod_num);
308 int timeout = 100000;
309
310 /* Wait for any previous transitions to complete */
311 psc_wait(domain_num);
312 mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
313 /* Should be set to 1 to de-assert Local reset */
314 if ((mdctl & PSC_REG_MDCTL_SET_LRSTZ(mdctl, 0))) {
315 mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl, 1);
316 __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
317 /* Wait for transition to take place */
318 psc_wait(domain_num);
319 }
320 mdstat = __raw_readl(KS2_PSC_BASE + PSC_REG_MDSTAT(mod_num));
321 while (timeout) {
322 mdstat = __raw_readl(KS2_PSC_BASE + PSC_REG_MDSTAT(mod_num));
323
324 if (!(PSC_REG_MDSTAT_GET_STATUS(mdstat) & 0x30) &&
325 PSC_REG_MDSTAT_GET_MRSTDONE(mdstat) &&
326 PSC_REG_MDSTAT_GET_LRSTDONE(mdstat))
327 break;
328 timeout--;
329 }
330
331 if (!timeout) {
332 printf("%s: Timedout waiting for mdstat(0x%08x) to change\n",
333 __func__, mdstat);
334 return -ETIMEDOUT;
335 }
336
337 return 0;
338}