be39bca9201d8a8a0b190be623a153a287e52c6a
[keystone-rtos/ibl.git] / src / hw / pscs / psccur / psc.c
1 /***********************************************************************************
2  * FILE PURPOSE: Driver for the PSC module
3  ***********************************************************************************
4  * FILE NAME: psc.c
5  *
6  * DESCRIPTION: The boot loader PSC driver
7  *
8  * Copyright (C) 2006, Texas Instruments, Inc.
9  * @file psc.c
10  * 
11  * @brief
12  *   The PSC 2.0.x driver
13  *
14  *  Redistribution and use in source and binary forms, with or without 
15  *  modification, are permitted provided that the following conditions 
16  *  are met:
17  *
18  *    Redistributions of source code must retain the above copyright 
19  *    notice, this list of conditions and the following disclaimer.
20  *
21  *    Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the 
23  *    documentation and/or other materials provided with the   
24  *    distribution.
25  *
26  *    Neither the name of Texas Instruments Incorporated nor the names of
27  *    its contributors may be used to endorse or promote products derived
28  *    from this software without specific prior written permission.
29  *
30  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
31  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
32  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
34  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
35  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
36  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
39  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
40  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  *
42 */
43 #include "types.h"
44 #include "pscapi.h"
45 #include "pscloc.h"
46 #include "target.h"
49 #define DEVICE_REG32_W(x,y)   *(volatile unsigned int *)(x)=(y)
50 #define DEVICE_REG32_R(x)    (*(volatile unsigned int *)(x))
52 /***********************************************************************************
53  * FUNCTION PURPOSE: Wait!
54  ***********************************************************************************
55  * DESCRIPTION: This function doesn't do didly. It loops around for a bit
56  *              to give transitions some time to occur.
57  *              This function always returns 1.
58  ***********************************************************************************/
59 int16 pscDelay (void)
60 {
61   volatile uint32 i;
62   for (i = 0; i < 10000; i++);
64   return (1);
66 } /* pscDelay */
69 /***********************************************************************************
70  * FUNCTION PURPOSE: Wait for end of transitional state
71  ***********************************************************************************
72  * DESCRIPTION: Polls pstat for the selected domain and waits for transitions
73  *              to be complete. 
74  *
75  *              Since this is boot loader code it is *ASSUMED* that interrupts
76  *              are disabled and no other core is mucking around with the psc
77  *              at the same time.
78  *
79  *              Returns 0 when the domain is free. Returns -1 if a timeout
80  *              occurred waiting for the completion.
81  ***********************************************************************************/
82 int16 pscWait (uint32 domainNum)
83 {
84   uint32 retry;
85   uint32 ptstat;
87   /* Do nothing if the power domain is in transition. This should never
88    * happen since the boot code is the only software accesses psc. 
89    * It's still remotely possible that the hardware state machines initiate transitions. 
90    * Don't trap if the domain (or a module in this domain) is 
91    * stuck in transition.  */
92   retry = 0;
94   do  {
96     ptstat = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PSTAT);
97     ptstat = ptstat & (1 << domainNum);
99   } while ((ptstat != 0) &&  ((retry += pscDelay ()) < PSC_PTSTAT_TIMEOUT_LIMIT));
101   if (retry >= PSC_PTSTAT_TIMEOUT_LIMIT)
102     return (-1);
104   return (0);
106 } /* pscWait */
109 /***********************************************************************************
110  * FUNCTION PURPOSE: Return the PSC state
111  ***********************************************************************************
112  * DESCRIPTION: Checks the power state of the module
113  ***********************************************************************************/
114 BOOL pscModuleIsEnabled (uint32 modNum)
116 #if 0
117         uint32 domainNum;
118   uint32 mdstat;
120   /* Get the power domain associated with the module number */
121   domainNum = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCFG(modNum));
122   domainNum = PSC_REG_MDCFG_GET_PD (domainNum);
124   /* Wait for the status of the domain/module to be non-transitional,
125    * but don't trap if stuck in a transitional state. */ 
126   pscWait (domainNum);
128   mdstat = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDSTAT(modNum));
129   mdstat = PSC_REG_MDSTAT_GET_STATUS (mdstat);
131   if ((mdstat == PSC_REG_VAL_MDSTAT_STATE_ON) || 
132       (mdstat == PSC_REG_VAL_MDSTAT_STATE_ENABLE_IN_PROG))
133       return (TRUE);
135   else  
137     return (FALSE);
138 #endif
140   return (TRUE);
141 } /* pscModuleIsEnabled */
146 /***********************************************************************************
147  * FUNCTION PURPOSE: Power up/down a module
148  ***********************************************************************************
149  * DESCRIPTION: Powers up/down the requested module and the associated power domain
150  *              if required. No action is taken it the module is already 
151  *              powered up/down.
152  *
153  *              This only controls modules. The domain in which the module 
154  *              resides will be left in the power on state. Multiple modules
155  *              can exist in a power domain, so powering down the domain based
156  *              on a single module is not done.
157  *
158  *              Returns 0 on success, -1 if the module can't be powered up, or
159  *              if there is a timeout waiting for the transition.
160  ***********************************************************************************/
161 int16 pscSetState (uint32 modNum, uint32 state)
163 #if 0
164   uint32 domainNum;
165   uint32 pdctl;
166   uint32 mdctl;
167   uint32 ptcmd;
168   uint32 resetIso;
169   uint32 v;
171   /* Get the power domain associated with the module number, and reset
172    * isolation functionality */
173   v         = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCFG(modNum));
174   domainNum = PSC_REG_MDCFG_GET_PD (v);
175   resetIso  = PSC_REG_MDCFG_GET_RESET_ISO(v);
178   /* Wait for the status of the domain/module to be non-transitional */ 
179   if (pscWait (domainNum) != 0)
180     return (-1);
183   /* Perform configuration even if the current status matches the existing state */
186   /* Set the next state of the power domain to on. It's OK if the domain
187    * is always on. This code will not ever power down a domain, so no change
188    * is made if the new state is power down. */
189   if (state == PSC_REG_VAL_MDCTL_NEXT_ON)  {
190       pdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum));
191       pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl, PSC_REG_VAL_PDCTL_NEXT_ON);
192       DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum), pdctl);
193   }
196   /* Set the next state for the module to enabled/disabled */
197   mdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum));
198   mdctl = PSC_REG_MDCTL_SET_NEXT (mdctl, state);
199   mdctl = PSC_REG_MDCTL_SET_RESET_ISO (mdctl, resetIso);
200   DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum), mdctl);
202   /* Trigger the enable */
203   ptcmd = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PTCMD);
204   ptcmd |= (uint32)(1<<domainNum);
205   DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PTCMD, ptcmd);
208   /* Wait on the complete */
209   return (pscWait (domainNum));
210 #endif
211 return 0;
212 } /* pscSetState*/
215 /***********************************************************************************
216  * FUNCTION PURPOSE: Power up a module
217  ***********************************************************************************
218  * DESCRIPTION: Powers up the requested module and the associated power domain
219  *              if required. No action is taken it the module is already 
220  *              powered up.
221  *
222  *              Returns 0 on success, -1 if the module can't be powered up, or
223  *              if there is a timeout waiting for the transition.
224  ***********************************************************************************/
225 int16 pscEnableModule (uint32 modNum)
228 //  return (pscSetState (modNum, PSC_REG_VAL_MDCTL_NEXT_ON));
229  return 0;
230 } /* pscEnableModule */
232 /************************************************************************************
233  * FUNCTION PURPOSE: Power down a module
234  ************************************************************************************
235  * DESCRIPTION: Powers down the requested module.
236  *  
237  *              Returns 0 on success, -1 on failure or timeout.
238  ************************************************************************************/
239 int16 pscDisableModule (uint32 modNum)
241 #if 0
242         uint32 mdctl;
244   /* Set the bit to apply reset */
245   mdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum));
246   mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl,0);
247   DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum), mdctl);
249   return (pscSetState (modNum, PSC_REG_VAL_MDCTL_NEXT_SWRSTDISABLE));
250 #endif
251   return 0;
252 } /* pscDisableModule */
255 /************************************************************************************
256  * FUNCTION PURPOSE: Set the reset isolation bit in mdctl
257  ************************************************************************************
258  * DESCRIPTION: The reset isolation enable bit is set. The state of the module
259  *              is not changed. Returns 0 if the module config showed that
260  *              reset isolation is supported. Returns 1 otherwise. This is not
261  *              an error, but setting the bit in mdctl has no effect.
262  ************************************************************************************/
263 int16 pscSetResetIso (uint32 modNum)
265 #if 0
266         uint32 v;
267   uint32 mdctl;
269   /* Set the reset isolation bit */
270   mdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum));
271   mdctl = PSC_REG_MDCTL_SET_RESET_ISO (mdctl, 1);
272   DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum), mdctl);
273   
274   v = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCFG(modNum));
275   if (PSC_REG_MDCFG_GET_RESET_ISO(v) == 1)
276     return (0);
278   return (1);
279 #endif
281   return (0);
282 } /* pscSetResetIso */
284 /*************************************************************************************
285  * FUNCTION PURPOSE: Disable a power domain
286  *************************************************************************************
287  * DESCRIPTION: The power domain is disabled
288  *************************************************************************************/
289 int16 pscDisableDomain (uint32 domainNum)
291 #if 0   
292   uint32 pdctl;
293   uint32 ptcmd;
295   pdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum));
296   pdctl = PSC_REG_PDCTL_SET_NEXT (pdctl, PSC_REG_VAL_PDCTL_NEXT_OFF);
297   pdctl = PSC_REG_PDCTL_SET_PDMODE (pdctl, PSC_REG_VAL_PDCTL_PDMODE_SLEEP);
298   DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum), pdctl);
300   ptcmd = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PTCMD);
301   ptcmd |= (uint32)(1<<domainNum);
302   DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PTCMD, ptcmd);
303 #endif
304   return (0);
306 } /* pscDisableDomain */
309 /*************************************************************************************
310  * FUNCTION PURPOSE: Power down a domain
311  *************************************************************************************
312  * DESCRIPTION: The specified power domain is set to the disabled state
313  *************************************************************************************/
314 void pscDisableModAndDomain (uint32 modNum, uint32 domainNum)
316 #if 0
317    uint32 pdctl;
318   uint32 ptcmd;
319   uint32 mdctl;
322   mdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum));
323   mdctl = PSC_REG_MDCTL_SET_NEXT(mdctl, PSC_REG_VAL_MDCTL_NEXT_SWRSTDISABLE);
324   mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl,0);
325   DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum), mdctl);
328   pdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum));
329   pdctl = PSC_REG_PDCTL_SET_NEXT (pdctl, PSC_REG_VAL_PDCTL_NEXT_OFF);
330   pdctl = PSC_REG_PDCTL_SET_PDMODE (pdctl, PSC_REG_VAL_PDCTL_PDMODE_SLEEP);
332   DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum), pdctl);
334   ptcmd = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PTCMD);
335   ptcmd |= (uint32)(1<<domainNum);
336   DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PTCMD, ptcmd);
339   /* Wait on the complete */
340   pscWait (domainNum);
341 #endif
343 //  return (0);