1 //*****************************************************************************
2 //
3 // prcm.c
4 //
5 // Driver for the Power, Reset and Clock Module (PRCM)
6 //
7 // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
8 //
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions
12 // are met:
13 //
14 // Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the
20 // distribution.
21 //
22 // Neither the name of Texas Instruments Incorporated nor the names of
23 // its contributors may be used to endorse or promote products derived
24 // from this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 //*****************************************************************************
39
40 //*****************************************************************************
41 //
42 //! \addtogroup PRCM_Power_Reset_Clock_Module_api
43 //! @{
44 //
45 //*****************************************************************************
46
47 #include "inc/hw_types.h"
48 #include "inc/hw_ints.h"
49 #include "inc/hw_memmap.h"
50 #include "inc/hw_apps_rcm.h"
51 #include "inc/hw_gprcm.h"
52 #include "inc/hw_hib1p2.h"
53 #include "inc/hw_hib3p3.h"
54 #include "prcm.h"
55 #include "interrupt.h"
56 #include "cpu.h"
57 #include "utils.h"
58 #include "rom_map.h"
59
60
61 //*****************************************************************************
62 // Macro definition
63 //*****************************************************************************
64 #define PRCM_SOFT_RESET 0x00000001
65 #define PRCM_ENABLE_STATUS 0x00000002
66 #define SYS_CLK 80000000
67 #define XTAL_CLK 40000000
68
69
70 //*****************************************************************************
71 // CC3200 does not have a true RTC capability. However, API(s) in this file
72 // provide an effective mechanism to support RTC feature in the device.
73 //
74 // The implementation to support RTC has been kept very simple. A set of
75 // HIB Memory Registers in conjunction with Slow Clock Counter are used
76 // to render RTC information to users. Core principle of design involves
77 // two steps (a) establish an association between user provided wall-clock
78 // and slow clock counter. (b) store reference value of this associattion
79 // in HIB Registers. This reference value and SCC value are then combined
80 // to create real-world calendar time.
81 //
82 // Across HIB cycles, value stored in HIB Registers is retained and slow
83 // clock counter continues to tick, thereby, this arragement is relevant
84 // and valid as long as device has a (tickle) battery power.
85 //
86 // Further, provision also has been made to set an alarm. When it RTC value
87 // matches that of set for alarm, an interrupt is generated.
88 //
89 // HIB MEM REG0 and REG1 are reserved for TI.
90 //
91 // If RTC feature is not used, then HIB REG2 & REG3 are available to user.
92 //
93 // Lower half of REG0 is used for TI HW ECO.
94 //*****************************************************************************
95 #define RTC_U64MSEC_MK(u32Secs, u16Msec) (((unsigned long long)u32Secs << 10)|\
96 (u16Msec & 0x3FF))
97
98 #define RTC_SECS_IN_U64MSEC(u64Msec) ((unsigned long)(u64Msec >> 10))
99 #define RTC_MSEC_IN_U64MSEC(u64Msec) ((unsigned short)(u64Msec & 0x3FF))
100
101 #define RTC_MSEC_U32_REG_ADDR (HIB3P3_BASE + HIB3P3_O_MEM_HIB_REG2)
102 #define RTC_SECS_U32_REG_ADDR (HIB3P3_BASE + HIB3P3_O_MEM_HIB_REG3)
103
104 //*****************************************************************************
105 // Register Access and Updates
106 //
107 // Tick of SCC has a resolution of 32768Hz, meaning 1 sec is equal to 32768
108 // clock ticks. Ideal way of getting time in millisecond will involve floating
109 // point arithmetic (division by 32.768). To avoid this, we simply divide it by
110 // 32, which will give a range from 0 -1023(instead of 0-999). To use this
111 // output correctly we have to take care of this inaccuracy externally.
112 // following wrapper can be used to convert the value from cycles to
113 // millisecond:
114 //
115 // CYCLES_U16MS(cycles) ((cycles * 1000) / 1024),
116 //
117 // Similarly, before setting the value, it must be first converted (from ms to
118 // cycles).
119 //
120 // U16MS_CYCLES(msec) ((msec * 1024) / 1000)
121 //
122 // Note: There is a precision loss of 1 ms with the above scheme.
123 //
124 //
125 #define SCC_U64MSEC_GET() (RTCFastDomainCounterGet() >> 5)
126 #define SCC_U64MSEC_MATCH_SET(u64Msec) (MAP_PRCMSlowClkCtrMatchSet(u64Msec << 5))
127 #define SCC_U64MSEC_MATCH_GET() (MAP_PRCMSlowClkCtrMatchGet() >> 5)
128
129 //*****************************************************************************
130 //
131 // Bit: 31 is used to indicate use of RTC. If set as '1', RTC feature is used.
132 // Bit: 30 is used to indicate that a safe boot should be performed.
133 // bit: 29 is used to indicate that the last reset was caused by the WDT.
134 // bit: 28 is used to indicate that the board is booting for the first time after being programmed in factory.
135 // Bits: 27 and 26 are unused.
136 // Bits: 25 to 16 are used to save millisecond part of RTC reference.
137 // Bits: 15 to 0 are being used for HW Changes / ECO.
138 //
139 //*****************************************************************************
140
141 //*****************************************************************************
142 // Set RTC USE Bit
143 //*****************************************************************************
RTCUseSet(void)144 static void RTCUseSet(void)
145 {
146 unsigned int uiRegValue;
147
148 uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) | (1 << 31);
149
150 PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue);
151 }
152
153 //*****************************************************************************
154 // Clear RTC USE Bit
155 //*****************************************************************************
RTCUseClear(void)156 static void RTCUseClear(void)
157 {
158 unsigned int uiRegValue;
159
160 uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (~(1 << 31));
161
162 PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue);
163 }
164
165 //*****************************************************************************
166 // Checks if RTC-USE bit is set
167 //*****************************************************************************
IsRTCUsed(void)168 static tBoolean IsRTCUsed(void)
169 {
170 return (MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (1 << 31)) ? true : false;
171 }
172
173 //*****************************************************************************
174 // Read 16-bit mSecs
175 //*****************************************************************************
RTCU32MSecRegRead(void)176 static unsigned short RTCU32MSecRegRead(void)
177 {
178 return ((MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) >> 16) & 0x03FF);
179 }
180
181 //*****************************************************************************
182 // Write 16-bit mSecs
183 //*****************************************************************************
RTCU32MSecRegWrite(unsigned int u32Msec)184 static void RTCU32MSecRegWrite(unsigned int u32Msec)
185 {
186 unsigned int uiRegValue;
187
188 // read the whole register and clear the msec bits
189 uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (~(0x03FF << 16));
190
191 // write the msec bits only
192 MAP_PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue | ((u32Msec & 0x03FF) << 16));
193 }
194
195 //*****************************************************************************
196 // Read 32-bit Secs
197 //*****************************************************************************
RTCU32SecRegRead(void)198 static unsigned long RTCU32SecRegRead(void)
199 {
200 return (MAP_PRCMHIBRegRead(RTC_SECS_U32_REG_ADDR));
201 }
202
203 //*****************************************************************************
204 // Write 32-bit Secs
205 //*****************************************************************************
RTCU32SecRegWrite(unsigned long u32Msec)206 static void RTCU32SecRegWrite(unsigned long u32Msec)
207 {
208 MAP_PRCMHIBRegWrite(RTC_SECS_U32_REG_ADDR, u32Msec);
209 }
210
211 //*****************************************************************************
212 // Fast function to get the most accurate RTC counter value
213 //*****************************************************************************
RTCFastDomainCounterGet(void)214 static unsigned long long RTCFastDomainCounterGet (void) {
215
216 #define BRK_IF_RTC_CTRS_ALIGN(c2, c1) if (c2 - c1 <= 1) { \
217 itr++; \
218 break; \
219 }
220
221 unsigned long long rtc_count1, rtc_count2, rtc_count3;
222 unsigned int itr;
223
224 do {
225 rtc_count1 = PRCMSlowClkCtrFastGet();
226 rtc_count2 = PRCMSlowClkCtrFastGet();
227 rtc_count3 = PRCMSlowClkCtrFastGet();
228 itr = 0;
229
230 BRK_IF_RTC_CTRS_ALIGN(rtc_count2, rtc_count1);
231 BRK_IF_RTC_CTRS_ALIGN(rtc_count3, rtc_count2);
232 BRK_IF_RTC_CTRS_ALIGN(rtc_count3, rtc_count1);
233
234 // Consistent values in two consecutive reads implies a correct
235 // value of the counter. Do note, the counter does not give the
236 // calendar time but a hardware that ticks upwards continuously.
237 // The 48-bit counter operates at 32,768 HZ.
238
239 } while (true);
240
241 return (1 == itr) ? rtc_count2 : rtc_count3;
242 }
243
244 //*****************************************************************************
245 // Macros
246 //*****************************************************************************
247 #define IS_RTC_USED() IsRTCUsed()
248 #define RTC_USE_SET() RTCUseSet()
249 #define RTC_USE_CLR() RTCUseClear()
250
251 #define RTC_U32MSEC_REG_RD() RTCU32MSecRegRead()
252 #define RTC_U32MSEC_REG_WR(u32Msec) RTCU32MSecRegWrite(u32Msec)
253
254 #define RTC_U32SECS_REG_RD() RTCU32SecRegRead()
255 #define RTC_U32SECS_REG_WR(u32Secs) RTCU32SecRegWrite(u32Secs)
256
257 #define SELECT_SCC_U42BITS(u64Msec) (u64Msec & 0x3ffffffffff)
258
259 //*****************************************************************************
260 // Global Peripheral clock and rest Registers
261 //*****************************************************************************
262 static const PRCM_PeriphRegs_t PRCM_PeriphRegsList[] =
263 {
264
265 {APPS_RCM_O_CAMERA_CLK_GATING, APPS_RCM_O_CAMERA_SOFT_RESET },
266 {APPS_RCM_O_MCASP_CLK_GATING, APPS_RCM_O_MCASP_SOFT_RESET },
267 {APPS_RCM_O_MMCHS_CLK_GATING, APPS_RCM_O_MMCHS_SOFT_RESET },
268 {APPS_RCM_O_MCSPI_A1_CLK_GATING, APPS_RCM_O_MCSPI_A1_SOFT_RESET },
269 {APPS_RCM_O_MCSPI_A2_CLK_GATING, APPS_RCM_O_MCSPI_A2_SOFT_RESET },
270 {APPS_RCM_O_UDMA_A_CLK_GATING, APPS_RCM_O_UDMA_A_SOFT_RESET },
271 {APPS_RCM_O_GPIO_A_CLK_GATING, APPS_RCM_O_GPIO_A_SOFT_RESET },
272 {APPS_RCM_O_GPIO_B_CLK_GATING, APPS_RCM_O_GPIO_B_SOFT_RESET },
273 {APPS_RCM_O_GPIO_C_CLK_GATING, APPS_RCM_O_GPIO_C_SOFT_RESET },
274 {APPS_RCM_O_GPIO_D_CLK_GATING, APPS_RCM_O_GPIO_D_SOFT_RESET },
275 {APPS_RCM_O_GPIO_E_CLK_GATING, APPS_RCM_O_GPIO_E_SOFT_RESET },
276 {APPS_RCM_O_WDOG_A_CLK_GATING, APPS_RCM_O_WDOG_A_SOFT_RESET },
277 {APPS_RCM_O_UART_A0_CLK_GATING, APPS_RCM_O_UART_A0_SOFT_RESET },
278 {APPS_RCM_O_UART_A1_CLK_GATING, APPS_RCM_O_UART_A1_SOFT_RESET },
279 {APPS_RCM_O_GPT_A0_CLK_GATING , APPS_RCM_O_GPT_A0_SOFT_RESET },
280 {APPS_RCM_O_GPT_A1_CLK_GATING, APPS_RCM_O_GPT_A1_SOFT_RESET },
281 {APPS_RCM_O_GPT_A2_CLK_GATING, APPS_RCM_O_GPT_A2_SOFT_RESET },
282 {APPS_RCM_O_GPT_A3_CLK_GATING, APPS_RCM_O_GPT_A3_SOFT_RESET },
283 {APPS_RCM_O_CRYPTO_CLK_GATING, APPS_RCM_O_CRYPTO_SOFT_RESET },
284 {APPS_RCM_O_MCSPI_S0_CLK_GATING, APPS_RCM_O_MCSPI_S0_SOFT_RESET },
285 {APPS_RCM_O_I2C_CLK_GATING, APPS_RCM_O_I2C_SOFT_RESET }
286
287 };
288
289 //*****************************************************************************
290 //
291 //! Set a special bit
292 //!
293 //! \return None.
294 //
295 //*****************************************************************************
PRCMSetSpecialBit(unsigned char bit)296 void PRCMSetSpecialBit(unsigned char bit)
297 {
298 unsigned int uiRegValue;
299
300 uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) | (1 << bit);
301
302 PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue);
303 }
304
305 //*****************************************************************************
306 //
307 //! Clear a special bit
308 //!
309 //! \return None.
310 //
311 //*****************************************************************************
PRCMClearSpecialBit(unsigned char bit)312 void PRCMClearSpecialBit(unsigned char bit)
313 {
314 unsigned int uiRegValue;
315
316 uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (~(1 << bit));
317
318 PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue);
319 }
320
321 //*****************************************************************************
322 //
323 //! Read a special bit
324 //!
325 //! \return Value of the bit
326 //
327 //*****************************************************************************
PRCMGetSpecialBit(unsigned char bit)328 tBoolean PRCMGetSpecialBit(unsigned char bit)
329 {
330 tBoolean value = (MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (1 << bit)) ? true : false;
331 // special bits must be cleared immediatelly after reading
332 PRCMClearSpecialBit(bit);
333 return value;
334 }
335
336 //*****************************************************************************
337 //
338 //! Performs a software reset of a SOC
339 //!
340 //! This function performs a software reset of a SOC
341 //!
342 //! \return None.
343 //
344 //*****************************************************************************
PRCMSOCReset(void)345 void PRCMSOCReset(void)
346 {
347 //
348 // Reset MCU
349 //
350 HWREG(GPRCM_BASE+ GPRCM_O_MCU_GLOBAL_SOFT_RESET) |= 0x1;
351
352 }
353
354 //*****************************************************************************
355 //
356 //! Performs a software reset of a MCU and associated peripherals
357 //!
358 //! \param bIncludeSubsystem is \b true to reset associated peripherals.
359 //!
360 //! This function performs a software reset of a MCU and associated peripherals.
361 //! To reset the associated peripheral, the parameter \e bIncludeSubsystem
362 //! should be set to \b true.
363 //!
364 //! \return None.
365 //
366 //*****************************************************************************
PRCMMCUReset(tBoolean bIncludeSubsystem)367 void PRCMMCUReset(tBoolean bIncludeSubsystem)
368 {
369 if(bIncludeSubsystem)
370 {
371 //
372 // Reset Apps processor and associated peripheral
373 //
374 HWREG(GPRCM_BASE+ GPRCM_O_APPS_SOFT_RESET) = 0x2;
375 }
376 else
377 {
378 //
379 // Reset Apps processor only
380 //
381 HWREG(GPRCM_BASE+ GPRCM_O_APPS_SOFT_RESET) = 0x1;
382 }
383 }
384
385 //*****************************************************************************
386 //
387 //! Gets the reason for a reset.
388 //!
389 //! This function returns the reason(s) for a reset. The reset reason are:-
390 //! -\b PRCM_POWER_ON - Device is powering up.
391 //! -\b PRCM_LPDS_EXIT - Device is exiting from LPDS.
392 //! -\b PRCM_CORE_RESET - Device is exiting soft core only reset
393 //! -\b PRCM_MCU_RESET - Device is exiting soft subsystem reset.
394 //! -\b PRCM_WDT_RESET - Device was reset by watchdog.
395 //! -\b PRCM_SOC_RESET - Device is exting SOC reset.
396 //! -\b PRCM_HIB_EXIT - Device is exiting hibernate.
397 //!
398 //! \return Returns one of the cause defined above.
399 //
400 //*****************************************************************************
PRCMSysResetCauseGet(void)401 unsigned long PRCMSysResetCauseGet(void)
402 {
403 unsigned long ulWakeupStatus;
404
405 //
406 // Read the Reset status
407 //
408 ulWakeupStatus = (HWREG(GPRCM_BASE+ GPRCM_O_APPS_RESET_CAUSE) & 0xFF);
409
410 //
411 // For hibernate do additional chaeck.
412 //
413 if(ulWakeupStatus == PRCM_POWER_ON)
414 {
415 if(MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_WAKE_STATUS) & 0x1)
416 {
417 ulWakeupStatus = PRCM_HIB_EXIT;
418 }
419 }
420
421 //
422 // Return status.
423 //
424 return ulWakeupStatus;
425 }
426
427 //*****************************************************************************
428 //
429 //! Enable clock(s) to peripheral.
430 //!
431 //! \param ulPeripheral is one of the valid peripherals
432 //! \param ulClkFlags are bitmask of clock(s) to be enabled.
433 //!
434 //! This function enables the clock for the specified peripheral. Peripherals
435 //! are by default clock gated (disabled) and generates a bus fault if
436 //! accessed.
437 //!
438 //! The parameter \e ulClkFlags can be logical OR of the following:
439 //! -\b PRCM_RUN_MODE_CLK - Ungates clock to the peripheral
440 //! -\b PRCM_SLP_MODE_CLK - Keeps the clocks ungated in sleep.
441 //! -\b PRCM_DSLP_MODE_CLK - Keeps the clock ungated in deepsleep.
442 //!
443 //! \return None.
444 //
445 //*****************************************************************************
PRCMPeripheralClkEnable(unsigned long ulPeripheral,unsigned long ulClkFlags)446 void PRCMPeripheralClkEnable(unsigned long ulPeripheral, unsigned long ulClkFlags)
447 {
448 //
449 // Enable the specified peripheral clocks, Nothing to be done for PRCM_ADC
450 // as it is a dummy define for pinmux utility code generation
451 //
452 if(ulPeripheral != PRCM_ADC)
453 {
454 HWREG(ARCM_BASE + PRCM_PeriphRegsList[ulPeripheral].ulClkReg) |= ulClkFlags;
455 }
456 //
457 // Set the default clock for camera
458 //
459 if(ulPeripheral == PRCM_CAMERA)
460 {
461 HWREG(ARCM_BASE + APPS_RCM_O_CAMERA_CLK_GEN) = 0x0404;
462 }
463 }
464
465 //*****************************************************************************
466 //
467 //! Disables clock(s) to peripheral.
468 //!
469 //! \param ulPeripheral is one of the valid peripherals
470 //! \param ulClkFlags are bitmask of clock(s) to be enabled.
471 //!
472 //! This function disable the clock for the specified peripheral. Peripherals
473 //! are by default clock gated (disabled) and generated a bus fault if
474 //! accessed.
475 //!
476 //! The parameter \e ulClkFlags can be logical OR bit fields as defined in
477 //! PRCMEnablePeripheral().
478 //!
479 //! \return None.
480 //
481 //*****************************************************************************
PRCMPeripheralClkDisable(unsigned long ulPeripheral,unsigned long ulClkFlags)482 void PRCMPeripheralClkDisable(unsigned long ulPeripheral, unsigned long ulClkFlags)
483 {
484 //
485 // Disable the specified peripheral clocks
486 //
487 HWREG(ARCM_BASE + PRCM_PeriphRegsList[ulPeripheral].ulClkReg) &= ~ulClkFlags;
488 }
489
490 //*****************************************************************************
491 //
492 //! Gets the input clock for the specified peripheral.
493 //!
494 //! \param ulPeripheral is one of the valid peripherals.
495 //!
496 //! This function gets the input clock for the specified peripheral.
497 //!
498 //! The parameter \e ulPeripheral has the same definition as that in
499 //! PRCMPeripheralClkEnable();
500 //!
501 //! \return Returns input clock frequency for specified peripheral.
502 //
503 //*****************************************************************************
PRCMPeripheralClockGet(unsigned long ulPeripheral)504 unsigned long PRCMPeripheralClockGet(unsigned long ulPeripheral)
505 {
506 unsigned long ulClockFreq;
507 unsigned long ulHiPulseDiv;
508 unsigned long ulLoPulseDiv;
509
510 //
511 // Get the clock based on specified peripheral.
512 //
513 if(((ulPeripheral == PRCM_SSPI) | (ulPeripheral == PRCM_LSPI)
514 | (ulPeripheral == PRCM_GSPI)))
515 {
516 return XTAL_CLK;
517 }
518 else if(ulPeripheral == PRCM_CAMERA)
519 {
520 ulHiPulseDiv = ((HWREG(ARCM_BASE + APPS_RCM_O_CAMERA_CLK_GEN) >> 8) & 0x07);
521 ulLoPulseDiv = (HWREG(ARCM_BASE + APPS_RCM_O_CAMERA_CLK_GEN)& 0xFF);
522 }
523 else if(ulPeripheral == PRCM_SDHOST)
524 {
525 ulHiPulseDiv = ((HWREG(ARCM_BASE + APPS_RCM_O_MMCHS_CLK_GEN) >> 8) & 0x07);
526 ulLoPulseDiv = (HWREG(ARCM_BASE + APPS_RCM_O_MMCHS_CLK_GEN)& 0xFF);
527 }
528 else
529 {
530 return SYS_CLK;
531 }
532
533 //
534 // Compute the clock freq. from the divider value
535 //
536 ulClockFreq = (240000000/((ulHiPulseDiv + 1) + (ulLoPulseDiv + 1)));
537
538 //
539 // Return the clock rate.
540 //
541 return ulClockFreq;
542 }
543
544 //*****************************************************************************
545 //
546 //! Performs a software reset of a peripheral.
547 //!
548 //! \param ulPeripheral is one of the valid peripheral.
549 //!
550 //! This assert or deassert reset to the specified peripheral based of the
551 //! \e bAssert parameter.
552 //!
553 //! \return None.
554 //
555 //*****************************************************************************
PRCMPeripheralReset(unsigned long ulPeripheral)556 void PRCMPeripheralReset(unsigned long ulPeripheral)
557 {
558 volatile unsigned long ulDelay;
559
560 if( ulPeripheral != PRCM_DTHE)
561 {
562 //
563 // Assert the reset
564 //
565 HWREG(ARCM_BASE + PRCM_PeriphRegsList[ulPeripheral].ulRstReg)
566 |= PRCM_SOFT_RESET;
567 //
568 // Delay for a little bit.
569 //
570 for(ulDelay = 0; ulDelay < 16; ulDelay++)
571 {
572 }
573
574 //
575 // Deassert the reset
576 //
577 HWREG(ARCM_BASE+PRCM_PeriphRegsList[ulPeripheral].ulRstReg)
578 &= ~PRCM_SOFT_RESET;
579 }
580 }
581
582 //*****************************************************************************
583 //
584 //! Determines if a peripheral is ready.
585 //!
586 //! \param ulPeripheral is one of the valid modules
587 //!
588 //! This function determines if a particular peripheral is ready to be
589 //! accessed. The peripheral may be in a non-ready state if it is not enabled,
590 //! is being held in reset, or is in the process of becoming ready after being
591 //! enabled or taken out of reset.
592 //!
593 //! \return Returns \b true if the peripheral is ready, \b false otherwise.
594 //
595 //*****************************************************************************
PRCMPeripheralStatusGet(unsigned long ulPeripheral)596 tBoolean PRCMPeripheralStatusGet(unsigned long ulPeripheral)
597 {
598 unsigned long ReadyBit;
599
600 //
601 // Read the ready bit status
602 //
603 ReadyBit = HWREG(ARCM_BASE + PRCM_PeriphRegsList[ulPeripheral].ulRstReg);
604 ReadyBit = ReadyBit & PRCM_ENABLE_STATUS;
605
606 if (ReadyBit)
607 {
608 //
609 // Module is ready
610 //
611 return(true);
612 }
613 else
614 {
615 //
616 // Module is not ready
617 //
618 return(false);
619 }
620 }
621
622 //*****************************************************************************
623 //
624 //! Configure I2S fracactional divider
625 //!
626 //! \param ulI2CClkFreq is the required input clock for McAPS module
627 //!
628 //! This function configures I2S fractional divider. By default this
629 //! divider is set to output 24 Mhz clock to I2S module.
630 //!
631 //! The minimum frequency that can be obtained by configuring this divider is
632 //!
633 //! (240000KHz/1023.99) = 234.377 KHz
634 //!
635 //! \return None.
636 //
637 //*****************************************************************************
PRCMI2SClockFreqSet(unsigned long ulI2CClkFreq)638 void PRCMI2SClockFreqSet(unsigned long ulI2CClkFreq)
639 {
640 unsigned long long ullDiv;
641 unsigned short usInteger;
642 unsigned short usFrac;
643
644 ullDiv = (((unsigned long long)240000000 * 65536)/ulI2CClkFreq);
645
646 usInteger = (ullDiv/65536);
647 usFrac = (ullDiv%65536);
648
649 HWREG(ARCM_BASE + APPS_RCM_O_MCASP_FRAC_CLK_CONFIG0) =
650 ((usInteger & 0x3FF) << 16 | usFrac);
651 }
652
653 //*****************************************************************************
654 //
655 //! Sets the LPDS exit PC and SP restore vlaues.
656 //!
657 //! \param ulStackPtr is the SP restore value.
658 //! \param ulProgCntr is the PC restore value
659 //!
660 //! This function sets the LPDS exit PC and SP restore vlaues. Setting
661 //! \e ulProgCntr to a non-zero value, forces bootloader to jump to that
662 //! address with Stack Pointer initialized to \e ulStackPtr on LPDS exit,
663 //! otherwise the application's vector table entries are used.
664 //!
665 //! \return None.
666 //
667 //*****************************************************************************
PRCMLPDSRestoreInfoSet(unsigned long ulStackPtr,unsigned long ulProgCntr)668 void PRCMLPDSRestoreInfoSet(unsigned long ulStackPtr, unsigned long ulProgCntr)
669 {
670 //
671 // Set The SP Value
672 //
673 HWREG(0x4402E18C) = ulStackPtr;
674
675 //
676 // Set The PC Value
677 //
678 HWREG(0x4402E190) = ulProgCntr;
679 }
680
681 //*****************************************************************************
682 //
683 //! Puts the system into Low Power Deel Sleep (LPDS) power mode.
684 //!
685 //! This function puts the system into Low Power Deel Sleep (LPDS) power mode.
686 //! A call to this function never returns and the execution starts from Reset.
687 //! \sa PRCMLPDSRestoreInfoSet().
688 //!
689 //! \return None.
690 //!
691 //! \note The Test Power Domain is shutdown whenever the system
692 //! enters LPDS (by default). In order to avoid this and allow for
693 //! connecting back the debugger after waking up from LPDS,
694 //! the macro KEEP_TESTPD_ALIVE has to be defined while building the library.
695 //! This is recommended for development purposes only as it adds to
696 //! the current consumption of the system.
697 //!
698 //
699 //*****************************************************************************
PRCMLPDSEnter(void)700 void PRCMLPDSEnter(void)
701 {
702 #ifndef DEBUG
703 //
704 // Disable TestPD
705 //
706 HWREG(0x4402E168) |= (1<<9);
707 #endif
708
709 //
710 // Set bandgap duty cycle to 1
711 //
712 HWREG(HIB1P2_BASE + HIB1P2_O_BGAP_DUTY_CYCLING_EXIT_CFG) = 0x1;
713
714 //
715 // Request LPDS
716 //
717 HWREG(ARCM_BASE + APPS_RCM_O_APPS_LPDS_REQ) = APPS_RCM_APPS_LPDS_REQ_APPS_LPDS_REQ;
718
719 __asm(" nop\n"
720 " nop\n"
721 " nop\n"
722 " nop\n");
723 }
724
725 //*****************************************************************************
726 //
727 //! Enable the individual LPDS wakeup source(s).
728 //!
729 //! \param ulLpdsWakeupSrc is logical OR of wakeup sources.
730 //!
731 //! This function enable the individual LPDS wakeup source(s) and following
732 //! three wakeup sources (\e ulLpdsWakeupSrc ) are supported by the device.
733 //! -\b PRCM_LPDS_HOST_IRQ
734 //! -\b PRCM_LPDS_GPIO
735 //! -\b PRCM_LPDS_TIMER
736 //!
737 //! \return None.
738 //
739 //*****************************************************************************
PRCMLPDSWakeupSourceEnable(unsigned long ulLpdsWakeupSrc)740 void PRCMLPDSWakeupSourceEnable(unsigned long ulLpdsWakeupSrc)
741 {
742 unsigned long ulRegVal;
743
744 //
745 // Read the current wakup sources
746 //
747 ulRegVal = HWREG(GPRCM_BASE+ GPRCM_O_APPS_LPDS_WAKEUP_CFG);
748
749 //
750 // Enable individual wakeup source
751 //
752 ulRegVal = ((ulRegVal | ulLpdsWakeupSrc) & 0x91);
753
754 //
755 // Set the configuration in the register
756 //
757 HWREG(GPRCM_BASE+ GPRCM_O_APPS_LPDS_WAKEUP_CFG) = ulRegVal;
758 }
759
760 //*****************************************************************************
761 //
762 //! Disable the individual LPDS wakeup source(s).
763 //!
764 //! \param ulLpdsWakeupSrc is logical OR of wakeup sources.
765 //!
766 //! This function enable the individual LPDS wakeup source(s) and following
767 //! three wake up sources (\e ulLpdsWakeupSrc ) are supported by the device.
768 //! -\b PRCM_LPDS_HOST_IRQ
769 //! -\b PRCM_LPDS_GPIO
770 //! -\b PRCM_LPDS_TIMER
771 //!
772 //! \return None.
773 //
774 //*****************************************************************************
PRCMLPDSWakeupSourceDisable(unsigned long ulLpdsWakeupSrc)775 void PRCMLPDSWakeupSourceDisable(unsigned long ulLpdsWakeupSrc)
776 {
777 HWREG(GPRCM_BASE+ GPRCM_O_APPS_LPDS_WAKEUP_CFG) &= ~ulLpdsWakeupSrc;
778 }
779
780
781 //*****************************************************************************
782 //
783 //! Get LPDS wakeup cause
784 //!
785 //! This function gets LPDS wakeup caouse
786 //!
787 //! \return Returns values enumerated as described in
788 //! PRCMLPDSWakeupSourceEnable().
789 //
790 //*****************************************************************************
PRCMLPDSWakeupCauseGet(void)791 unsigned long PRCMLPDSWakeupCauseGet(void)
792 {
793 return (HWREG(GPRCM_BASE+ GPRCM_O_APPS_LPDS_WAKEUP_SRC));
794 }
795
796 //*****************************************************************************
797 //
798 //! Sets LPDS wakeup Timer
799 //!
800 //! \param ulTicks is number of 32.768 KHz clocks
801 //!
802 //! This function sets internal LPDS wakeup timer running at 32.768 KHz. The
803 //! timer is only configured if the parameter \e ulTicks is in valid range i.e.
804 //! from 21 to 2^32.
805 //!
806 //! \return Returns \b true on success, \b false otherwise.
807 //
808 //*****************************************************************************
PRCMLPDSIntervalSet(unsigned long ulTicks)809 void PRCMLPDSIntervalSet(unsigned long ulTicks)
810 {
811 //
812 // Check sleep is atleast for 21 cycles
813 // If not set the sleep time to 21 cycles
814 //
815 if( ulTicks < 21)
816 {
817 ulTicks = 21;
818 }
819
820 HWREG(GPRCM_BASE + GPRCM_O_APPS_LPDS_WAKETIME_WAKE_CFG) = ulTicks;
821 HWREG(GPRCM_BASE + GPRCM_O_APPS_LPDS_WAKETIME_OPP_CFG) = ulTicks-20;
822 }
823
824 //*****************************************************************************
825 //
826 //! Selects the GPIO for LPDS wakeup
827 //!
828 //! \param ulGPIOPin is one of the valid GPIO fro LPDS wakeup.
829 //! \param ulType is the wakeup trigger type.
830 //!
831 //! This function setects the wakeup GPIO for LPDS wakeup and can be
832 //! used to select one out of 7 pre-defined GPIO(s).
833 //!
834 //! The parameter \e ulLpdsGPIOSel should be one of the following:-
835 //! -\b PRCM_LPDS_GPIO2
836 //! -\b PRCM_LPDS_GPIO4
837 //! -\b PRCM_LPDS_GPIO13
838 //! -\b PRCM_LPDS_GPIO17
839 //! -\b PRCM_LPDS_GPIO11
840 //! -\b PRCM_LPDS_GPIO24
841 //! -\b PRCM_LPDS_GPIO26
842 //!
843 //! The parameter \e ulType sets the trigger type and can be one of the
844 //! following:
845 //! - \b PRCM_LPDS_LOW_LEVEL
846 //! - \b PRCM_LPDS_HIGH_LEVEL
847 //! - \b PRCM_LPDS_FALL_EDGE
848 //! - \b PRCM_LPDS_RISE_EDGE
849 //!
850 //! \return None.
851 //
852 //*****************************************************************************
PRCMLPDSWakeUpGPIOSelect(unsigned long ulGPIOPin,unsigned long ulType)853 void PRCMLPDSWakeUpGPIOSelect(unsigned long ulGPIOPin, unsigned long ulType)
854 {
855 //
856 // Set the wakeup GPIO
857 //
858 MAP_PRCMHIBRegWrite(HIB3P3_BASE + HIB3P3_O_MEM_HIB_LPDS_GPIO_SEL, ulGPIOPin);
859
860 //
861 // Set the trigger type.
862 //
863 HWREG(GPRCM_BASE + GPRCM_O_APPS_GPIO_WAKE_CONF) = (ulType & 0x3);
864 }
865
866 //*****************************************************************************
867 //
868 //! Puts the system into Sleep.
869 //!
870 //! This function puts the system into sleep power mode. System exits the power
871 //! state on any one of the available interrupt. On exit from sleep mode the
872 //! function returns to the calling function with all the processor core
873 //! registers retained.
874 //!
875 //! \return None.
876 //
877 //*****************************************************************************
PRCMSleepEnter(void)878 void PRCMSleepEnter(void)
879 {
880 //
881 // Request Sleep
882 //
883 CPUwfi();
884 }
885
886 //*****************************************************************************
887 //
888 //! Puts the system into Deep Sleep power mode.
889 //!
890 //! This function puts the system into Deep Sleep power mode. System exits the
891 //! power state on any one of the available interrupt. On exit from deep
892 //! sleep the function returns to the calling function with all the processor
893 //! core registers retained.
894 //!
895 //! \return None.
896 //
897 //*****************************************************************************
PRCMDeepSleepEnter(void)898 void PRCMDeepSleepEnter(void)
899 {
900 //
901 // Set bandgap duty cycle to 1
902 //
903 HWREG(HIB1P2_BASE + HIB1P2_O_BGAP_DUTY_CYCLING_EXIT_CFG) = 0x1;
904
905 //
906 // Enable DSLP in cortex
907 //
908 HWREG(0xE000ED10)|=1<<2;
909
910 //
911 // Request Deep Sleep
912 //
913 CPUwfi();
914
915 //
916 // Disable DSLP in cortex before
917 // returning to the caller
918 //
919 HWREG(0xE000ED10) &= ~(1<<2);
920
921 }
922
923 //*****************************************************************************
924 //
925 //! Enable SRAM column retention during Deep Sleep and/or LPDS Power mode(s)
926 //!
927 //! \param ulSramColSel is bit mask of valid SRAM columns.
928 //! \param ulModeFlags is the bit mask of power modes.
929 //!
930 //! This functions enables the SRAM retention. The device supports configurable
931 //! SRAM column retention in Low Power Deep Sleep (LPDS) and Deep Sleep power
932 //! modes. Each column is of 64 KB size.
933 //!
934 //! The parameter \e ulSramColSel should be logical OR of the following:-
935 //! -\b PRCM_SRAM_COL_1
936 //! -\b PRCM_SRAM_COL_2
937 //! -\b PRCM_SRAM_COL_3
938 //! -\b PRCM_SRAM_COL_4
939 //!
940 //! The parameter \e ulModeFlags selects the power modes and sholud be logical
941 //! OR of one or more of the following
942 //! -\b PRCM_SRAM_DSLP_RET
943 //! -\b PRCM_SRAM_LPDS_RET
944 //!
945 //! \return None.
946 //
947 //****************************************************************************
PRCMSRAMRetentionEnable(unsigned long ulSramColSel,unsigned long ulModeFlags)948 void PRCMSRAMRetentionEnable(unsigned long ulSramColSel, unsigned long ulModeFlags)
949 {
950 if(ulModeFlags & PRCM_SRAM_DSLP_RET)
951 {
952 //
953 // Configure deep sleep SRAM retention register
954 //
955 HWREG(GPRCM_BASE+ GPRCM_O_APPS_SRAM_DSLP_CFG) = (ulSramColSel & 0xF);
956 }
957
958 if(ulModeFlags & PRCM_SRAM_LPDS_RET)
959 {
960 //
961 // Configure LPDS SRAM retention register
962 //
963 HWREG(GPRCM_BASE+ GPRCM_O_APPS_SRAM_LPDS_CFG) = (ulSramColSel & 0xF);
964 }
965 }
966
967 //*****************************************************************************
968 //
969 //! Disable SRAM column retention during Deep Sleep and/or LPDS Power mode(s).
970 //!
971 //! \param ulSramColSel is bit mask of valid SRAM columns.
972 //! \param ulFlags is the bit mask of power modes.
973 //!
974 //! This functions disable the SRAM retention. The device supports configurable
975 //! SRAM column retention in Low Power Deep Sleep (LPDS) and Deep Sleep power
976 //! modes. Each column is of 64 KB size.
977 //!
978 //! The parameter \e ulSramColSel should be logical OR of the following:-
979 //! -\b PRCM_SRAM_COL_1
980 //! -\b PRCM_SRAM_COL_2
981 //! -\b PRCM_SRAM_COL_3
982 //! -\b PRCM_SRAM_COL_4
983 //!
984 //! The parameter \e ulFlags selects the power modes and sholud be logical OR
985 //! of one or more of the following
986 //! -\b PRCM_SRAM_DSLP_RET
987 //! -\b PRCM_SRAM_LPDS_RET
988 //!
989 //! \return None.
990 //
991 //****************************************************************************
PRCMSRAMRetentionDisable(unsigned long ulSramColSel,unsigned long ulFlags)992 void PRCMSRAMRetentionDisable(unsigned long ulSramColSel, unsigned long ulFlags)
993 {
994 if(ulFlags & PRCM_SRAM_DSLP_RET)
995 {
996 //
997 // Configure deep sleep SRAM retention register
998 //
999 HWREG(GPRCM_BASE+ GPRCM_O_APPS_SRAM_DSLP_CFG) &= ~(ulSramColSel & 0xF);
1000 }
1001
1002 if(ulFlags & PRCM_SRAM_LPDS_RET)
1003 {
1004 //
1005 // Configure LPDS SRAM retention register
1006 //
1007 HWREG(GPRCM_BASE+ GPRCM_O_APPS_SRAM_LPDS_CFG) &= ~(ulSramColSel & 0xF);
1008 }
1009 }
1010
1011
1012 //*****************************************************************************
1013 //
1014 //! Enables individual HIB wakeup source(s).
1015 //!
1016 //! \param ulHIBWakupSrc is logical OR of valid HIB wakeup sources.
1017 //!
1018 //! This function enables individual HIB wakeup source(s). The paramter
1019 //! \e ulHIBWakupSrc is the bit mask of HIB wakeup sources and should be
1020 //! logical OR of one or more of the follwoing :-
1021 //! -\b PRCM_HIB_SLOW_CLK_CTR
1022 //! -\b PRCM_HIB_GPIO2
1023 //! -\b PRCM_HIB_GPIO4
1024 //! -\b PRCM_HIB_GPIO13
1025 //! -\b PRCM_HIB_GPIO17
1026 //! -\b PRCM_HIB_GPIO11
1027 //! -\b PRCM_HIB_GPIO24
1028 //! -\b PRCM_HIB_GPIO26
1029 //!
1030 //! \return None.
1031 //
1032 //*****************************************************************************
PRCMHibernateWakeupSourceEnable(unsigned long ulHIBWakupSrc)1033 void PRCMHibernateWakeupSourceEnable(unsigned long ulHIBWakupSrc)
1034 {
1035 unsigned long ulRegValue;
1036
1037 //
1038 // Read the RTC register
1039 //
1040 ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_EN);
1041
1042 //
1043 // Enable the RTC as wakeup source if specified
1044 //
1045 ulRegValue |= (ulHIBWakupSrc & 0x1);
1046
1047 //
1048 // Enable HIB wakeup sources
1049 //
1050 MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_EN,ulRegValue);
1051
1052 //
1053 // REad the GPIO wakeup configuration register
1054 //
1055 ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_GPIO_WAKE_EN);
1056
1057 //
1058 // Enable the specified GPIOs a wakeup sources
1059 //
1060 ulRegValue |= ((ulHIBWakupSrc>>16)&0xFF);
1061
1062 //
1063 // Write the new register configuration
1064 //
1065 MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_GPIO_WAKE_EN,ulRegValue);
1066 }
1067
1068 //*****************************************************************************
1069 //
1070 //! Disable individual HIB wakeup source(s).
1071 //!
1072 //! \param ulHIBWakupSrc is logical OR of valid HIB wakeup sources.
1073 //!
1074 //! This function disable individual HIB wakeup source(s). The paramter
1075 //! \e ulHIBWakupSrc is same as bit fileds defined in
1076 //! PRCMEnableHibernateWakeupSource()
1077 //!
1078 //! \return None.
1079 //
1080 //*****************************************************************************
PRCMHibernateWakeupSourceDisable(unsigned long ulHIBWakupSrc)1081 void PRCMHibernateWakeupSourceDisable(unsigned long ulHIBWakupSrc)
1082 {
1083 unsigned long ulRegValue;
1084
1085 //
1086 // Read the RTC register
1087 //
1088 ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_EN);
1089
1090 //
1091 // Disable the RTC as wakeup source if specified
1092 //
1093 ulRegValue &= ~(ulHIBWakupSrc & 0x1);
1094
1095 //
1096 // Disable HIB wakeup sources
1097 //
1098 MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_EN,ulRegValue);
1099
1100 //
1101 // Read the GPIO wakeup configuration register
1102 //
1103 ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_GPIO_WAKE_EN);
1104
1105 //
1106 // Enable the specified GPIOs a wakeup sources
1107 //
1108 ulRegValue &= ~((ulHIBWakupSrc>>16)&0xFF);
1109
1110 //
1111 // Write the new register configuration
1112 //
1113 MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_GPIO_WAKE_EN,ulRegValue);
1114 }
1115
1116
1117 //*****************************************************************************
1118 //
1119 //! Get hibernate wakeup cause
1120 //!
1121 //! This function gets the hibernate wakeup cause.
1122 //!
1123 //! \return Returns \b PRCM_HIB_WAKEUP_CAUSE_SLOW_CLOCK or
1124 //! \b PRCM_HIB_WAKEUP_CAUSE_GPIO
1125 //
1126 //*****************************************************************************
PRCMHibernateWakeupCauseGet(void)1127 unsigned long PRCMHibernateWakeupCauseGet(void)
1128 {
1129 return ((MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_WAKE_STATUS)>>1)&0xF);
1130 }
1131
1132 //*****************************************************************************
1133 //
1134 //! Sets Hibernate wakeup Timer
1135 //!
1136 //! \param ullTicks is number of 32.768 KHz clocks
1137 //!
1138 //! This function sets internal hibernate wakeup timer running at 32.768 KHz.
1139 //!
1140 //! \return Returns \b true on success, \b false otherwise.
1141 //
1142 //*****************************************************************************
PRCMHibernateIntervalSet(unsigned long long ullTicks)1143 void PRCMHibernateIntervalSet(unsigned long long ullTicks)
1144 {
1145 unsigned long long ullRTCVal;
1146
1147 //
1148 // Latch the RTC vlaue
1149 //
1150 MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_TIMER_READ ,0x1);
1151
1152 //
1153 // Read latched values as 2 32-bit vlaues
1154 //
1155 ullRTCVal = MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_TIMER_MSW);
1156 ullRTCVal = ullRTCVal << 32;
1157 ullRTCVal |= MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_TIMER_LSW);
1158
1159 //
1160 // Add the interval
1161 //
1162 ullRTCVal = ullRTCVal + ullTicks;
1163
1164 //
1165 // Set RTC match value
1166 //
1167 MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_LSW_CONF,
1168 (unsigned long)(ullRTCVal));
1169 MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_MSW_CONF,
1170 (unsigned long)(ullRTCVal>>32));
1171 }
1172
1173
1174 //*****************************************************************************
1175 //
1176 //! Selects the GPIO(s) for hibernate wakeup
1177 //!
1178 //! \param ulGPIOBitMap is the bit-map of valid hibernate wakeup GPIO.
1179 //! \param ulType is the wakeup trigger type.
1180 //!
1181 //! This function setects the wakeup GPIO for hibernate and can be
1182 //! used to select any combination of 7 pre-defined GPIO(s).
1183 //!
1184 //! This function enables individual HIB wakeup source(s). The paramter
1185 //! \e ulGPIOBitMap should be one of the follwoing :-
1186 //! -\b PRCM_HIB_GPIO2
1187 //! -\b PRCM_HIB_GPIO4
1188 //! -\b PRCM_HIB_GPIO13
1189 //! -\b PRCM_HIB_GPIO17
1190 //! -\b PRCM_HIB_GPIO11
1191 //! -\b PRCM_HIB_GPIO24
1192 //! -\b PRCM_HIB_GPIO26
1193 //!
1194 //! The parameter \e ulType sets the trigger type and can be one of the
1195 //! following:
1196 //! - \b PRCM_HIB_LOW_LEVEL
1197 //! - \b PRCM_HIB_HIGH_LEVEL
1198 //! - \b PRCM_HIB_FALL_EDGE
1199 //! - \b PRCM_HIB_RISE_EDGE
1200 //!
1201 //! \return None.
1202 //
1203 //*****************************************************************************
PRCMHibernateWakeUpGPIOSelect(unsigned long ulGPIOBitMap,unsigned long ulType)1204 void PRCMHibernateWakeUpGPIOSelect(unsigned long ulGPIOBitMap, unsigned long ulType)
1205 {
1206 unsigned char ucLoop;
1207 unsigned long ulRegValue;
1208
1209 //
1210 // Shift the bits to extract the GPIO selection
1211 //
1212 ulGPIOBitMap >>= 16;
1213
1214 //
1215 // Set the configuration for each GPIO
1216 //
1217 for(ucLoop=0; ucLoop < 7; ucLoop++)
1218 {
1219 if(ulGPIOBitMap & (1<<ucLoop))
1220 {
1221 ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_GPIO_WAKE_CONF);
1222 ulRegValue |= (ulType << (ucLoop*2));
1223 MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_GPIO_WAKE_CONF, ulRegValue);
1224 }
1225 }
1226 }
1227
1228 //*****************************************************************************
1229 //
1230 //! Puts the system into Hibernate
1231 //!
1232 //! This function puts the system into Hibernate. The device enters HIB
1233 //! immediately and on exit from HIB device core starts its execution from
1234 //! reset thus the function never returns.
1235 //!
1236 //! \return None.
1237 //
1238 //*****************************************************************************
PRCMHibernateEnter(void)1239 void PRCMHibernateEnter(void)
1240 {
1241
1242 //
1243 // Request hibernate.
1244 //
1245 MAP_PRCMHIBRegWrite((HIB3P3_BASE+HIB3P3_O_MEM_HIB_REQ),0x1);
1246
1247 __asm(" nop\n"
1248 " nop\n"
1249 " nop\n"
1250 " nop\n");
1251 }
1252
1253 //*****************************************************************************
1254 //
1255 //! Gets the current value of the internal slow clock counter
1256 //!
1257 //! This function latches and reads the internal RTC running at 32.768 Khz
1258 //!
1259 //! \return 64-bit current counter vlaue.
1260 //
1261 //*****************************************************************************
PRCMSlowClkCtrGet(void)1262 unsigned long long PRCMSlowClkCtrGet(void)
1263 {
1264 unsigned long long ullRTCVal;
1265
1266 //
1267 // Latch the RTC vlaue
1268 //
1269 MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_TIMER_READ, 0x1);
1270
1271 //
1272 // Read latched values as 2 32-bit vlaues
1273 //
1274 ullRTCVal = MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_TIMER_MSW);
1275 ullRTCVal = ullRTCVal << 32;
1276 ullRTCVal |= MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_TIMER_LSW);
1277
1278 return ullRTCVal;
1279 }
1280
1281 //*****************************************************************************
1282 //
1283 //! Gets the current value of the internal slow clock counter
1284 //!
1285 //! This function is similar to \sa PRCMSlowClkCtrGet() but reads the counter
1286 //! value from a relatively faster interface using an auto-latch mechainsm.
1287 //!
1288 //! \note Due to the nature of implemetation of auto latching, when using this
1289 //! API, the recommendation is to read the value thrice and identify the right
1290 //! value (as 2 out the 3 read values will always be correct and with a max. of
1291 //! 1 LSB change)
1292 //!
1293 //! \return 64-bit current counter vlaue.
1294 //
1295 //*****************************************************************************
PRCMSlowClkCtrFastGet(void)1296 unsigned long long PRCMSlowClkCtrFastGet(void)
1297 {
1298 unsigned long long ullRTCVal;
1299
1300 //
1301 // Read as 2 32-bit values
1302 //
1303 ullRTCVal = HWREG(HIB1P2_BASE + HIB1P2_O_HIB_RTC_TIMER_MSW_1P2);
1304 ullRTCVal = ullRTCVal << 32;
1305 ullRTCVal |= HWREG(HIB1P2_BASE + HIB1P2_O_HIB_RTC_TIMER_LSW_1P2);
1306
1307 return ullRTCVal;
1308
1309 }
1310
1311 //*****************************************************************************
1312 //
1313 //! Sets slow clock counter match value to interrupt the processor.
1314 //!
1315 //! \param ullValue is the match value.
1316 //!
1317 //! This function sets the match value for slow clock counter. This is use
1318 //! to interrupt the processor when RTC counts to the specified value.
1319 //!
1320 //! \return None.
1321 //
1322 //*****************************************************************************
PRCMSlowClkCtrMatchSet(unsigned long long ullValue)1323 void PRCMSlowClkCtrMatchSet(unsigned long long ullValue)
1324 {
1325 //
1326 // Set RTC match value
1327 //
1328 MAP_PRCMHIBRegWrite(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_LSW_CONF,
1329 (unsigned long)(ullValue));
1330 MAP_PRCMHIBRegWrite(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_MSW_CONF,
1331 (unsigned long)(ullValue>>32));
1332 }
1333
1334 //*****************************************************************************
1335 //
1336 //! Gets slow clock counter match value.
1337 //!
1338 //! This function gets the match value for slow clock counter. This is use
1339 //! to interrupt the processor when RTC counts to the specified value.
1340 //!
1341 //! \return None.
1342 //
1343 //*****************************************************************************
PRCMSlowClkCtrMatchGet(void)1344 unsigned long long PRCMSlowClkCtrMatchGet(void)
1345 {
1346 unsigned long long ullValue;
1347
1348 //
1349 // Get RTC match value
1350 //
1351 ullValue = MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_MSW_CONF);
1352 ullValue = ullValue<<32;
1353 ullValue |= MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_LSW_CONF);
1354
1355 //
1356 // Return the value
1357 //
1358 return ullValue;
1359 }
1360
1361
1362 //*****************************************************************************
1363 //
1364 //! Write to On-Chip Retention (OCR) register.
1365 //!
1366 //! This function writes to On-Chip retention register. The device supports two
1367 //! 4-byte OCR register which are retained across all power mode.
1368 //!
1369 //! The parameter \e ucIndex is an index of the OCR and can be \b 0 or \b 1.
1370 //!
1371 //! \return None.
1372 //
1373 //*****************************************************************************
PRCMOCRRegisterWrite(unsigned char ucIndex,unsigned long ulRegValue)1374 void PRCMOCRRegisterWrite(unsigned char ucIndex, unsigned long ulRegValue)
1375 {
1376 MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_REG2+(ucIndex << 2),ulRegValue);
1377 }
1378
1379 //*****************************************************************************
1380 //
1381 //! Read from On-Chip Retention (OCR) register.
1382 //!
1383 //! This function reads from On-Chip retention register. The device supports two
1384 //! 4-byte OCR register which are retained across all power mode.
1385 //!
1386 //! The parameter \e ucIndex is an index of the OCR and can be \b 0 or \b 1.
1387 //!
1388 //! \return None.
1389 //
1390 //*****************************************************************************
PRCMOCRRegisterRead(unsigned char ucIndex)1391 unsigned long PRCMOCRRegisterRead(unsigned char ucIndex)
1392 {
1393 //
1394 // Return the read value.
1395 //
1396 return MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_HIB_REG2 + (ucIndex << 2));
1397 }
1398
1399 //*****************************************************************************
1400 //
1401 //! Registers an interrupt handler for the PRCM.
1402 //!
1403 //! \param pfnHandler is a pointer to the function to be called when the
1404 //! interrupt is activated.
1405 //!
1406 //! This function does the actual registering of the interrupt handler. This
1407 //! function enables the global interrupt in the interrupt controller;
1408 //!
1409 //! \return None.
1410 //
1411 //*****************************************************************************
PRCMIntRegister(void (* pfnHandler)(void))1412 void PRCMIntRegister(void (*pfnHandler)(void))
1413 {
1414 //
1415 // Register the interrupt handler.
1416 //
1417 IntRegister(INT_PRCM, pfnHandler);
1418
1419 //
1420 // Enable the PRCM interrupt.
1421 //
1422 IntEnable(INT_PRCM);
1423 }
1424
1425 //*****************************************************************************
1426 //
1427 //! Unregisters an interrupt handler for the PRCM.
1428 //!
1429 //! This function does the actual unregistering of the interrupt handler. It
1430 //! clears the handler to be called when a PRCM interrupt occurs. This
1431 //! function also masks off the interrupt in the interrupt controller so that
1432 //! the interrupt handler no longer is called.
1433 //!
1434 //! \return None.
1435 //
1436 //*****************************************************************************
PRCMIntUnregister(void)1437 void PRCMIntUnregister(void)
1438 {
1439 //
1440 // Enable the UART interrupt.
1441 //
1442 IntDisable(INT_PRCM);
1443
1444 //
1445 // Register the interrupt handler.
1446 //
1447 IntUnregister(INT_PRCM);
1448 }
1449
1450 //*****************************************************************************
1451 //
1452 //! Enables individual PRCM interrupt sources.
1453 //!
1454 //! \param ulIntFlags is the bit mask of the interrupt sources to be enabled.
1455 //!
1456 //! This function enables the indicated ARCM interrupt sources. Only the
1457 //! sources that are enabled can be reflected to the processor interrupt;
1458 //! disabled sources have no effect on the processor.
1459 //!
1460 //! The \e ulIntFlags parameter is the logical OR of any of the following:
1461 //! -\b PRCM_INT_SLOW_CLK_CTR
1462 //!
1463 //
1464 //*****************************************************************************
PRCMIntEnable(unsigned long ulIntFlags)1465 void PRCMIntEnable(unsigned long ulIntFlags)
1466 {
1467 unsigned long ulRegValue;
1468
1469 if(ulIntFlags & PRCM_INT_SLOW_CLK_CTR )
1470 {
1471 //
1472 // Enable PRCM interrupt
1473 //
1474 HWREG(ARCM_BASE + APPS_RCM_O_APPS_RCM_INTERRUPT_ENABLE) |= 0x4;
1475
1476 //
1477 // Enable RTC interrupt
1478 //
1479 ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE);
1480 ulRegValue |= 0x1;
1481 MAP_PRCMHIBRegWrite(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE, ulRegValue);
1482 }
1483 }
1484
1485 //*****************************************************************************
1486 //
1487 //! Disables individual PRCM interrupt sources.
1488 //!
1489 //! \param ulIntFlags is the bit mask of the interrupt sources to be disabled.
1490 //!
1491 //! This function disables the indicated ARCM interrupt sources. Only the
1492 //! sources that are enabled can be reflected to the processor interrupt;
1493 //! disabled sources have no effect on the processor.
1494 //!
1495 //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags
1496 //! parameter to PRCMEnableInterrupt().
1497 //!
1498 //! \return None.
1499 //
1500 //*****************************************************************************
PRCMIntDisable(unsigned long ulIntFlags)1501 void PRCMIntDisable(unsigned long ulIntFlags)
1502 {
1503 unsigned long ulRegValue;
1504
1505 if(ulIntFlags & PRCM_INT_SLOW_CLK_CTR )
1506 {
1507 //
1508 // Disable PRCM interrupt
1509 //
1510 HWREG(ARCM_BASE + APPS_RCM_O_APPS_RCM_INTERRUPT_ENABLE) &= ~0x4;
1511
1512 //
1513 // Disable RTC interrupt
1514 //
1515 ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE);
1516 ulRegValue &= ~0x1;
1517 MAP_PRCMHIBRegWrite(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE, ulRegValue);
1518 }
1519 }
1520
1521 //*****************************************************************************
1522 //
1523 //! Gets the current interrupt status.
1524 //!
1525 //! This function returns the PRCM interrupt status of interrupts that are
1526 //! allowed to reflect to the processor. The interrupts are cleared on read.
1527 //!
1528 //! \return Returns the current interrupt status.
1529 //
1530 //*****************************************************************************
PRCMIntStatus(void)1531 unsigned long PRCMIntStatus(void)
1532 {
1533 return HWREG(ARCM_BASE + APPS_RCM_O_APPS_RCM_INTERRUPT_STATUS);
1534 }
1535
1536 //*****************************************************************************
1537 //
1538 //! Mark the function of RTC as being used
1539 //!
1540 //! This function marks in HW that feature to maintain calendar time in device
1541 //! is being used.
1542 //!
1543 //! Specifically, this feature reserves user's HIB Register-1 accessed through
1544 //! PRCMOCRRegisterWrite(1) for internal work / purpose, therefore, the stated
1545 //! register is not available to user. Also, users must not excercise the Slow
1546 //! Clock Counter API(s), if RTC has been set for use.
1547 //!
1548 //! \return None.
1549 //
1550 //*****************************************************************************
PRCMRTCInUseSet(void)1551 void PRCMRTCInUseSet(void)
1552 {
1553 RTC_USE_SET();
1554 return;
1555 }
1556
1557 //*****************************************************************************
1558 //
1559 //! Clear the function of RTC as being used
1560 //!
1561 //! \return None.
1562 //
1563 //*****************************************************************************
PRCMRTCInUseClear(void)1564 void PRCMRTCInUseClear(void)
1565 {
1566 RTC_USE_CLR();
1567 return;
1568 }
1569
1570 //*****************************************************************************
1571 //
1572 //! Ascertain whether function of RTC is being used
1573 //!
1574 //! This function indicates whether function of RTC is being used on the device
1575 //! or not.
1576 //!
1577 //! This routine should be utilized by the application software, when returning
1578 //! from low-power, to confirm that RTC has been put to use and may not need to
1579 //! set the value of the RTC.
1580 //!
1581 //! The RTC feature, if set or marked, can be only reset either through reboot
1582 //! or power cycle.
1583 //!
1584 //! \return None.
1585 //
1586 //*****************************************************************************
PRCMRTCInUseGet(void)1587 tBoolean PRCMRTCInUseGet(void)
1588 {
1589 return IS_RTC_USED()? true : false;
1590 }
1591
1592 //*****************************************************************************
1593 //
1594 //! Set the calendar time in the device.
1595 //!
1596 //! \param ulSecs refers to the seconds part of the calendar time
1597 //! \param usMsec refers to the fractional (ms) part of the second
1598 //!
1599 //! This function sets the specified calendar time in the device. The calendar
1600 //! time is outlined in terms of seconds and milliseconds. However, the device
1601 //! makes no assumption about the origin or reference of the calendar time.
1602 //!
1603 //! The device uses the indicated calendar value to update and maintain the
1604 //! wall-clock time across active and low power states.
1605 //!
1606 //! The function PRCMRTCInUseSet() must be invoked prior to use of this feature.
1607 //!
1608 //! \return None.
1609 //
1610 //*****************************************************************************
PRCMRTCSet(unsigned long ulSecs,unsigned short usMsec)1611 void PRCMRTCSet(unsigned long ulSecs, unsigned short usMsec)
1612 {
1613 unsigned long long ullMsec = 0;
1614
1615 if(IS_RTC_USED()) {
1616 ullMsec = RTC_U64MSEC_MK(ulSecs, usMsec) - SCC_U64MSEC_GET();
1617
1618 RTC_U32SECS_REG_WR(RTC_SECS_IN_U64MSEC(ullMsec));
1619 RTC_U32MSEC_REG_WR(RTC_MSEC_IN_U64MSEC(ullMsec));
1620 }
1621
1622 return;
1623 }
1624
1625 //*****************************************************************************
1626 //
1627 //! Get the instantaneous calendar time from the device.
1628 //!
1629 //! \param ulSecs refers to the seconds part of the calendar time
1630 //! \param usMsec refers to the fractional (ms) part of the second
1631 //!
1632 //! This function fetches the instantaneous value of the ticking calendar time
1633 //! from the device. The calendar time is outlined in terms of seconds and
1634 //! milliseconds.
1635 //!
1636 //! The device provides the calendar value that has been maintained across
1637 //! active and low power states.
1638 //!
1639 //! The function PRCMRTCSet() must have been invoked once to set a reference.
1640 //!
1641 //! \return None.
1642 //
1643 //*****************************************************************************
PRCMRTCGet(unsigned long * ulSecs,unsigned short * usMsec)1644 void PRCMRTCGet(unsigned long *ulSecs, unsigned short *usMsec)
1645 {
1646 unsigned long long ullMsec = 0;
1647
1648 if(IS_RTC_USED()) {
1649 ullMsec = RTC_U64MSEC_MK(RTC_U32SECS_REG_RD(),
1650 RTC_U32MSEC_REG_RD());
1651 ullMsec += SCC_U64MSEC_GET();
1652 }
1653
1654 *ulSecs = RTC_SECS_IN_U64MSEC(ullMsec);
1655 *usMsec = RTC_MSEC_IN_U64MSEC(ullMsec);
1656
1657 return;
1658 }
1659
1660 //*****************************************************************************
1661 //
1662 //! Set a calendar time alarm.
1663 //!
1664 //! \param ulSecs refers to the seconds part of the calendar time
1665 //! \param usMsec refers to the fractional (ms) part of the second
1666 //!
1667 //! This function sets an wall-clock alarm in the device to be reported for a
1668 //! futuristic calendar time. The calendar time is outlined in terms of seconds
1669 //! and milliseconds.
1670 //!
1671 //! The device provides uses the calendar value that has been maintained across
1672 //! active and low power states to report attainment of alarm time.
1673 //!
1674 //! The function PRCMRTCSet() must have been invoked once to set a reference.
1675 //!
1676 //! \return None.
1677 //
1678 //*****************************************************************************
PRCMRTCMatchSet(unsigned long ulSecs,unsigned short usMsec)1679 void PRCMRTCMatchSet(unsigned long ulSecs, unsigned short usMsec)
1680 {
1681 unsigned long long ullMsec = 0;
1682
1683 if(IS_RTC_USED()) {
1684 ullMsec = RTC_U64MSEC_MK(ulSecs, usMsec);
1685 ullMsec -= RTC_U64MSEC_MK(RTC_U32SECS_REG_RD(),
1686 RTC_U32MSEC_REG_RD());
1687 SCC_U64MSEC_MATCH_SET(SELECT_SCC_U42BITS(ullMsec));
1688 }
1689
1690 return;
1691 }
1692
1693 //*****************************************************************************
1694 //
1695 //! Get a previously set calendar time alarm.
1696 //!
1697 //! \param ulSecs refers to the seconds part of the calendar time
1698 //! \param usMsec refers to the fractional (ms) part of the second
1699 //!
1700 //! This function fetches from the device a wall-clock alarm that would have
1701 //! been previously set in the device. The calendar time is outlined in terms
1702 //! of seconds and milliseconds.
1703 //!
1704 //! If no alarm was set in the past, then this function would fetch a random
1705 //! information.
1706 //!
1707 //! The function PRCMRTCMatchSet() must have been invoked once to set an alarm.
1708 //!
1709 //! \return None.
1710 //
1711 //*****************************************************************************
PRCMRTCMatchGet(unsigned long * ulSecs,unsigned short * usMsec)1712 void PRCMRTCMatchGet(unsigned long *ulSecs, unsigned short *usMsec)
1713 {
1714 unsigned long long ullMsec = 0;
1715
1716 if(IS_RTC_USED()) {
1717 ullMsec = SCC_U64MSEC_MATCH_GET();
1718 ullMsec += RTC_U64MSEC_MK(RTC_U32SECS_REG_RD(),
1719 RTC_U32MSEC_REG_RD());
1720 }
1721
1722 *ulSecs = RTC_SECS_IN_U64MSEC(ullMsec);
1723 *usMsec = RTC_MSEC_IN_U64MSEC(ullMsec);
1724
1725 return;
1726 }
1727
1728 //*****************************************************************************
1729 //
1730 //! MCU Initialization Routine
1731 //!
1732 //! This function sets mandatory configurations for the MCU
1733 //!
1734 //! \return None
1735 //
1736 //*****************************************************************************
PRCMCC3200MCUInit(void)1737 void PRCMCC3200MCUInit(void)
1738 {
1739 unsigned long ulRegValue;
1740
1741 //
1742 // DIG DCDC LPDS ECO Enable
1743 //
1744 HWREG(0x4402F064) |= 0x800000;
1745
1746 //
1747 // Enable hibernate ECO for PG 1.32 devices only. With this ECO enabled,
1748 // any hibernate wakeup source will be kept masked until the device enters
1749 // hibernate completely (analog + digital)
1750 //
1751 ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_REG0);
1752 MAP_PRCMHIBRegWrite(HIB3P3_BASE + HIB3P3_O_MEM_HIB_REG0, ulRegValue | (1<<4));
1753
1754 //
1755 // Handling the clock switching (for 1.32 only)
1756 //
1757 HWREG(0x4402E16C) |= 0x3C;
1758
1759 //
1760 // Enable uDMA
1761 //
1762 MAP_PRCMPeripheralClkEnable(PRCM_UDMA,PRCM_RUN_MODE_CLK);
1763
1764 //
1765 // Reset uDMA
1766 //
1767 MAP_PRCMPeripheralReset(PRCM_UDMA);
1768
1769 //
1770 // Disable uDMA
1771 //
1772 MAP_PRCMPeripheralClkDisable(PRCM_UDMA,PRCM_RUN_MODE_CLK);
1773
1774 //
1775 // Enable RTC
1776 //
1777 if(MAP_PRCMSysResetCauseGet()== PRCM_POWER_ON)
1778 {
1779 MAP_PRCMHIBRegWrite(0x4402F804,0x1);
1780 }
1781
1782 //
1783 // SWD mode
1784 //
1785 if (((HWREG(0x4402F0C8) & 0xFF) == 0x2))
1786 {
1787 HWREG(0x4402E110) = ((HWREG(0x4402E110) & ~0xC0F) | 0x2);
1788 HWREG(0x4402E114) = ((HWREG(0x4402E110) & ~0xC0F) | 0x2);
1789 }
1790
1791 //
1792 // Override JTAG mux
1793 //
1794 HWREG(0x4402E184) |= 0x2;
1795
1796 //
1797 // Change UART pins(55,57) mode to PIN_MODE_0 if they are in PIN_MODE_1
1798 //
1799 if ((HWREG(0x4402E0A4) & 0xF) == 0x1)
1800 {
1801 HWREG(0x4402E0A4) = ((HWREG(0x4402E0A4) & ~0xF));
1802 }
1803
1804 if ((HWREG(0x4402E0A8) & 0xF) == 0x1)
1805 {
1806 HWREG(0x4402E0A8) = ((HWREG(0x4402E0A8) & ~0xF));
1807 }
1808
1809 //
1810 // DIG DCDC VOUT trim settings based on PROCESS INDICATOR
1811 //
1812 if (((HWREG(0x4402DC78) >> 22) & 0xF) == 0xE)
1813 {
1814 HWREG(0x4402F0B0) = ((HWREG(0x4402F0B0) & ~(0x00FC0000))|(0x32 << 18));
1815 }
1816 else
1817 {
1818 HWREG(0x4402F0B0) = ((HWREG(0x4402F0B0) & ~(0x00FC0000))|(0x29 << 18));
1819 }
1820
1821 //
1822 // Enable SOFT RESTART in case of DIG DCDC collapse
1823 //
1824 HWREG(0x4402FC74) &= ~(0x10000000);
1825
1826
1827 //
1828 // Disable the sleep for ANA DCDC
1829 //
1830 HWREG(0x4402F0A8) |= 0x00000004 ;
1831 }
1832
1833 //*****************************************************************************
1834 //
1835 //! Reads 32-bit value from register at specified address
1836 //!
1837 //! \param ulRegAddr is the address of register to be read.
1838 //!
1839 //! This function reads 32-bit value from the register as specified by
1840 //! \e ulRegAddr.
1841 //!
1842 //! \return Return the value of the register.
1843 //
1844 //*****************************************************************************
PRCMHIBRegRead(unsigned long ulRegAddr)1845 unsigned long PRCMHIBRegRead(unsigned long ulRegAddr)
1846 {
1847 unsigned long ulValue;
1848
1849 //
1850 // Read the Reg value
1851 //
1852 ulValue = HWREG(ulRegAddr);
1853
1854 //
1855 // Wait for 200 uSec
1856 //
1857 UtilsDelay((80*200)/3);
1858
1859 //
1860 // Return the value
1861 //
1862 return ulValue;
1863 }
1864
1865 //*****************************************************************************
1866 //
1867 //! Writes 32-bit value to register at specified address
1868 //!
1869 //! \param ulRegAddr is the address of register to be read.
1870 //! \param ulValue is the 32-bit value to be written.
1871 //!
1872 //! This function writes 32-bit value passed as \e ulValue to the register as
1873 //! specified by \e ulRegAddr
1874 //!
1875 //! \return None
1876 //
1877 //*****************************************************************************
PRCMHIBRegWrite(unsigned long ulRegAddr,unsigned long ulValue)1878 void PRCMHIBRegWrite(unsigned long ulRegAddr, unsigned long ulValue)
1879 {
1880 //
1881 // Read the Reg value
1882 //
1883 HWREG(ulRegAddr) = ulValue;
1884
1885 //
1886 // Wait for 200 uSec
1887 //
1888 UtilsDelay((80*200)/3);
1889 }
1890
1891 //*****************************************************************************
1892 //
1893 //! \param ulDivider is clock frequency divider value
1894 //! \param ulWidth is the width of the high pulse
1895 //!
1896 //! This function sets the input frequency for camera module.
1897 //!
1898 //! The frequency is calculated as follows:
1899 //!
1900 //! f_out = 240MHz/ulDivider;
1901 //!
1902 //! The parameter \e ulWidth sets the width of the high pulse.
1903 //!
1904 //! For e.g.:
1905 //!
1906 //! ulDivider = 4;
1907 //! ulWidth = 2;
1908 //!
1909 //! f_out = 30 MHz and 50% duty cycle
1910 //!
1911 //! And,
1912 //!
1913 //! ulDivider = 4;
1914 //! ulWidth = 1;
1915 //!
1916 //! f_out = 30 MHz and 25% duty cycle
1917 //!
1918 //! \return 0 on success, 1 on error
1919 //
1920 //*****************************************************************************
PRCMCameraFreqSet(unsigned char ulDivider,unsigned char ulWidth)1921 unsigned long PRCMCameraFreqSet(unsigned char ulDivider, unsigned char ulWidth)
1922 {
1923 if(ulDivider > ulWidth && ulWidth != 0 )
1924 {
1925 //
1926 // Set the hifh pulse width
1927 //
1928 HWREG(ARCM_BASE +
1929 APPS_RCM_O_CAMERA_CLK_GEN) = (((ulWidth & 0x07) -1) << 8);
1930
1931 //
1932 // Set the low pulse width
1933 //
1934 HWREG(ARCM_BASE +
1935 APPS_RCM_O_CAMERA_CLK_GEN) = ((ulDivider - ulWidth - 1) & 0x07);
1936 //
1937 // Return success
1938 //
1939 return 0;
1940 }
1941
1942 //
1943 // Success;
1944 //
1945 return 1;
1946 }
1947
1948 //*****************************************************************************
1949 //
1950 // Close the Doxygen group.
1951 //! @}
1952 //
1953 //*****************************************************************************
1954