ethernut5.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * Copyright 2010-2012 by egnite GmbH
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. /*
  35. * \file arch/arm/board/ethernut5.c
  36. * \brief Ethernut 5 board initialization.
  37. *
  38. * \verbatim
  39. * $Id$
  40. * \endverbatim
  41. */
  42. #include <toolchain.h>
  43. #ifndef PMM_RST_BASE
  44. /* Power management reset port. */
  45. #define PMM_RST_BASE PIOB_BASE
  46. #endif
  47. #ifndef PMM_RST_PIN
  48. /* Power management reset pin. */
  49. #define PMM_RST_PIN 8
  50. #endif
  51. /*! \name Power Management Registers */
  52. /*@{*/
  53. /*! \brief Version register. */
  54. #define PWRMAN_REG_VERS 0
  55. /*! \brief Feature status register. */
  56. #define PWRMAN_REG_STA 1
  57. /*! \brief Feature enable register. */
  58. #define PWRMAN_REG_ENA 2
  59. /*! \brief Feature disable register. */
  60. #define PWRMAN_REG_DIS 3
  61. /*! \brief Board temperature register. */
  62. #define PWRMAN_REG_TEMP 4
  63. /*! \brief Auxiliary input voltage register. */
  64. #define PWRMAN_REG_VAUX 6
  65. /*! \brief LED blinking timer register. */
  66. #define PWRMAN_REG_LEDCTL 8
  67. /*@}*/
  68. /* \name Feature flags */
  69. /*@{*/
  70. /*! \brief 1.8V and 3.3V supply. */
  71. #define PWRMAN_BOARD 0x01
  72. /*! \brief VBUS input at device connector. */
  73. #define PWRMAN_VBIN 0x02
  74. /*! \brief VBUS output at host connector. */
  75. #define PWRMAN_VBOUT 0x04
  76. /*! \brief Memory card supply. */
  77. #define PWRMAN_MMC 0x08
  78. /*! \brief RS-232 driver shutdown. */
  79. #define PWRMAN_RS232 0x10
  80. /*! \brief Ethernet clock enable. */
  81. #define PWRMAN_ETHCLK 0x20
  82. /*! \brief Ethernet PHY reset. */
  83. #define PWRMAN_ETHRST 0x40
  84. /*! \brief RTC wake-up. */
  85. #define PWRMAN_WAKEUP 0x80
  86. /*@}*/
  87. #define ARM_TTD_DOM_LSB 5
  88. #define ARM_TTD_DOM(x) ((x) << ARM_TTD_DOM_LSB)
  89. #define ARM_TTD_AP_PN_UN 0x000
  90. #define ARM_TTD_AP_PW_UN 0x400
  91. #define ARM_TTD_AP_PW_UR 0x800
  92. #define ARM_TTD_AP_PW_UW 0xC00
  93. #define ARM_TTD_INVALID 0x0
  94. #define ARM_TTD_COARSE_PAGE 0x1
  95. #define ARM_TTD_SECTION 0x12
  96. #define ARM_TTD_FINE_PAGE 0x3
  97. /* Noncacheable, nonbufferable */
  98. #define ARM_TTD_NC_NB 0x0
  99. /* Noncacheable, bufferable */
  100. #define ARM_TTD_NC_B 0x4
  101. /* Cacheable, write-through */
  102. #define ARM_TTD_C_WT 0x8
  103. /* Cacheable, write-back */
  104. #define ARM_TTD_C_WB 0xC
  105. #define ARM_SET_CP15_TTBR(val) __asm__ __volatile__("mcr p15, 0, %0, c2, c0, 0" :: "r"(val) : "cc")
  106. #define ARM_SET_CP15_DACR(val) __asm__ __volatile__("mcr p15, 0, %0, c3, c0, 0" :: "r"(val) : "cc")
  107. void __set_stacks(void) NUT_NAKED_FUNC;
  108. void __init2(void) NUT_NAKED_FUNC NUT_LINKER_SECT(".init2.user");
  109. void __init2(void)
  110. {
  111. /*
  112. * The watchdog is enabled after processor reset.
  113. */
  114. #if defined(NUT_WDT_START)
  115. #if NUT_WDT_START
  116. /* Configure the watchdog. */
  117. outr(WDT_MR, NUT_WDT_START);
  118. #else
  119. /* Disable the watchdog. */
  120. outr(WDT_MR, WDT_WDDIS);
  121. #endif
  122. #endif
  123. /*
  124. * Enable external reset key.
  125. */
  126. outr(RSTC_MR, RSTC_KEY | RSTC_URSTEN);
  127. /* Continue with runtime initialization. */
  128. __set_stacks();
  129. }
  130. void __clear_bss(void) NUT_NAKED_FUNC;
  131. void __init3(void) NUT_NAKED_FUNC NUT_LINKER_SECT(".init3.user");
  132. void __init3(void)
  133. {
  134. /* Enable instruction cache. */
  135. ARM_SET_CP15_CR(ARM_GET_CP15_CR() | (1 << 12));
  136. /* Continue with runtime initialization. */
  137. __clear_bss();
  138. }
  139. void __call_rtos(void) NUT_NAKED_FUNC;
  140. void __init4(void) NUT_NAKED_FUNC NUT_LINKER_SECT(".init4.user");
  141. void __init4(void)
  142. {
  143. static unsigned int *ttb = (unsigned int *) 0x20000000;
  144. static const unsigned int dom = 0xC0000000;
  145. static unsigned int i;
  146. /* Set translation table base. */
  147. ARM_SET_CP15_TTBR((unsigned int) ttb);
  148. /* Do not check access permissions for domain 15. */
  149. ARM_SET_CP15_DACR(dom);
  150. for(i = 0; i < 4096; i++) {
  151. ttb[i] = 0;
  152. }
  153. /* Set mapped internal SRAM section mapping. */
  154. ttb[0x000] = 0x00000000 | ARM_TTD_AP_PW_UN | ARM_TTD_DOM(15) | ARM_TTD_C_WB | ARM_TTD_SECTION;
  155. /* Set Flash memory section mapping. */
  156. ttb[0x002] = 0x00200000 | ARM_TTD_AP_PW_UN | ARM_TTD_DOM(15) | ARM_TTD_C_WT | ARM_TTD_SECTION;
  157. for(i = 0; i < 128; i++) {
  158. ttb[0x200 + i] = (0x20000000 + (i << 20)) | ARM_TTD_AP_PW_UN | ARM_TTD_DOM(15) | ARM_TTD_C_WB | ARM_TTD_SECTION;
  159. }
  160. /* Set external NAND Flash mapping. */
  161. for(i = 0; i < 256; i++) {
  162. ttb[0x400 + i] = (0x40000000 + (i << 20)) | ARM_TTD_AP_PW_UN | ARM_TTD_DOM(15) | ARM_TTD_SECTION;
  163. }
  164. /* Set peripheral register mapping. */
  165. ttb[0xFFF] = 0xFFF00000 | ARM_TTD_AP_PW_UN | ARM_TTD_DOM(15) | ARM_TTD_SECTION;
  166. /* Finally enable the MMU and the data cache. */
  167. ARM_SET_CP15_CR(ARM_GET_CP15_CR() | (1 << 12) | (1 << 2));
  168. /* Continue with runtime initialization. */
  169. __call_rtos();
  170. }
  171. /*!
  172. * \brief Delay loop.
  173. *
  174. * Delay by executing a given number of loops, roughly 5ns each.
  175. *
  176. * \param n Number of microseconds.
  177. */
  178. static void BootLoopDelay(int n)
  179. {
  180. while (n--) {
  181. _NOP();
  182. }
  183. }
  184. /*!
  185. * \brief Microsecond delay.
  186. *
  187. * \param us Number of microseconds.
  188. */
  189. static void BootMicroDelay(int us)
  190. {
  191. while (us--) {
  192. BootLoopDelay(200);
  193. }
  194. }
  195. /*!
  196. * \brief Millisecond delay.
  197. *
  198. * We are running prior to Nut/OS timer initialization and cannot use
  199. * NutSleep, not even NutDelay.
  200. *
  201. * \param ms Number of milliseconds.
  202. */
  203. static void BootMilliDelay(int ms)
  204. {
  205. while (ms--) {
  206. BootMicroDelay(1000);
  207. }
  208. }
  209. /*!
  210. * \brief Initialize the power management interface.
  211. */
  212. static void PmmInit(void)
  213. {
  214. #if defined(PMM_RST_BASE) && defined(PMM_RST_PIN)
  215. /* Activate the power management reset pin. */
  216. outr(PMM_RST_BASE + PIO_SODR_OFF, _BV(PMM_RST_PIN));
  217. outr(PMM_RST_BASE + PIO_PER_OFF, _BV(PMM_RST_PIN));
  218. outr(PMM_RST_BASE + PIO_OER_OFF, _BV(PMM_RST_PIN));
  219. BootMilliDelay(1);
  220. /* Deactivate the reset. */
  221. outr(PMM_RST_BASE + PIO_CODR_OFF, _BV(PMM_RST_PIN));
  222. BootMilliDelay(100);
  223. #endif
  224. /* Set peripheral lines for TWD and TWCK. */
  225. outr(PIOA_ASR, _BV(PA23_TWD_A) | _BV(PA24_TWCK_A));
  226. outr(PIOA_PDR, _BV(PA23_TWD_A) | _BV(PA24_TWCK_A));
  227. /* Switch TWI lines to open drain. */
  228. outr(PIOA_MDER, _BV(PA23_TWD_A) | _BV(PA24_TWCK_A));
  229. /* Enable TWI clock. */
  230. outr(PMC_PCER, _BV(TWI_ID));
  231. /* Disable interrupts and reset the interface. */
  232. outr(TWI_IDR, 0xFFFFFFFF);
  233. outr(TWI_CR, TWI_SWRST);
  234. /* Switch to master mode. */
  235. outr(TWI_CR, TWI_MSEN | TWI_SVDIS);
  236. /* Set transfer rate. */
  237. outr(TWI_CWGR, (7 << TWI_CKDIV_LSB) | (128 << TWI_CHDIV_LSB) | (128 << TWI_CLDIV_LSB));
  238. }
  239. /*!
  240. * \brief Write value to an 8-bit power management register.
  241. *
  242. * \param reg PMM register to write to.
  243. * \param val Value to write.
  244. *
  245. * \return 0 on success, -1 otherwise.
  246. */
  247. static int PmmWriteReg(unsigned int reg, unsigned int val)
  248. {
  249. volatile int tmo;
  250. outr(TWI_MMR, 0x22 << TWI_DADR_LSB);
  251. outr(TWI_CR, TWI_START);
  252. outr(TWI_THR, reg);
  253. for (tmo = 0; (inr(TWI_SR) & TWI_TXRDY) == 0; tmo++) {
  254. if (tmo > 100000) {
  255. return -1;
  256. }
  257. }
  258. outr(TWI_CR, TWI_STOP);
  259. outr(TWI_THR, val);
  260. for (tmo = 0; (inr(TWI_SR) & TWI_TXCOMP) == 0; tmo++) {
  261. if (tmo > 100000) {
  262. return -1;
  263. }
  264. }
  265. return 0;
  266. }
  267. #if 0
  268. /* For an unknown reason the system hangs in NutTimer(!) processing
  269. when trying to read the version. Something is somewhere
  270. mysteriously broken. Stack? CPU initialization? Keep this code
  271. for reference. */
  272. static int PmmReadReg(unsigned int reg, unsigned char *val)
  273. {
  274. unsigned long sr;
  275. volatile unsigned int tmo;
  276. outr(TWI_IADRR, reg);
  277. outr(TWI_MMR, 0x22 << TWI_DADR_LSB | TWI_IADRSZ_1BYTE | TWI_MREAD);
  278. outr(TWI_CR, TWI_START | TWI_STOP);
  279. for (tmo = 0; ((sr = inr(TWI_SR)) & TWI_RXRDY) == 0; tmo++) {
  280. if (tmo > 100000) {
  281. return -1;
  282. }
  283. }
  284. if (sr & TWI_NACK) {
  285. return -1;
  286. }
  287. *val = inb(TWI_RHR);
  288. return 0;
  289. }
  290. #endif
  291. /*!
  292. * \brief Ethernet PHY hardware reset.
  293. */
  294. static void PmmPhyReset(void)
  295. {
  296. /* Enable PIO pull-ups at PHY mode strap pins. */
  297. outr(PIOA_ODR, _BV(14) | _BV(15) | _BV(17));
  298. outr(PIOA_PUER, _BV(14) | _BV(15) | _BV(17));
  299. outr(PIOA_PER, _BV(14) | _BV(15) | _BV(17));
  300. /* Enable PIO at PHY address 0 strap pin. */
  301. outr(PIOA_ODR, _BV(18));
  302. outr(PIOA_PUDR, _BV(18));
  303. outr(PIOA_PER, _BV(18));
  304. BootMilliDelay(10);
  305. PmmWriteReg(PWRMAN_REG_ENA, PWRMAN_ETHRST | PWRMAN_ETHCLK);
  306. BootMilliDelay(1);
  307. PmmWriteReg(PWRMAN_REG_DIS, PWRMAN_ETHRST);
  308. BootMilliDelay(10);
  309. }
  310. /*!
  311. * \brief Early Ethernut 5 hardware initialization.
  312. */
  313. void NutBoardInit(void)
  314. {
  315. PmmInit();
  316. PmmPhyReset();
  317. }