aurix_hal_sys.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. #include <machine/intrinsics.h>
  2. #include <machine/wdtcon.h>
  3. #include <stdlib.h>
  4. #include "aurix_hal_sys.h"
  5. #include "IfxScu_reg.h"
  6. #include "IfxScu_bf.h"
  7. #include "IfxCpu_reg.h"
  8. #include "IfxCpu_bf.h"
  9. #include "IfxStm_reg.h"
  10. #include "IfxStm_bf.h"
  11. #include "IfxQspi_reg.h"
  12. # define BOARD_NAME "TriBoard-TC233A"
  13. # define BOARD_TITLE "TC233A TriBoard"
  14. # define MCU_NAME "TC233A"
  15. #include "IfxPort_reg.h"
  16. #include "IfxPort_bf.h"
  17. #include "IfxAsclin_reg.h"
  18. #include "IfxAsclin_bf.h"
  19. #define USE_DISABLE_EXT_WDT 1
  20. typedef struct _PllInitValue_t
  21. {
  22. unsigned int valOSCCON;
  23. unsigned int valPLLCON0;
  24. unsigned int valPLLCON1; /* first step K dividers */
  25. unsigned int valCCUCON0;
  26. unsigned int valCCUCON1;
  27. unsigned int valCCUCON2;
  28. unsigned int finalK; /* final K2DIV value */
  29. } PllInitValue_t;
  30. static const PllInitValue_t g_PllInitValue_200_100;
  31. #define PLL_VALUE_200_100 ((const PllInitValue_t *)(&g_PllInitValue_200_100))
  32. static const PllInitValue_t g_PllInitValue_100_50;
  33. #define PLL_VALUE_100_50 ((const PllInitValue_t *)(&g_PllInitValue_100_50))
  34. static const PllInitValue_t g_PllInitValue_7_37;
  35. #define PLL_VALUE_20_10 ((const PllInitValue_t *)(&g_PllInitValue_20_10))
  36. #define DEFAULT_PLL_VALUE PLL_VALUE_20_10
  37. #ifndef DEFAULT_PLL_VALUE
  38. # define DEFAULT_PLL_VALUE PLL_VALUE_200_100
  39. #endif
  40. #ifndef EXTCLK
  41. # define EXTCLK (20000000) /* external oscillator clock (20MHz) */
  42. #endif
  43. #pragma section ".rodata"
  44. /* PLL settings for 20MHz ext. clock */
  45. static const PllInitValue_t g_PllInitValue_20_10 = {
  46. 0x0007001C, 0x01017600, 0x00022020, 0x12120118, 0x10012242, 0x00000002, 29
  47. };
  48. /* 200/100 MHz @ 20MHz ext. clock */
  49. static const PllInitValue_t g_PllInitValue_200_100 =
  50. {
  51. /* OSCCON, PLLCON0, PLLCON1, CCUCON0, CCUCON1, CCUCON2, finalK */
  52. 0x0007001C, 0x01017600, 0x00020505, 0x12120118, 0x10012242, 0x00000002, 2
  53. };
  54. /* 100/50 MHz @ 20MHz ext. clock */
  55. static const PllInitValue_t g_PllInitValue_100_50 =
  56. {
  57. /* OSCCON, PLLCON0, PLLCON1, CCUCON0, CCUCON1, CCUCON2, finalK */
  58. 0x0007001C, 0x01018a00, 0x00020606, 0x12120118, 0x10012241, 0x00000002, 6
  59. };
  60. #pragma section
  61. static Ifx_SCU * const pSCU = (Ifx_SCU *)&MODULE_SCU;
  62. #if (USE_DISABLE_EXT_WDT == 1)
  63. /* for serving A-step and B-step (+ newer) TLF devices: use both commands for err pin monitor */
  64. #define WDT_CMD_SIZE (10 + 1)
  65. static void disable_external_watchdog(void)
  66. {
  67. int i;
  68. /* command sequence for disabling external watchdog */
  69. const unsigned short wdtdiscmd[WDT_CMD_SIZE] =
  70. {
  71. 0x8756, 0x87de, 0x86ad, 0x8625, /* unprotect register (PROTCFG) */
  72. 0x8d27, /* disable window watchdog */
  73. 0x8811, /* disable err pin monitor (A-step) */
  74. 0x8A01, /* disable err pin monitor (not A-step) */
  75. 0x87be, 0x8668, 0x877d, 0x8795 /* protect register (PROTCFG) */
  76. };
  77. /* check that this disabling has not been already done (e.g. by the debugger) */
  78. if (QSPI2_GLOBALCON.B.EN)
  79. {
  80. /* don't do it again */
  81. return;
  82. }
  83. /* initialise QSPI2 interface */
  84. unlock_wdtcon(); /* remove ENDINIT protection */
  85. QSPI2_CLC.U = 0x8; /* activate module, disable sleep mode */
  86. (void)QSPI2_CLC.U; /* read back to get effective */
  87. P15_PDR0.U = 0x00000000; /* fast speed (all pins) */
  88. P14_PDR0.U = 0x00000000; /* fast speed (all pins) */
  89. QSPI2_PISEL.U = 1; /* MRIS=1 ==> use MRST2B pin */
  90. lock_wdtcon(); /* re-enable ENDINIT protection */
  91. /* configure port pins */
  92. P14_IOCR0.B.PC2 = 0x13; /* SLSO21 */
  93. P15_IOCR0.B.PC3 = 0x13; /* SCLK2 */
  94. #if (APPKIT_TC2X7 == 1)
  95. P15_IOCR4.B.PC6 = 0x13; /* MTSR2 */
  96. #else
  97. P15_IOCR4.B.PC5 = 0x13; /* MTSR2 */
  98. #endif /* APPKIT_TC2X7 */
  99. P15_IOCR4.B.PC7 = 0x02; /* MRST2B */
  100. /* program QSPI2 parameters */
  101. QSPI2_GLOBALCON.U = 0x00003C04; /* EXPECT=15,SI=0, TQ=4 */
  102. QSPI2_GLOBALCON1.U = 0x14000000;/* RXFM=1,TXFM=1 (Single Move Mode for RX/TX) */
  103. QSPI2_SSOC.U = 0x00020000; /* enable SLSO21, low active */
  104. QSPI2_ECON1.U = 0x501; /* Q=1,A=0,B=1,C=1 */
  105. do
  106. {
  107. QSPI2_FLAGSCLEAR.U = 0xFFF; /* PT2F,PT1F,RXF,TXF,ERRORFLAGS */
  108. } while (QSPI2_STATUS.U & 0xFFF);
  109. /* prepare data transfer format */
  110. QSPI2_BACONENTRY.U = 0x17A10001; /* CS=1,DL=15,MSB=1,TRAIL=1,LAST=1 */
  111. QSPI2_GLOBALCON.B.EN = 1; /* ... and enable the module */
  112. /* transfer all data */
  113. for (i = 0; i < WDT_CMD_SIZE; ++i)
  114. {
  115. QSPI2_DATAENTRY0.U = (unsigned int)wdtdiscmd[i];
  116. /* wait until transfer is complete */
  117. while (!QSPI2_STATUS.B.TXF)
  118. ;
  119. /* clear TX flag */
  120. QSPI2_FLAGSCLEAR.U = 1 << 9;
  121. /* wait for receive is finished */
  122. while (!QSPI2_STATUS.B.RXF)
  123. ;
  124. /* clear RX flag */
  125. QSPI2_FLAGSCLEAR.U = 1 << 10;
  126. /* read and discard value */
  127. (void)QSPI2_RXEXIT.U;
  128. }
  129. }
  130. #endif /* USE_DISABLE_EXT_WDT */
  131. #ifndef SYSTEM_DONT_SET_PLL
  132. /* STM time scaling (for avoiding overflow) */
  133. #define TIME_SCALE_DN 100
  134. #define TIME_SCALE_UP (1000000 / TIME_SCALE_DN)
  135. /* wait for <time> micro seconds */
  136. /* beware of overflows: 100 us at (>=)43 MHz will overflow (if not scaled before multiplying) */
  137. static void wait(unsigned int time)
  138. {
  139. unsigned int fSTM = (unsigned int)SYSTEM_GetStmClock();
  140. unsigned int stmWaitCount = (fSTM / TIME_SCALE_DN) * time / TIME_SCALE_UP;
  141. /* prepare compare register */
  142. STM0_CMP0.U = STM0_TIM0.U + stmWaitCount;
  143. STM0_CMCON.U = 31;
  144. /* Attention: keep this order, otherwise first match will trigger too soon */
  145. /* reset interrupt flag */
  146. STM0_ISCR.U = (IFX_STM_ISCR_CMP0IRR_MSK << IFX_STM_ISCR_CMP0IRR_OFF);
  147. /* enable compare match */
  148. STM0_ICR.B.CMP0EN = 1;
  149. /* wait for compare match */
  150. while (0 == STM0_ICR.B.CMP0IR)
  151. ;
  152. STM0_ICR.B.CMP0EN = 0;
  153. }
  154. static void system_set_pll(const PllInitValue_t *pPllInitValue)
  155. {
  156. unsigned int k;
  157. unlock_safety_wdtcon();
  158. pSCU->OSCCON.U = pPllInitValue->valOSCCON;
  159. while (pSCU->CCUCON1.B.LCK)
  160. ;
  161. pSCU->CCUCON1.U = pPllInitValue->valCCUCON1 | (1 << IFX_SCU_CCUCON1_UP_OFF);
  162. while (pSCU->CCUCON2.B.LCK)
  163. ;
  164. pSCU->CCUCON2.U = pPllInitValue->valCCUCON2 | (1 << IFX_SCU_CCUCON2_UP_OFF);
  165. pSCU->PLLCON0.U |= ((1 << IFX_SCU_PLLCON0_VCOBYP_OFF) | (1 << IFX_SCU_PLLCON0_SETFINDIS_OFF));
  166. pSCU->PLLCON1.U = pPllInitValue->valPLLCON1; /* set Kn divider */
  167. pSCU->PLLCON0.U = pPllInitValue->valPLLCON0 /* set P,N divider */
  168. | ((1 << IFX_SCU_PLLCON0_VCOBYP_OFF) | (1 << IFX_SCU_PLLCON0_CLRFINDIS_OFF));
  169. while (pSCU->CCUCON0.B.LCK)
  170. ;
  171. pSCU->CCUCON0.U = pPllInitValue->valCCUCON0 | (1 << IFX_SCU_CCUCON0_UP_OFF);
  172. lock_safety_wdtcon();
  173. if (0 == (pPllInitValue->valPLLCON0 & (1 << IFX_SCU_PLLCON0_VCOBYP_OFF))) /* no prescaler mode requested */
  174. {
  175. #ifndef SYSTEM_PLL_HAS_NO_LOCK
  176. /* wait for PLL locked */
  177. while (0 == pSCU->PLLSTAT.B.VCOLOCK)
  178. ;
  179. #endif
  180. unlock_safety_wdtcon();
  181. pSCU->PLLCON0.B.VCOBYP = 0; /* disable VCO bypass */
  182. lock_safety_wdtcon();
  183. }
  184. /* update K dividers for stepping up to final clock */
  185. k = pSCU->PLLCON1.B.K2DIV;
  186. /* wait some time (100 us) */
  187. wait(100);
  188. while (k > pPllInitValue->finalK)
  189. {
  190. Ifx_SCU_PLLCON1 pllcon1 = pSCU->PLLCON1;
  191. --k;
  192. /* prepare value to write */
  193. pllcon1.B.K2DIV = k;
  194. pllcon1.B.K3DIV = k;
  195. /* wait until K2 operation is stable */
  196. while (0 == pSCU->PLLSTAT.B.K2RDY)
  197. ;
  198. unlock_safety_wdtcon();
  199. pSCU->PLLCON1 = pllcon1;
  200. lock_safety_wdtcon();
  201. /* wait some time (100 us) */
  202. wait(100);
  203. }
  204. }
  205. #endif
  206. /*! \brief System initialisation
  207. * \param pPllInitValue ... address of PLL initialisation struct
  208. */
  209. static void SYSTEM_InitExt(const PllInitValue_t *pPllInitValue)
  210. {
  211. #ifndef SYSTEM_DONT_SET_PLL
  212. /* initialise PLL (only done by CPU0) */
  213. if (0 == (_mfcr(CPU_CORE_ID) & IFX_CPU_CORE_ID_CORE_ID_MSK))
  214. system_set_pll(pPllInitValue);
  215. #endif
  216. #ifdef USE_IRQ
  217. /* activate interrupt system */
  218. InterruptInit();
  219. #endif /* USE_IRQ */
  220. }
  221. void SYSTEM_Init(void)
  222. {
  223. SYSTEM_InitExt(DEFAULT_PLL_VALUE);
  224. #if (USE_DISABLE_EXT_WDT == 1)
  225. disable_external_watchdog();
  226. #endif /* USE_DISABLE_EXT_WDT */
  227. }
  228. unsigned long SYSTEM_GetExtClock(void)
  229. {
  230. return EXTCLK;
  231. }
  232. static unsigned long system_GetPllClock(void)
  233. {
  234. unsigned int frequency = EXTCLK; /* fOSC */
  235. Ifx_SCU_PLLSTAT pllstat = pSCU->PLLSTAT;
  236. Ifx_SCU_PLLCON0 pllcon0 = pSCU->PLLCON0;
  237. Ifx_SCU_PLLCON1 pllcon1 = pSCU->PLLCON1;
  238. if (0 == (pllstat.B.VCOBYST))
  239. {
  240. if (0 == (pllstat.B.FINDIS))
  241. {
  242. /* normal mode */
  243. frequency *= (pllcon0.B.NDIV + 1); /* fOSC*N */
  244. frequency /= (pllcon0.B.PDIV + 1); /* .../P */
  245. frequency /= (pllcon1.B.K2DIV + 1); /* .../K2 */
  246. }
  247. else /* freerunning mode */
  248. {
  249. frequency = 800000000; /* fVCOBASE 800 MHz (???) */
  250. frequency /= (pllcon1.B.K2DIV + 1); /* .../K2 */
  251. }
  252. }
  253. else /* prescaler mode */
  254. {
  255. frequency /= (pllcon1.B.K1DIV + 1); /* fOSC/K1 */
  256. }
  257. return (unsigned long)frequency;
  258. }
  259. static unsigned long system_GetIntClock(void)
  260. {
  261. unsigned long frequency = 0;
  262. switch (pSCU->CCUCON0.B.CLKSEL)
  263. {
  264. default:
  265. case 0: /* back-up clock (typ. 100 MHz) */
  266. frequency = 100000000ul;
  267. break;
  268. case 1: /* fPLL */
  269. frequency = system_GetPllClock();
  270. break;
  271. }
  272. return frequency;
  273. }
  274. unsigned long SYSTEM_GetCpuClock(void)
  275. {
  276. unsigned long frequency = system_GetIntClock();
  277. /* fCPU = fSRI */
  278. unsigned long divider = pSCU->CCUCON0.B.SRIDIV;
  279. unsigned long cpudiv = pSCU->CCUCON6.B.CPU0DIV;
  280. if (0 == divider)
  281. return 0;
  282. frequency /= divider;
  283. if (cpudiv != 0)
  284. {
  285. frequency *= (64 - cpudiv);
  286. frequency /= 64;
  287. }
  288. return frequency;
  289. }
  290. unsigned long SYSTEM_GetSysClock(void)
  291. {
  292. unsigned long frequency = system_GetIntClock();
  293. unsigned long divider = pSCU->CCUCON0.B.SPBDIV;
  294. if (0 == divider)
  295. return 0;
  296. return (frequency / divider);
  297. }
  298. unsigned long SYSTEM_GetStmClock(void)
  299. {
  300. unsigned long frequency = system_GetIntClock();
  301. unsigned long divider = pSCU->CCUCON1.B.STMDIV;
  302. if (0 == divider)
  303. return 0;
  304. return (frequency / divider);
  305. }
  306. unsigned long SYSTEM_GetCanClock(void)
  307. {
  308. unsigned long frequency = system_GetIntClock();
  309. unsigned long divider = pSCU->CCUCON1.B.CANDIV;
  310. if (0 == divider)
  311. return 0;
  312. return (frequency / divider);
  313. }
  314. void SYSTEM_EnableInterrupts(void)
  315. {
  316. _enable();
  317. }
  318. void SYSTEM_DisableInterrupts(void)
  319. {
  320. _disable();
  321. }
  322. void SYSTEM_EnableProtection(void)
  323. {
  324. lock_wdtcon();
  325. }
  326. void SYSTEM_DisableProtection(void)
  327. {
  328. unlock_wdtcon();
  329. }
  330. void SYSTEM_EnableProtectionExt(int Sel)
  331. {
  332. if (Sel < 3)
  333. lock_wdtcon(); /* CPU watchdog */
  334. else
  335. lock_safety_wdtcon(); /* safety watchdog */
  336. }
  337. void SYSTEM_DisableProtectionExt(int Sel)
  338. {
  339. if (Sel < 3)
  340. unlock_wdtcon(); /* CPU watchdog */
  341. else
  342. unlock_safety_wdtcon(); /* safety watchdog */
  343. }
  344. void SYSTEM_EnableSecProtection(void)
  345. {
  346. lock_safety_wdtcon();
  347. }
  348. void SYSTEM_DisableSecProtection(void)
  349. {
  350. unlock_safety_wdtcon();
  351. }
  352. int SYSTEM_Reset(void)
  353. {
  354. unlock_safety_wdtcon();
  355. pSCU->SWRSTCON.B.SWRSTREQ = 1;
  356. while (1)
  357. ;
  358. return 0;
  359. }
  360. int SYSTEM_IdleExt(int CoreId)
  361. {
  362. unlock_wdtcon();
  363. switch (CoreId)
  364. {
  365. case 0:
  366. pSCU->PMCSR[0].U = 1; /* request CPU idle mode */
  367. break;
  368. }
  369. lock_wdtcon();
  370. return 0;
  371. }
  372. int SYSTEM_Idle(void)
  373. {
  374. return SYSTEM_IdleExt(_mfcr(CPU_CORE_ID) & IFX_CPU_CORE_ID_CORE_ID_MSK);
  375. }
  376. int SYSTEM_Sleep(void)
  377. {
  378. unlock_wdtcon();
  379. switch (_mfcr(CPU_CORE_ID) & IFX_CPU_CORE_ID_CORE_ID_MSK)
  380. {
  381. case 0:
  382. pSCU->PMCSR[0].U = 2; /* request system sleep mode */
  383. break;
  384. }
  385. lock_wdtcon();
  386. return 0;
  387. }
  388. int SYSTEM_IsCacheEnabled(void)
  389. {
  390. unsigned int ui = _mfcr(CPU_PCON0);
  391. if (ui & 2)
  392. return 0; /* Cache is in bypass mode */
  393. ui = _mfcr(CPU_PCON2);
  394. if (0 == (ui & (IFX_CPU_PCON2_PCACHE_SZE_MSK << IFX_CPU_PCON2_PCACHE_SZE_OFF)))
  395. return 0; /* Cache size is 0 */
  396. return 1;
  397. }
  398. void SYSTEM_EnaDisCache(int Enable)
  399. {
  400. unlock_wdtcon();
  401. if (Enable)
  402. {
  403. _mtcr(CPU_PCON0, 0);
  404. _mtcr(CPU_DCON0, 0);
  405. }
  406. else /* disable */
  407. {
  408. _mtcr(CPU_PCON0, 2);
  409. _mtcr(CPU_PCON1, 3);
  410. _mtcr(CPU_DCON0, 2);
  411. }
  412. lock_wdtcon();
  413. }
  414. void SYSTEM_DbgBreak(void)
  415. {
  416. #ifdef DEBUG
  417. __asm volatile ("debug");
  418. #else
  419. while (1)
  420. ;
  421. #endif
  422. }