diff options
Diffstat (limited to 'cpu/arm920t/at91rm9200')
-rw-r--r-- | cpu/arm920t/at91rm9200/Makefile | 43 | ||||
-rw-r--r-- | cpu/arm920t/at91rm9200/ether.c | 294 | ||||
-rw-r--r-- | cpu/arm920t/at91rm9200/i2c.c | 192 | ||||
-rw-r--r-- | cpu/arm920t/at91rm9200/interrupts.c | 210 | ||||
-rw-r--r-- | cpu/arm920t/at91rm9200/lowlevel_init.S | 200 | ||||
-rw-r--r-- | cpu/arm920t/at91rm9200/serial.c | 115 |
6 files changed, 1054 insertions, 0 deletions
diff --git a/cpu/arm920t/at91rm9200/Makefile b/cpu/arm920t/at91rm9200/Makefile new file mode 100644 index 0000000..0c9bcb2 --- /dev/null +++ b/cpu/arm920t/at91rm9200/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2000-2005 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(SOC).a + +OBJS = ether.o i2c.o interrupts.o serial.o +SOBJS = lowlevel_init.o + +all: .depend $(LIB) + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) $(SOBJS) + +######################################################################### + +.depend: Makefile $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm920t/at91rm9200/ether.c b/cpu/arm920t/at91rm9200/ether.c new file mode 100644 index 0000000..0bc1d89 --- /dev/null +++ b/cpu/arm920t/at91rm9200/ether.c @@ -0,0 +1,294 @@ +/* + * (C) Copyright 2003 + * Author : Hamid Ikdoumi (Atmel) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <at91rm9200_net.h> +#include <net.h> + +/* ----- Ethernet Buffer definitions ----- */ + +typedef struct { + unsigned long addr, size; +} rbf_t; + +#define RBF_ADDR 0xfffffffc +#define RBF_OWNER (1<<0) +#define RBF_WRAP (1<<1) +#define RBF_BROADCAST (1<<31) +#define RBF_MULTICAST (1<<30) +#define RBF_UNICAST (1<<29) +#define RBF_EXTERNAL (1<<28) +#define RBF_UNKOWN (1<<27) +#define RBF_SIZE 0x07ff +#define RBF_LOCAL4 (1<<26) +#define RBF_LOCAL3 (1<<25) +#define RBF_LOCAL2 (1<<24) +#define RBF_LOCAL1 (1<<23) + +/* Emac Buffers in last 512KBytes of SDRAM*/ +/* Be careful, buffer size is limited to 512KBytes !!! */ +#define RBF_FRAMEMAX 100 +/*#define RBF_FRAMEMEM 0x200000 */ +#define RBF_FRAMEMEM 0x21F80000 +#define RBF_FRAMELEN 0x600 + +#define RBF_FRAMEBTD RBF_FRAMEMEM +#define RBF_FRAMEBUF (RBF_FRAMEMEM + RBF_FRAMEMAX*sizeof(rbf_t)) + + +#ifdef CONFIG_DRIVER_ETHER + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +/* structure to interface the PHY */ +AT91S_PhyOps PhyOps; + +AT91PS_EMAC p_mac; + +/*********** EMAC Phy layer Management functions *************************/ +/* + * Name: + * at91rm9200_EmacEnableMDIO + * Description: + * Enables the MDIO bit in MAC control register + * Arguments: + * p_mac - pointer to struct AT91S_EMAC + * Return value: + * none + */ +void at91rm9200_EmacEnableMDIO (AT91PS_EMAC p_mac) +{ + /* Mac CTRL reg set for MDIO enable */ + p_mac->EMAC_CTL |= AT91C_EMAC_MPE; /* Management port enable */ +} + +/* + * Name: + * at91rm9200_EmacDisableMDIO + * Description: + * Disables the MDIO bit in MAC control register + * Arguments: + * p_mac - pointer to struct AT91S_EMAC + * Return value: + * none + */ +void at91rm9200_EmacDisableMDIO (AT91PS_EMAC p_mac) +{ + /* Mac CTRL reg set for MDIO disable */ + p_mac->EMAC_CTL &= ~AT91C_EMAC_MPE; /* Management port disable */ +} + + +/* + * Name: + * at91rm9200_EmacReadPhy + * Description: + * Reads data from the PHY register + * Arguments: + * dev - pointer to struct net_device + * RegisterAddress - unsigned char + * pInput - pointer to value read from register + * Return value: + * TRUE - if data read successfully + */ +UCHAR at91rm9200_EmacReadPhy (AT91PS_EMAC p_mac, + unsigned char RegisterAddress, + unsigned short *pInput) +{ + p_mac->EMAC_MAN = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) | + (AT91C_EMAC_RW_R) | + (RegisterAddress << 18) | + (AT91C_EMAC_CODE_802_3); + + udelay (10000); + + *pInput = (unsigned short) p_mac->EMAC_MAN; + + return TRUE; +} + + +/* + * Name: + * at91rm9200_EmacWritePhy + * Description: + * Writes data to the PHY register + * Arguments: + * dev - pointer to struct net_device + * RegisterAddress - unsigned char + * pOutput - pointer to value to be written in the register + * Return value: + * TRUE - if data read successfully + */ +UCHAR at91rm9200_EmacWritePhy (AT91PS_EMAC p_mac, + unsigned char RegisterAddress, + unsigned short *pOutput) +{ + p_mac->EMAC_MAN = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) | + AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W | + (RegisterAddress << 18) | *pOutput; + + udelay (10000); + + return TRUE; +} + + +rbf_t *rbfdt; +rbf_t *rbfp; + +int eth_init (bd_t * bd) +{ + int ret; + int i; + + p_mac = AT91C_BASE_EMAC; + + /* PIO Disable Register */ + *AT91C_PIOA_PDR = AT91C_PA16_EMDIO | AT91C_PA15_EMDC | AT91C_PA14_ERXER | + AT91C_PA13_ERX1 | AT91C_PA12_ERX0 | AT91C_PA11_ECRS_ECRSDV | + AT91C_PA10_ETX1 | AT91C_PA9_ETX0 | AT91C_PA8_ETXEN | + AT91C_PA7_ETXCK_EREFCK; + +#ifdef CONFIG_AT91C_USE_RMII + *AT91C_PIOB_PDR = AT91C_PB19_ERXCK; + *AT91C_PIOB_BSR = AT91C_PB19_ERXCK; +#else + *AT91C_PIOB_PDR = AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV | + AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | AT91C_PB14_ETXER | + AT91C_PB13_ETX3 | AT91C_PB12_ETX2; + + /* Select B Register */ + *AT91C_PIOB_BSR = AT91C_PB19_ERXCK | AT91C_PB18_ECOL | + AT91C_PB17_ERXDV | AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | + AT91C_PB14_ETXER | AT91C_PB13_ETX3 | AT91C_PB12_ETX2; +#endif + + *AT91C_PMC_PCER = 1 << AT91C_ID_EMAC; /* Peripheral Clock Enable Register */ + + p_mac->EMAC_CFG |= AT91C_EMAC_CSR; /* Clear statistics */ + + /* Init Ehternet buffers */ + rbfdt = (rbf_t *) RBF_FRAMEBTD; + for (i = 0; i < RBF_FRAMEMAX; i++) { + rbfdt[i].addr = RBF_FRAMEBUF + RBF_FRAMELEN * i; + rbfdt[i].size = 0; + } + rbfdt[RBF_FRAMEMAX - 1].addr |= RBF_WRAP; + rbfp = &rbfdt[0]; + + p_mac->EMAC_SA2L = (bd->bi_enetaddr[3] << 24) | (bd->bi_enetaddr[2] << 16) + | (bd->bi_enetaddr[1] << 8) | (bd->bi_enetaddr[0]); + p_mac->EMAC_SA2H = (bd->bi_enetaddr[5] << 8) | (bd->bi_enetaddr[4]); + + p_mac->EMAC_RBQP = (long) (&rbfdt[0]); + p_mac->EMAC_RSR &= ~(AT91C_EMAC_RSR_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA); + + p_mac->EMAC_CFG = (p_mac->EMAC_CFG | AT91C_EMAC_CAF | AT91C_EMAC_NBC) + & ~AT91C_EMAC_CLK; + +#ifdef CONFIG_AT91C_USE_RMII + p_mac->EMAC_CFG |= AT91C_EMAC_RMII; +#endif + +#if (AT91C_MASTER_CLOCK > 40000000) + /* MDIO clock must not exceed 2.5 MHz, so enable MCK divider */ + p_mac->EMAC_CFG |= AT91C_EMAC_CLK_HCLK_64; +#endif + + p_mac->EMAC_CTL |= AT91C_EMAC_TE | AT91C_EMAC_RE; + + at91rm92000_GetPhyInterface (& PhyOps); + + if (!PhyOps.IsPhyConnected (p_mac)) + printf ("PHY not connected!!\n\r"); + + /* MII management start from here */ + if (!(p_mac->EMAC_SR & AT91C_EMAC_LINK)) { + if (!(ret = PhyOps.Init (p_mac))) { + printf ("MAC: error during MII initialization\n"); + return 0; + } + } else { + printf ("No link\n\r"); + return 0; + } + + return 0; +} + +int eth_send (volatile void *packet, int length) +{ + while (!(p_mac->EMAC_TSR & AT91C_EMAC_BNQ)); + p_mac->EMAC_TAR = (long) packet; + p_mac->EMAC_TCR = length; + while (p_mac->EMAC_TCR & 0x7ff); + p_mac->EMAC_TSR |= AT91C_EMAC_COMP; + return 0; +} + +int eth_rx (void) +{ + int size; + + if (!(rbfp->addr & RBF_OWNER)) + return 0; + + size = rbfp->size & RBF_SIZE; + NetReceive ((volatile uchar *) (rbfp->addr & RBF_ADDR), size); + + rbfp->addr &= ~RBF_OWNER; + if (rbfp->addr & RBF_WRAP) + rbfp = &rbfdt[0]; + else + rbfp++; + + p_mac->EMAC_RSR |= AT91C_EMAC_REC; + + return size; +} + +void eth_halt (void) +{ +}; + +#if (CONFIG_COMMANDS & CFG_CMD_MII) +int miiphy_read(unsigned char addr, unsigned char reg, unsigned short * value) +{ + at91rm9200_EmacEnableMDIO (p_mac); + at91rm9200_EmacReadPhy (p_mac, reg, value); + at91rm9200_EmacDisableMDIO (p_mac); + return 0; +} + +int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value) +{ + at91rm9200_EmacEnableMDIO (p_mac); + at91rm9200_EmacWritePhy (p_mac, reg, &value); + at91rm9200_EmacDisableMDIO (p_mac); + return 0; +} +#endif /* CONFIG_COMMANDS & CFG_CMD_MII */ + +#endif /* CONFIG_COMMANDS & CFG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ diff --git a/cpu/arm920t/at91rm9200/i2c.c b/cpu/arm920t/at91rm9200/i2c.c new file mode 100644 index 0000000..433dd32 --- /dev/null +++ b/cpu/arm920t/at91rm9200/i2c.c @@ -0,0 +1,192 @@ +/* + * i2c Support for Atmel's AT91RM9200 Two-Wire Interface + * + * (c) Rick Bronson + * + * Borrowed heavily from original work by: + * Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> + * + * Modified to work with u-boot by (C) 2004 Gary Jennejohn garyj@denx.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * +*/ +#include <common.h> + +#ifdef CONFIG_HARD_I2C + +#include <i2c.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> + +#include <at91rm9200_i2c.h> + +/* define DEBUG */ + +/* + * Poll the i2c status register until the specified bit is set. + * Returns 0 if timed out (100 msec) + */ +static short at91_poll_status(AT91PS_TWI twi, unsigned long bit) { + int loop_cntr = 10000; + do { + udelay(10); + } while (!(twi->TWI_SR & bit) && (--loop_cntr > 0)); + + return (loop_cntr > 0); +} + +/* + * Generic i2c master transfer entrypoint + * + * rw == 1 means that this is a read + */ +static int +at91_xfer(unsigned char chip, unsigned int addr, int alen, + unsigned char *buffer, int len, int rw) +{ + AT91PS_TWI twi = (AT91PS_TWI) AT91_TWI_BASE; + int length; + unsigned char *buf; + /* Set the TWI Master Mode Register */ + twi->TWI_MMR = (chip << 16) | (alen << 8) + | ((rw == 1) ? AT91C_TWI_MREAD : 0); + + /* Set TWI Internal Address Register with first messages data field */ + /* only one address byte is supported */ + if (alen > 0) + twi->TWI_IADR = addr & 0xff; + + length = len; + buf = buffer; + if (length && buf) { /* sanity check */ + if (rw) { + twi->TWI_CR = AT91C_TWI_START; + while (length--) { + if (!length) + twi->TWI_CR = AT91C_TWI_STOP; + /* Wait until transfer is finished */ + if (!at91_poll_status(twi, AT91C_TWI_RXRDY)) { + debug ("at91_i2c: timeout 1\n"); + return 1; + } + *buf++ = twi->TWI_RHR; + } + if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) { + debug ("at91_i2c: timeout 2\n"); + return 1; + } + } else { + twi->TWI_CR = AT91C_TWI_START; + while (length--) { + twi->TWI_THR = *buf++; + if (!length) + twi->TWI_CR = AT91C_TWI_STOP; + if (!at91_poll_status(twi, AT91C_TWI_TXRDY)) { + debug ("at91_i2c: timeout 3\n"); + return 1; + } + } + /* Wait until transfer is finished */ + if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) { + debug ("at91_i2c: timeout 4\n"); + return 1; + } + } + } + return 0; +} + +int +i2c_probe(unsigned char chip) +{ + char buffer[1]; + + return at91_xfer(chip, 0, 0, buffer, 1, 1); +} + +int +i2c_read (unsigned char chip, unsigned int addr, int alen, + unsigned char *buffer, int len) +{ +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW + /* we only allow one address byte */ + if (alen > 1) + return 1; + /* XXX assume an ATMEL AT24C16 */ + if (alen == 1) { +#if 0 /* EEPROM code already sets this correctly */ + chip |= (addr >> 8) & 0xff; +#endif + addr = addr & 0xff; + } +#endif + return at91_xfer(chip, addr, alen, buffer, len, 1); +} + +int +i2c_write(unsigned char chip, unsigned int addr, int alen, + unsigned char *buffer, int len) +{ + int i; + unsigned char *buf; + +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW + /* we only allow one address byte */ + if (alen > 1) + return 1; + /* XXX assume an ATMEL AT24C16 */ + if (alen == 1) { + buf = buffer; + /* do single byte writes */ + for (i = 0; i < len; i++) { +#if 0 /* EEPROM code already sets this correctly */ + chip |= (addr >> 8) & 0xff; +#endif + addr = addr & 0xff; + if (at91_xfer(chip, addr, alen, buf++, 1, 0)) + return 1; + addr++; + } + return 0; + } +#endif + return at91_xfer(chip, addr, alen, buffer, len, 0); +} + +/* + * Main initialization routine + */ +void +i2c_init(int speed, int slaveaddr) +{ + AT91PS_TWI twi = (AT91PS_TWI) AT91_TWI_BASE; + + *AT91C_PIOA_PDR = AT91C_PA25_TWD | AT91C_PA26_TWCK; + *AT91C_PIOA_ASR = AT91C_PA25_TWD | AT91C_PA26_TWCK; + *AT91C_PIOA_MDER = AT91C_PA25_TWD | AT91C_PA26_TWCK; + *AT91C_PMC_PCER = 1 << AT91C_ID_TWI; /* enable peripheral clock */ + + twi->TWI_IDR = 0x3ff; /* Disable all interrupts */ + twi->TWI_CR = AT91C_TWI_SWRST; /* Reset peripheral */ + twi->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS; /* Set Master mode */ + + /* Here, CKDIV = 1 and CHDIV=CLDIV ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6) */ + twi->TWI_CWGR = AT91C_TWI_CKDIV1 | AT91C_TWI_CLDIV3 | (AT91C_TWI_CLDIV3 << 8); + + debug ("Found AT91 i2c\n"); + return; +} +#endif /* CONFIG_HARD_I2C */ diff --git a/cpu/arm920t/at91rm9200/interrupts.c b/cpu/arm920t/at91rm9200/interrupts.c new file mode 100644 index 0000000..1054602 --- /dev/null +++ b/cpu/arm920t/at91rm9200/interrupts.c @@ -0,0 +1,210 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc. <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +/*#include <asm/io.h>*/ +#include <asm/arch/hardware.h> +/*#include <asm/proc/ptrace.h>*/ + +/* the number of clocks per CFG_HZ */ +#define TIMER_LOAD_VAL (CFG_HZ_CLOCK/CFG_HZ) + +/* macro to read the 16 bit timer */ +#define READ_TIMER (tmr->TC_CV & 0x0000ffff) +AT91PS_TC tmr; + +static ulong timestamp; +static ulong lastinc; + +int interrupt_init (void) +{ + tmr = AT91C_BASE_TC0; + + /* enables TC1.0 clock */ + *AT91C_PMC_PCER = 1 << AT91C_ID_TC0; /* enable clock */ + + *AT91C_TCB0_BCR = 0; + *AT91C_TCB0_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_NONE | AT91C_TCB_TC2XC2S_NONE; + tmr->TC_CCR = AT91C_TC_CLKDIS; +#define AT91C_TC_CMR_CPCTRG (1 << 14) + /* set to MCLK/2 and restart the timer when the vlaue in TC_RC is reached */ + tmr->TC_CMR = AT91C_TC_TIMER_DIV1_CLOCK | AT91C_TC_CMR_CPCTRG; + + tmr->TC_IDR = ~0ul; + tmr->TC_RC = TIMER_LOAD_VAL; + lastinc = 0; + tmr->TC_CCR = AT91C_TC_SWTRG | AT91C_TC_CLKEN; + timestamp = 0; + + return (0); +} + +/* + * timer without interrupts + */ + +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base) +{ + return get_timer_masked () - base; +} + +void set_timer (ulong t) +{ + timestamp = t; +} + +void udelay (unsigned long usec) +{ + udelay_masked(usec); +} + +void reset_timer_masked (void) +{ + /* reset time */ + lastinc = READ_TIMER; + timestamp = 0; +} + +ulong get_timer_raw (void) +{ + ulong now = READ_TIMER; + + if (now >= lastinc) { + /* normal mode */ + timestamp += now - lastinc; + } else { + /* we have an overflow ... */ + timestamp += now + TIMER_LOAD_VAL - lastinc; + } + lastinc = now; + + return timestamp; +} + +ulong get_timer_masked (void) +{ + return get_timer_raw()/TIMER_LOAD_VAL; +} + +void udelay_masked (unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + tmo = CFG_HZ_CLOCK / 1000; + tmo *= usec; + tmo /= 1000; + + endtime = get_timer_raw () + tmo; + + do { + ulong now = get_timer_raw (); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + ulong tbclk; + + tbclk = CFG_HZ; + return tbclk; +} + +/* + * Reset the cpu by setting up the watchdog timer and let him time out + * or toggle a GPIO pin on the AT91RM9200DK board + */ +void reset_cpu (ulong ignored) +{ + +#ifdef CONFIG_DBGU + AT91PS_USART us = (AT91PS_USART) AT91C_BASE_DBGU; +#endif +#ifdef CONFIG_USART0 + AT91PS_USART us = AT91C_BASE_US0; +#endif +#ifdef CONFIG_USART1 + AT91PS_USART us = AT91C_BASE_US1; +#endif +#ifdef CONFIG_AT91RM9200DK + AT91PS_PIO pio = AT91C_BASE_PIOA; +#endif + + /*shutdown the console to avoid strange chars during reset */ + us->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX); + +#ifdef CONFIG_AT91RM9200DK + /* Clear PA19 to trigger the hard reset */ + pio->PIO_CODR = 0x00080000; + pio->PIO_OER = 0x00080000; + pio->PIO_PER = 0x00080000; +#endif + + /* this is the way Linux does it */ + + /* FIXME: + * These defines should be moved into + * include/asm-arm/arch-at91rm9200/AT91RM9200.h + * as soon as the whitespace fix gets applied. + */ + #define AT91C_ST_RSTEN (0x1 << 16) + #define AT91C_ST_EXTEN (0x1 << 17) + #define AT91C_ST_WDRST (0x1 << 0) + #define ST_WDMR *((unsigned long *)0xfffffd08) /* watchdog mode register */ + #define ST_CR *((unsigned long *)0xfffffd00) /* system clock control register */ + + ST_WDMR = AT91C_ST_RSTEN | AT91C_ST_EXTEN | 1 ; + ST_CR = AT91C_ST_WDRST; + + while (1); + /* Never reached */ +} diff --git a/cpu/arm920t/at91rm9200/lowlevel_init.S b/cpu/arm920t/at91rm9200/lowlevel_init.S new file mode 100644 index 0000000..05887ad --- /dev/null +++ b/cpu/arm920t/at91rm9200/lowlevel_init.S @@ -0,0 +1,200 @@ +/* + * Memory Setup stuff - taken from blob memsetup.S + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * Modified for the at91rm9200dk board by + * (C) Copyright 2004 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <version.h> + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +/* + * some parameters for the board + * + * This is based on rm9200dk.cfg for the BDI2000 from ABATRON which in + * turn is based on the boot.bin code from ATMEL + * + */ + +/* flash */ +#define MC_PUIA 0xFFFFFF10 +#define MC_PUP 0xFFFFFF50 +#define MC_PUER 0xFFFFFF54 +#define MC_ASR 0xFFFFFF04 +#define MC_AASR 0xFFFFFF08 +#define EBI_CFGR 0xFFFFFF64 +#define SMC2_CSR 0xFFFFFF70 + +/* clocks */ +#define PLLAR 0xFFFFFC28 +#define PLLBR 0xFFFFFC2C +#define MCKR 0xFFFFFC30 + +#define AT91C_BASE_CKGR 0xFFFFFC20 +#define CKGR_MOR 0 + +/* sdram */ +#define PIOC_ASR 0xFFFFF870 +#define PIOC_BSR 0xFFFFF874 +#define PIOC_PDR 0xFFFFF804 +#define EBI_CSA 0xFFFFFF60 +#define SDRC_CR 0xFFFFFF98 +#define SDRC_MR 0xFFFFFF90 +#define SDRC_TR 0xFFFFFF94 + + +_MTEXT_BASE: +#undef START_FROM_MEM +#ifdef START_FROM_MEM + .word TEXT_BASE-PHYS_FLASH_1 +#else + .word TEXT_BASE +#endif + +.globl lowlevel_init +lowlevel_init: + /* Get the CKGR Base Address */ + ldr r1, =AT91C_BASE_CKGR + /* Main oscillator Enable register */ +#ifdef CFG_USE_MAIN_OSCILLATOR + ldr r0, =0x0000FF01 /* Enable main oscillator, OSCOUNT = 0xFF */ +#else + ldr r0, =0x0000FF00 /* Disable main oscillator, OSCOUNT = 0xFF */ +#endif + str r0, [r1, #CKGR_MOR] + /* Add loop to compensate Main Oscillator startup time */ + ldr r0, =0x00000010 +LoopOsc: + subs r0, r0, #1 + bhi LoopOsc + + /* memory control configuration */ + /* this isn't very elegant, but what the heck */ + ldr r0, =SMRDATA + ldr r1, _MTEXT_BASE + sub r0, r0, r1 + add r2, r0, #80 +0: + /* the address */ + ldr r1, [r0], #4 + /* the value */ + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne 0b + /* delay - this is all done by guess */ + ldr r0, =0x00010000 +1: + subs r0, r0, #1 + bhi 1b + ldr r0, =SMRDATA1 + ldr r1, _MTEXT_BASE + sub r0, r0, r1 + add r2, r0, #176 +2: + /* the address */ + ldr r1, [r0], #4 + /* the value */ + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne 2b + + /* everything is fine now */ + mov pc, lr + + .ltorg + +SMRDATA: + .word MC_PUIA + .word MC_PUIA_VAL + .word MC_PUP + .word MC_PUP_VAL + .word MC_PUER + .word MC_PUER_VAL + .word MC_ASR + .word MC_ASR_VAL + .word MC_AASR + .word MC_AASR_VAL + .word EBI_CFGR + .word EBI_CFGR_VAL + .word SMC2_CSR + .word SMC2_CSR_VAL + .word PLLAR + .word PLLAR_VAL + .word PLLBR + .word PLLBR_VAL + .word MCKR + .word MCKR_VAL + /* SMRDATA is 80 bytes long */ + /* here there's a delay of 100 */ +SMRDATA1: + .word PIOC_ASR + .word PIOC_ASR_VAL + .word PIOC_BSR + .word PIOC_BSR_VAL + .word PIOC_PDR + .word PIOC_PDR_VAL + .word EBI_CSA + .word EBI_CSA_VAL + .word SDRC_CR + .word SDRC_CR_VAL + .word SDRC_MR + .word SDRC_MR_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRC_MR + .word SDRC_MR_VAL1 + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRC_MR + .word SDRC_MR_VAL2 + .word SDRAM1 + .word SDRAM_VAL + .word SDRC_TR + .word SDRC_TR_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRC_MR + .word SDRC_MR_VAL3 + .word SDRAM + .word SDRAM_VAL + /* SMRDATA1 is 176 bytes long */ +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ diff --git a/cpu/arm920t/at91rm9200/serial.c b/cpu/arm920t/at91rm9200/serial.c new file mode 100644 index 0000000..a9693bf --- /dev/null +++ b/cpu/arm920t/at91rm9200/serial.c @@ -0,0 +1,115 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> + +#if !defined(CONFIG_DBGU) && !defined(CONFIG_USART0) && !defined(CONFIG_USART1) +#error must define one of CONFIG_DBGU or CONFIG_USART0 or CONFIG_USART1 +#endif + +/* ggi thunder */ +#ifdef CONFIG_DBGU +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_DBGU; +#endif +#ifdef CONFIG_USART0 +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_US0; +#endif +#ifdef CONFIG_USART1 +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_US1; +#endif + +void serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + int baudrate; + + if ((baudrate = gd->baudrate) <= 0) + baudrate = CONFIG_BAUDRATE; + if (baudrate == 0 || baudrate == CONFIG_BAUDRATE) + us->US_BRGR = CFG_AT91C_BRGR_DIVISOR; /* hardcode so no __divsi3 */ + else + /* MASTER_CLOCK/(16 * baudrate) */ + us->US_BRGR = (AT91C_MASTER_CLOCK >> 4)/baudrate; +} + +int serial_init (void) +{ + /* make any port initializations specific to this port */ +#ifdef CONFIG_DBGU + *AT91C_PIOA_PDR = AT91C_PA31_DTXD | AT91C_PA30_DRXD; /* PA 31 & 30 */ + *AT91C_PMC_PCER = 1 << AT91C_ID_SYS; /* enable clock */ +#endif +#ifdef CONFIG_USART0 + *AT91C_PIOA_PDR = AT91C_PA17_TXD0 | AT91C_PA18_RXD0; + *AT91C_PMC_PCER |= 1 << AT91C_ID_USART0; /* enable clock */ +#endif +#ifdef CONFIG_USART1 + *AT91C_PIOB_PDR = AT91C_PB21_TXD1 | AT91C_PB20_RXD1; + *AT91C_PMC_PCER |= 1 << AT91C_ID_USART1; /* enable clock */ +#endif + serial_setbrg (); + + us->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX; + us->US_CR = AT91C_US_RXEN | AT91C_US_TXEN; + us->US_MR = + (AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS | + AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT); + us->US_IMR = ~0ul; + return (0); +} + +void serial_putc (const char c) +{ + if (c == '\n') + serial_putc ('\r'); + while ((us->US_CSR & AT91C_US_TXRDY) == 0); + us->US_THR = c; +} + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +int serial_getc (void) +{ + while ((us->US_CSR & AT91C_US_RXRDY) == 0); + return us->US_RHR; +} + +int serial_tstc (void) +{ + return ((us->US_CSR & AT91C_US_RXRDY) == AT91C_US_RXRDY); +} |