]> git.sur5r.net Git - u-boot/blob - arch/arm/cpu/armv7/keystone/psc.c
ARM: keystone: clock: move K2HK SoC dependent code in separate file
[u-boot] / arch / arm / cpu / armv7 / keystone / psc.c
1 /*
2  * Keystone: PSC configuration module
3  *
4  * (C) Copyright 2012-2014
5  *     Texas Instruments Incorporated, <www.ti.com>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <asm-generic/errno.h>
12 #include <asm/io.h>
13 #include <asm/processor.h>
14 #include <asm/arch/psc_defs.h>
15
16 #define DEVICE_REG32_R(addr)                    __raw_readl((u32 *)(addr))
17 #define DEVICE_REG32_W(addr, val)               __raw_writel(val, (u32 *)(addr))
18
19 int psc_delay(void)
20 {
21         udelay(10);
22         return 10;
23 }
24
25 /*
26  * FUNCTION PURPOSE: Wait for end of transitional state
27  *
28  * DESCRIPTION: Polls pstat for the selected domain and waits for transitions
29  *              to be complete.
30  *
31  *              Since this is boot loader code it is *ASSUMED* that interrupts
32  *              are disabled and no other core is mucking around with the psc
33  *              at the same time.
34  *
35  *              Returns 0 when the domain is free. Returns -1 if a timeout
36  *              occurred waiting for the completion.
37  */
38 int psc_wait(u32 domain_num)
39 {
40         u32 retry;
41         u32 ptstat;
42
43         /*
44          * Do nothing if the power domain is in transition. This should never
45          * happen since the boot code is the only software accesses psc.
46          * It's still remotely possible that the hardware state machines
47          * initiate transitions.
48          * Don't trap if the domain (or a module in this domain) is
49          * stuck in transition.
50          */
51         retry = 0;
52
53         do {
54                 ptstat = DEVICE_REG32_R(KS2_PSC_BASE + PSC_REG_PSTAT);
55                 ptstat = ptstat & (1 << domain_num);
56         } while ((ptstat != 0) && ((retry += psc_delay()) <
57                  PSC_PTSTAT_TIMEOUT_LIMIT));
58
59         if (retry >= PSC_PTSTAT_TIMEOUT_LIMIT)
60                 return -1;
61
62         return 0;
63 }
64
65 u32 psc_get_domain_num(u32 mod_num)
66 {
67         u32 domain_num;
68
69         /* Get the power domain associated with the module number */
70         domain_num = DEVICE_REG32_R(KS2_PSC_BASE +
71                                     PSC_REG_MDCFG(mod_num));
72         domain_num = PSC_REG_MDCFG_GET_PD(domain_num);
73
74         return domain_num;
75 }
76
77 /*
78  * FUNCTION PURPOSE: Power up/down a module
79  *
80  * DESCRIPTION: Powers up/down the requested module and the associated power
81  *              domain if required. No action is taken it the module is
82  *              already powered up/down.
83  *
84  *              This only controls modules. The domain in which the module
85  *              resides will be left in the power on state. Multiple modules
86  *              can exist in a power domain, so powering down the domain based
87  *              on a single module is not done.
88  *
89  *              Returns 0 on success, -1 if the module can't be powered up, or
90  *              if there is a timeout waiting for the transition.
91  */
92 int psc_set_state(u32 mod_num, u32 state)
93 {
94         u32 domain_num;
95         u32 pdctl;
96         u32 mdctl;
97         u32 ptcmd;
98         u32 reset_iso;
99         u32 v;
100
101         /*
102          * Get the power domain associated with the module number, and reset
103          * isolation functionality
104          */
105         v = DEVICE_REG32_R(KS2_PSC_BASE + PSC_REG_MDCFG(mod_num));
106         domain_num = PSC_REG_MDCFG_GET_PD(v);
107         reset_iso  = PSC_REG_MDCFG_GET_RESET_ISO(v);
108
109         /* Wait for the status of the domain/module to be non-transitional */
110         if (psc_wait(domain_num) != 0)
111                 return -1;
112
113         /*
114          * Perform configuration even if the current status matches the
115          * existing state
116          *
117          * Set the next state of the power domain to on. It's OK if the domain
118          * is always on. This code will not ever power down a domain, so no
119          * change is made if the new state is power down.
120          */
121         if (state == PSC_REG_VAL_MDCTL_NEXT_ON) {
122                 pdctl = DEVICE_REG32_R(KS2_PSC_BASE +
123                                        PSC_REG_PDCTL(domain_num));
124                 pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl,
125                                                PSC_REG_VAL_PDCTL_NEXT_ON);
126                 DEVICE_REG32_W(KS2_PSC_BASE + PSC_REG_PDCTL(domain_num),
127                                pdctl);
128         }
129
130         /* Set the next state for the module to enabled/disabled */
131         mdctl = DEVICE_REG32_R(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
132         mdctl = PSC_REG_MDCTL_SET_NEXT(mdctl, state);
133         mdctl = PSC_REG_MDCTL_SET_RESET_ISO(mdctl, reset_iso);
134         DEVICE_REG32_W(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num), mdctl);
135
136         /* Trigger the enable */
137         ptcmd = DEVICE_REG32_R(KS2_PSC_BASE + PSC_REG_PTCMD);
138         ptcmd |= (u32)(1<<domain_num);
139         DEVICE_REG32_W(KS2_PSC_BASE + PSC_REG_PTCMD, ptcmd);
140
141         /* Wait on the complete */
142         return psc_wait(domain_num);
143 }
144
145 /*
146  * FUNCTION PURPOSE: Power up a module
147  *
148  * DESCRIPTION: Powers up the requested module and the associated power domain
149  *              if required. No action is taken it the module is already
150  *              powered up.
151  *
152  *              Returns 0 on success, -1 if the module can't be powered up, or
153  *              if there is a timeout waiting for the transition.
154  */
155 int psc_enable_module(u32 mod_num)
156 {
157         u32 mdctl;
158
159         /* Set the bit to apply reset */
160         mdctl = DEVICE_REG32_R(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
161         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
167 /*
168  * FUNCTION PURPOSE: Power down a module
169  *
170  * DESCRIPTION: Powers down the requested module.
171  *
172  *              Returns 0 on success, -1 on failure or timeout.
173  */
174 int psc_disable_module(u32 mod_num)
175 {
176         u32 mdctl;
177
178         /* Set the bit to apply reset */
179         mdctl = DEVICE_REG32_R(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
180         if ((mdctl & 0x3f) == 0)
181                 return 0;
182         mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl, 0);
183         DEVICE_REG32_W(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num), mdctl);
184
185         return psc_set_state(mod_num, PSC_REG_VAL_MDCTL_NEXT_SWRSTDISABLE);
186 }
187
188 /*
189  * FUNCTION PURPOSE: Set the reset isolation bit in mdctl
190  *
191  * DESCRIPTION: The reset isolation enable bit is set. The state of the module
192  *              is not changed. Returns 0 if the module config showed that
193  *              reset isolation is supported. Returns 1 otherwise. This is not
194  *              an error, but setting the bit in mdctl has no effect.
195  */
196 int psc_set_reset_iso(u32 mod_num)
197 {
198         u32 v;
199         u32 mdctl;
200
201         /* Set the reset isolation bit */
202         mdctl = DEVICE_REG32_R(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
203         mdctl = PSC_REG_MDCTL_SET_RESET_ISO(mdctl, 1);
204         DEVICE_REG32_W(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num), mdctl);
205
206         v = DEVICE_REG32_R(KS2_PSC_BASE + PSC_REG_MDCFG(mod_num));
207         if (PSC_REG_MDCFG_GET_RESET_ISO(v) == 1)
208                 return 0;
209
210         return 1;
211 }
212
213 /*
214  * FUNCTION PURPOSE: Disable a power domain
215  *
216  * DESCRIPTION: The power domain is disabled
217  */
218 int psc_disable_domain(u32 domain_num)
219 {
220         u32 pdctl;
221         u32 ptcmd;
222
223         pdctl = DEVICE_REG32_R(KS2_PSC_BASE + PSC_REG_PDCTL(domain_num));
224         pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl, PSC_REG_VAL_PDCTL_NEXT_OFF);
225         pdctl = PSC_REG_PDCTL_SET_PDMODE(pdctl, PSC_REG_VAL_PDCTL_PDMODE_SLEEP);
226         DEVICE_REG32_W(KS2_PSC_BASE + PSC_REG_PDCTL(domain_num), pdctl);
227
228         ptcmd = DEVICE_REG32_R(KS2_PSC_BASE + PSC_REG_PTCMD);
229         ptcmd |= (u32)(1 << domain_num);
230         DEVICE_REG32_W(KS2_PSC_BASE + PSC_REG_PTCMD, ptcmd);
231
232         return psc_wait(domain_num);
233 }