| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- /*
- * Copyright 2010-2012 by egnite GmbH
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * For additional information see http://www.ethernut.de/
- */
- /*
- * \file arch/arm/board/ethernut5.c
- * \brief Ethernut 5 board initialization.
- *
- * \verbatim
- * $Id$
- * \endverbatim
- */
- #include <toolchain.h>
- #ifndef PMM_RST_BASE
- /* Power management reset port. */
- #define PMM_RST_BASE PIOB_BASE
- #endif
- #ifndef PMM_RST_PIN
- /* Power management reset pin. */
- #define PMM_RST_PIN 8
- #endif
- /*! \name Power Management Registers */
- /*@{*/
- /*! \brief Version register. */
- #define PWRMAN_REG_VERS 0
- /*! \brief Feature status register. */
- #define PWRMAN_REG_STA 1
- /*! \brief Feature enable register. */
- #define PWRMAN_REG_ENA 2
- /*! \brief Feature disable register. */
- #define PWRMAN_REG_DIS 3
- /*! \brief Board temperature register. */
- #define PWRMAN_REG_TEMP 4
- /*! \brief Auxiliary input voltage register. */
- #define PWRMAN_REG_VAUX 6
- /*! \brief LED blinking timer register. */
- #define PWRMAN_REG_LEDCTL 8
- /*@}*/
- /* \name Feature flags */
- /*@{*/
- /*! \brief 1.8V and 3.3V supply. */
- #define PWRMAN_BOARD 0x01
- /*! \brief VBUS input at device connector. */
- #define PWRMAN_VBIN 0x02
- /*! \brief VBUS output at host connector. */
- #define PWRMAN_VBOUT 0x04
- /*! \brief Memory card supply. */
- #define PWRMAN_MMC 0x08
- /*! \brief RS-232 driver shutdown. */
- #define PWRMAN_RS232 0x10
- /*! \brief Ethernet clock enable. */
- #define PWRMAN_ETHCLK 0x20
- /*! \brief Ethernet PHY reset. */
- #define PWRMAN_ETHRST 0x40
- /*! \brief RTC wake-up. */
- #define PWRMAN_WAKEUP 0x80
- /*@}*/
- #define ARM_TTD_DOM_LSB 5
- #define ARM_TTD_DOM(x) ((x) << ARM_TTD_DOM_LSB)
- #define ARM_TTD_AP_PN_UN 0x000
- #define ARM_TTD_AP_PW_UN 0x400
- #define ARM_TTD_AP_PW_UR 0x800
- #define ARM_TTD_AP_PW_UW 0xC00
- #define ARM_TTD_INVALID 0x0
- #define ARM_TTD_COARSE_PAGE 0x1
- #define ARM_TTD_SECTION 0x12
- #define ARM_TTD_FINE_PAGE 0x3
- /* Noncacheable, nonbufferable */
- #define ARM_TTD_NC_NB 0x0
- /* Noncacheable, bufferable */
- #define ARM_TTD_NC_B 0x4
- /* Cacheable, write-through */
- #define ARM_TTD_C_WT 0x8
- /* Cacheable, write-back */
- #define ARM_TTD_C_WB 0xC
- #define ARM_SET_CP15_TTBR(val) __asm__ __volatile__("mcr p15, 0, %0, c2, c0, 0" :: "r"(val) : "cc")
- #define ARM_SET_CP15_DACR(val) __asm__ __volatile__("mcr p15, 0, %0, c3, c0, 0" :: "r"(val) : "cc")
- void __set_stacks(void) NUT_NAKED_FUNC;
- void __init2(void) NUT_NAKED_FUNC NUT_LINKER_SECT(".init2.user");
- void __init2(void)
- {
- /*
- * The watchdog is enabled after processor reset.
- */
- #if defined(NUT_WDT_START)
- #if NUT_WDT_START
- /* Configure the watchdog. */
- outr(WDT_MR, NUT_WDT_START);
- #else
- /* Disable the watchdog. */
- outr(WDT_MR, WDT_WDDIS);
- #endif
- #endif
- /*
- * Enable external reset key.
- */
- outr(RSTC_MR, RSTC_KEY | RSTC_URSTEN);
- /* Continue with runtime initialization. */
- __set_stacks();
- }
- void __clear_bss(void) NUT_NAKED_FUNC;
- void __init3(void) NUT_NAKED_FUNC NUT_LINKER_SECT(".init3.user");
- void __init3(void)
- {
- /* Enable instruction cache. */
- ARM_SET_CP15_CR(ARM_GET_CP15_CR() | (1 << 12));
- /* Continue with runtime initialization. */
- __clear_bss();
- }
- void __call_rtos(void) NUT_NAKED_FUNC;
- void __init4(void) NUT_NAKED_FUNC NUT_LINKER_SECT(".init4.user");
- void __init4(void)
- {
- static unsigned int *ttb = (unsigned int *) 0x20000000;
- static const unsigned int dom = 0xC0000000;
- static unsigned int i;
- /* Set translation table base. */
- ARM_SET_CP15_TTBR((unsigned int) ttb);
- /* Do not check access permissions for domain 15. */
- ARM_SET_CP15_DACR(dom);
- for(i = 0; i < 4096; i++) {
- ttb[i] = 0;
- }
- /* Set mapped internal SRAM section mapping. */
- ttb[0x000] = 0x00000000 | ARM_TTD_AP_PW_UN | ARM_TTD_DOM(15) | ARM_TTD_C_WB | ARM_TTD_SECTION;
- /* Set Flash memory section mapping. */
- ttb[0x002] = 0x00200000 | ARM_TTD_AP_PW_UN | ARM_TTD_DOM(15) | ARM_TTD_C_WT | ARM_TTD_SECTION;
- for(i = 0; i < 128; i++) {
- ttb[0x200 + i] = (0x20000000 + (i << 20)) | ARM_TTD_AP_PW_UN | ARM_TTD_DOM(15) | ARM_TTD_C_WB | ARM_TTD_SECTION;
- }
- /* Set external NAND Flash mapping. */
- for(i = 0; i < 256; i++) {
- ttb[0x400 + i] = (0x40000000 + (i << 20)) | ARM_TTD_AP_PW_UN | ARM_TTD_DOM(15) | ARM_TTD_SECTION;
- }
- /* Set peripheral register mapping. */
- ttb[0xFFF] = 0xFFF00000 | ARM_TTD_AP_PW_UN | ARM_TTD_DOM(15) | ARM_TTD_SECTION;
- /* Finally enable the MMU and the data cache. */
- ARM_SET_CP15_CR(ARM_GET_CP15_CR() | (1 << 12) | (1 << 2));
- /* Continue with runtime initialization. */
- __call_rtos();
- }
- /*!
- * \brief Delay loop.
- *
- * Delay by executing a given number of loops, roughly 5ns each.
- *
- * \param n Number of microseconds.
- */
- static void BootLoopDelay(int n)
- {
- while (n--) {
- _NOP();
- }
- }
- /*!
- * \brief Microsecond delay.
- *
- * \param us Number of microseconds.
- */
- static void BootMicroDelay(int us)
- {
- while (us--) {
- BootLoopDelay(200);
- }
- }
- /*!
- * \brief Millisecond delay.
- *
- * We are running prior to Nut/OS timer initialization and cannot use
- * NutSleep, not even NutDelay.
- *
- * \param ms Number of milliseconds.
- */
- static void BootMilliDelay(int ms)
- {
- while (ms--) {
- BootMicroDelay(1000);
- }
- }
- /*!
- * \brief Initialize the power management interface.
- */
- static void PmmInit(void)
- {
- #if defined(PMM_RST_BASE) && defined(PMM_RST_PIN)
- /* Activate the power management reset pin. */
- outr(PMM_RST_BASE + PIO_SODR_OFF, _BV(PMM_RST_PIN));
- outr(PMM_RST_BASE + PIO_PER_OFF, _BV(PMM_RST_PIN));
- outr(PMM_RST_BASE + PIO_OER_OFF, _BV(PMM_RST_PIN));
- BootMilliDelay(1);
- /* Deactivate the reset. */
- outr(PMM_RST_BASE + PIO_CODR_OFF, _BV(PMM_RST_PIN));
- BootMilliDelay(100);
- #endif
- /* Set peripheral lines for TWD and TWCK. */
- outr(PIOA_ASR, _BV(PA23_TWD_A) | _BV(PA24_TWCK_A));
- outr(PIOA_PDR, _BV(PA23_TWD_A) | _BV(PA24_TWCK_A));
- /* Switch TWI lines to open drain. */
- outr(PIOA_MDER, _BV(PA23_TWD_A) | _BV(PA24_TWCK_A));
- /* Enable TWI clock. */
- outr(PMC_PCER, _BV(TWI_ID));
- /* Disable interrupts and reset the interface. */
- outr(TWI_IDR, 0xFFFFFFFF);
- outr(TWI_CR, TWI_SWRST);
- /* Switch to master mode. */
- outr(TWI_CR, TWI_MSEN | TWI_SVDIS);
- /* Set transfer rate. */
- outr(TWI_CWGR, (7 << TWI_CKDIV_LSB) | (128 << TWI_CHDIV_LSB) | (128 << TWI_CLDIV_LSB));
- }
- /*!
- * \brief Write value to an 8-bit power management register.
- *
- * \param reg PMM register to write to.
- * \param val Value to write.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int PmmWriteReg(unsigned int reg, unsigned int val)
- {
- volatile int tmo;
- outr(TWI_MMR, 0x22 << TWI_DADR_LSB);
- outr(TWI_CR, TWI_START);
- outr(TWI_THR, reg);
- for (tmo = 0; (inr(TWI_SR) & TWI_TXRDY) == 0; tmo++) {
- if (tmo > 100000) {
- return -1;
- }
- }
- outr(TWI_CR, TWI_STOP);
- outr(TWI_THR, val);
- for (tmo = 0; (inr(TWI_SR) & TWI_TXCOMP) == 0; tmo++) {
- if (tmo > 100000) {
- return -1;
- }
- }
- return 0;
- }
- #if 0
- /* For an unknown reason the system hangs in NutTimer(!) processing
- when trying to read the version. Something is somewhere
- mysteriously broken. Stack? CPU initialization? Keep this code
- for reference. */
- static int PmmReadReg(unsigned int reg, unsigned char *val)
- {
- unsigned long sr;
- volatile unsigned int tmo;
- outr(TWI_IADRR, reg);
- outr(TWI_MMR, 0x22 << TWI_DADR_LSB | TWI_IADRSZ_1BYTE | TWI_MREAD);
- outr(TWI_CR, TWI_START | TWI_STOP);
- for (tmo = 0; ((sr = inr(TWI_SR)) & TWI_RXRDY) == 0; tmo++) {
- if (tmo > 100000) {
- return -1;
- }
- }
- if (sr & TWI_NACK) {
- return -1;
- }
- *val = inb(TWI_RHR);
- return 0;
- }
- #endif
- /*!
- * \brief Ethernet PHY hardware reset.
- */
- static void PmmPhyReset(void)
- {
- /* Enable PIO pull-ups at PHY mode strap pins. */
- outr(PIOA_ODR, _BV(14) | _BV(15) | _BV(17));
- outr(PIOA_PUER, _BV(14) | _BV(15) | _BV(17));
- outr(PIOA_PER, _BV(14) | _BV(15) | _BV(17));
- /* Enable PIO at PHY address 0 strap pin. */
- outr(PIOA_ODR, _BV(18));
- outr(PIOA_PUDR, _BV(18));
- outr(PIOA_PER, _BV(18));
- BootMilliDelay(10);
- PmmWriteReg(PWRMAN_REG_ENA, PWRMAN_ETHRST | PWRMAN_ETHCLK);
- BootMilliDelay(1);
- PmmWriteReg(PWRMAN_REG_DIS, PWRMAN_ETHRST);
- BootMilliDelay(10);
- }
- /*!
- * \brief Early Ethernut 5 hardware initialization.
- */
- void NutBoardInit(void)
- {
- PmmInit();
- PmmPhyReset();
- }
|