diff options
Diffstat (limited to 'cpu/mcf52x2')
-rwxr-xr-x | cpu/mcf52x2/Makefile | 45 | ||||
-rwxr-xr-x | cpu/mcf52x2/config.mk | 27 | ||||
-rwxr-xr-x | cpu/mcf52x2/cpu.c | 146 | ||||
-rwxr-xr-x | cpu/mcf52x2/cpu_init.c | 252 | ||||
-rwxr-xr-x | cpu/mcf52x2/fec.c | 569 | ||||
-rwxr-xr-x | cpu/mcf52x2/interrupts.c | 188 | ||||
-rwxr-xr-x | cpu/mcf52x2/serial.c | 167 | ||||
-rwxr-xr-x | cpu/mcf52x2/speed.c | 41 | ||||
-rwxr-xr-x | cpu/mcf52x2/start.S | 345 |
9 files changed, 1780 insertions, 0 deletions
diff --git a/cpu/mcf52x2/Makefile b/cpu/mcf52x2/Makefile new file mode 100755 index 0000000..879deb7 --- /dev/null +++ b/cpu/mcf52x2/Makefile @@ -0,0 +1,45 @@ +# +# (C) Copyright 2000-2004 +# 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 + +# CFLAGS += -DET_DEBUG + +LIB = lib$(CPU).a + +START = +OBJS = serial.o interrupts.o cpu.o speed.o cpu_init.o fec.o + +all: .depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/mcf52x2/config.mk b/cpu/mcf52x2/config.mk new file mode 100755 index 0000000..650db85 --- /dev/null +++ b/cpu/mcf52x2/config.mk @@ -0,0 +1,27 @@ +# +# (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de> +# +# (C) Copyright 2000-2004 +# 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 +# + +PLATFORM_RELFLAGS += -ffixed-d7 -msep-data +PLATFORM_CPPFLAGS += -m5307 diff --git a/cpu/mcf52x2/cpu.c b/cpu/mcf52x2/cpu.c new file mode 100755 index 0000000..32a524f --- /dev/null +++ b/cpu/mcf52x2/cpu.c @@ -0,0 +1,146 @@ +/* + * (C) Copyright 2003 + * Josef Baumgartner <josef.baumgartner@telex.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 <watchdog.h> +#include <command.h> + +#ifdef CONFIG_M5272 +#include <asm/immap_5272.h> +#include <asm/m5272.h> +#endif + +#ifdef CONFIG_M5282 + +#endif + +#ifdef CONFIG_M5249 +#include <asm/m5249.h> +#endif + + +#ifdef CONFIG_M5272 +int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) { + volatile wdog_t * wdp = (wdog_t *)(CFG_MBAR + MCFSIM_WRRR); + + wdp->wdog_wrrr = 0; + udelay (1000); + + /* enable watchdog, set timeout to 0 and wait */ + wdp->wdog_wrrr = 1; + while (1); + + /* we don't return! */ + return 0; +}; + +int checkcpu(void) { + ulong *dirp = (ulong *)(CFG_MBAR + MCFSIM_DIR); + uchar msk; + char *suf; + + puts ("CPU: "); + msk = (*dirp > 28) & 0xf; + switch (msk) { + case 0x2: suf = "1K75N"; break; + case 0x4: suf = "3K75N"; break; + default: + suf = NULL; + printf ("MOTOROLA MCF5272 (Mask:%01x)\n", msk); + break; + } + + if (suf) + printf ("MOTOROLA MCF5272 %s\n", suf); + return 0; +}; + + +#if defined(CONFIG_WATCHDOG) +/* Called by macro WATCHDOG_RESET */ +void watchdog_reset (void) +{ + volatile immap_t * regp = (volatile immap_t *)CFG_MBAR; + regp->wdog_reg.wdog_wcr = 0; +} + +int watchdog_disable (void) +{ + volatile immap_t *regp = (volatile immap_t *)CFG_MBAR; + + regp->wdog_reg.wdog_wcr = 0; /* reset watchdog counter */ + regp->wdog_reg.wdog_wirr = 0; /* disable watchdog interrupt */ + regp->wdog_reg.wdog_wrrr = 0; /* disable watchdog timer */ + + puts ("WATCHDOG:disabled\n"); + return (0); +} + +int watchdog_init (void) +{ + volatile immap_t *regp = (volatile immap_t *)CFG_MBAR; + + regp->wdog_reg.wdog_wirr = 0; /* disable watchdog interrupt */ + + /* set timeout and enable watchdog */ + regp->wdog_reg.wdog_wrrr = ((CONFIG_WATCHDOG_TIMEOUT * CFG_HZ) / (32768 * 1000)) - 1; + regp->wdog_reg.wdog_wcr = 0; /* reset watchdog counter */ + + puts ("WATCHDOG:enabled\n"); + return (0); +} +#endif /* #ifdef CONFIG_WATCHDOG */ + +#endif /* #ifdef CONFIG_M5272 */ + + +#ifdef CONFIG_M5282 +int checkcpu (void) +{ + puts ("CPU: MOTOROLA Coldfire MCF5282\n"); + return 0; +} + +int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) { + return 0; +}; +#endif + +#ifdef CONFIG_M5249 /* test-only: todo... */ +int checkcpu (void) +{ + char buf[32]; + + printf ("CPU: MOTOROLA Coldfire MCF5249 at %s MHz\n", strmhz(buf, CFG_CLK)); + return 0; +} + +int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) { + /* enable watchdog, set timeout to 0 and wait */ + mbar_writeByte(MCFSIM_SYPCR, 0xc0); + while (1); + + /* we don't return! */ + return 0; +}; +#endif diff --git a/cpu/mcf52x2/cpu_init.c b/cpu/mcf52x2/cpu_init.c new file mode 100755 index 0000000..350c431 --- /dev/null +++ b/cpu/mcf52x2/cpu_init.c @@ -0,0 +1,252 @@ +/* + * (C) Copyright 2003 + * Josef Baumgartner <josef.baumgartner@telex.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 <watchdog.h> + +#ifdef CONFIG_M5272 +#include <asm/m5272.h> +#include <asm/immap_5272.h> +#endif + +#ifdef CONFIG_M5282 +#include <asm/m5282.h> +#include <asm/immap_5282.h> +#endif + +#ifdef CONFIG_M5249 +#include <asm/m5249.h> +#endif + +#if defined(CONFIG_M5272) +/* + * Breath some life into the CPU... + * + * Set up the memory map, + * initialize a bunch of registers, + * initialize the UPM's + */ +void cpu_init_f (void) +{ + /* if we come from RAM we assume the CPU is + * already initialized. + */ +#ifndef CONFIG_MONITOR_IS_IN_RAM + volatile immap_t *regp = (immap_t *)CFG_MBAR; + + volatile unsigned char *mbar; + mbar = (volatile unsigned char *) CFG_MBAR; + + regp->sysctrl_reg.sc_scr = CFG_SCR; + regp->sysctrl_reg.sc_spr = CFG_SPR; + + /* Setup Ports: */ + regp->gpio_reg.gpio_pacnt = CFG_PACNT; + regp->gpio_reg.gpio_paddr = CFG_PADDR; + regp->gpio_reg.gpio_padat = CFG_PADAT; + regp->gpio_reg.gpio_pbcnt = CFG_PBCNT; + regp->gpio_reg.gpio_pbddr = CFG_PBDDR; + regp->gpio_reg.gpio_pbdat = CFG_PBDAT; + regp->gpio_reg.gpio_pdcnt = CFG_PDCNT; + + /* Memory Controller: */ + regp->csctrl_reg.cs_br0 = CFG_BR0_PRELIM; + regp->csctrl_reg.cs_or0 = CFG_OR0_PRELIM; + +#if (defined(CFG_OR1_PRELIM) && defined(CFG_BR1_PRELIM)) + regp->csctrl_reg.cs_br1 = CFG_BR1_PRELIM; + regp->csctrl_reg.cs_or1 = CFG_OR1_PRELIM; +#endif + +#if defined(CFG_OR2_PRELIM) && defined(CFG_BR2_PRELIM) + regp->csctrl_reg.cs_br2 = CFG_BR2_PRELIM; + regp->csctrl_reg.cs_or2 = CFG_OR2_PRELIM; +#endif + +#if defined(CFG_OR3_PRELIM) && defined(CFG_BR3_PRELIM) + regp->csctrl_reg.cs_br3 = CFG_BR3_PRELIM; + regp->csctrl_reg.cs_or3 = CFG_OR3_PRELIM; +#endif + +#if defined(CFG_OR4_PRELIM) && defined(CFG_BR4_PRELIM) + regp->csctrl_reg.cs_br4 = CFG_BR4_PRELIM; + regp->csctrl_reg.cs_or4 = CFG_OR4_PRELIM; +#endif + +#if defined(CFG_OR5_PRELIM) && defined(CFG_BR5_PRELIM) + regp->csctrl_reg.cs_br5 = CFG_BR5_PRELIM; + regp->csctrl_reg.cs_or5 = CFG_OR5_PRELIM; +#endif + +#if defined(CFG_OR6_PRELIM) && defined(CFG_BR6_PRELIM) + regp->csctrl_reg.cs_br6 = CFG_BR6_PRELIM; + regp->csctrl_reg.cs_or6 = CFG_OR6_PRELIM; +#endif + +#if defined(CFG_OR7_PRELIM) && defined(CFG_BR7_PRELIM) + regp->csctrl_reg.cs_br7 = CFG_BR7_PRELIM; + regp->csctrl_reg.cs_or7 = CFG_OR7_PRELIM; +#endif + +#endif /* #ifndef CONFIG_MONITOR_IS_IN_RAM */ + + /* enable instruction cache now */ + icache_enable(); + +} + +/* + * initialize higher level parts of CPU like timers + */ +int cpu_init_r (void) +{ + return (0); +} +#endif /* #if defined(CONFIG_M5272) */ + + +#ifdef CONFIG_M5282 +/* + * Breath some life into the CPU... + * + * Set up the memory map, + * initialize a bunch of registers, + * initialize the UPM's + */ +void cpu_init_f (void) +{ + +} + +/* + * initialize higher level parts of CPU like timers + */ +int cpu_init_r (void) +{ + return (0); +} +#endif + +#if defined(CONFIG_M5249) +/* + * Breath some life into the CPU... + * + * Set up the memory map, + * initialize a bunch of registers, + * initialize the UPM's + */ +void cpu_init_f (void) +{ +#ifndef CFG_PLL_BYPASS + /* + * Setup the PLL to run at the specified speed + * + */ + volatile unsigned long cpll = mbar2_readLong(MCFSIM_PLLCR); + unsigned long pllcr; +#ifdef CFG_FAST_CLK + pllcr = 0x925a3100; /* ~140MHz clock (PLL bypass = 0) */ +#else + pllcr = 0x135a4140; /* ~72MHz clock (PLL bypass = 0) */ +#endif + cpll = cpll & 0xfffffffe; /* Set PLL bypass mode = 0 (PSTCLK = crystal) */ + mbar2_writeLong(MCFSIM_PLLCR, cpll); /* Set the PLL to bypass mode (PSTCLK = crystal) */ + mbar2_writeLong(MCFSIM_PLLCR, pllcr); /* set the clock speed */ + pllcr ^= 0x00000001; /* Set pll bypass to 1 */ + mbar2_writeLong(MCFSIM_PLLCR, pllcr); /* Start locking (pll bypass = 1) */ + udelay(0x20); /* Wait for a lock ... */ +#endif /* #ifndef CFG_PLL_BYPASS */ + + /* + * NOTE: by setting the GPIO_FUNCTION registers, we ensure that the UART pins + * (UART0: gpio 30,27, UART1: gpio 31, 28) will be used as UART pins + * which is their primary function. + * ~Jeremy + */ + mbar2_writeLong(MCFSIM_GPIO_FUNC, CFG_GPIO_FUNC); + mbar2_writeLong(MCFSIM_GPIO1_FUNC, CFG_GPIO1_FUNC); + mbar2_writeLong(MCFSIM_GPIO_EN, CFG_GPIO_EN); + mbar2_writeLong(MCFSIM_GPIO1_EN, CFG_GPIO1_EN); + mbar2_writeLong(MCFSIM_GPIO_OUT, CFG_GPIO_OUT); + mbar2_writeLong(MCFSIM_GPIO1_OUT, CFG_GPIO1_OUT); + + /* + * dBug Compliance: + * You can verify these values by using dBug's 'ird' + * (Internal Register Display) command + * ~Jeremy + * + */ + mbar_writeByte(MCFSIM_MPARK, 0x30); /* 5249 Internal Core takes priority over DMA */ + mbar_writeByte(MCFSIM_SYPCR, 0x00); + mbar_writeByte(MCFSIM_SWIVR, 0x0f); + mbar_writeByte(MCFSIM_SWSR, 0x00); + mbar_writeLong(MCFSIM_IMR, 0xfffffbff); + mbar_writeByte(MCFSIM_SWDICR, 0x00); + mbar_writeByte(MCFSIM_TIMER1ICR, 0x00); + mbar_writeByte(MCFSIM_TIMER2ICR, 0x88); + mbar_writeByte(MCFSIM_I2CICR, 0x00); + mbar_writeByte(MCFSIM_UART1ICR, 0x00); + mbar_writeByte(MCFSIM_UART2ICR, 0x00); + mbar_writeByte(MCFSIM_ICR6, 0x00); + mbar_writeByte(MCFSIM_ICR7, 0x00); + mbar_writeByte(MCFSIM_ICR8, 0x00); + mbar_writeByte(MCFSIM_ICR9, 0x00); + mbar_writeByte(MCFSIM_QSPIICR, 0x00); + + mbar2_writeLong(MCFSIM_GPIO_INT_EN, 0x00000080); + mbar2_writeByte(MCFSIM_INTBASE, 0x40); /* Base interrupts at 64 */ + mbar2_writeByte(MCFSIM_SPURVEC, 0x00); + mbar2_writeLong(MCFSIM_IDECONFIG1, 0x00000020); /* Enable a 1 cycle pre-drive cycle on CS1 */ + + /* Setup interrupt priorities for gpio7 */ + /* mbar2_writeLong(MCFSIM_INTLEV5, 0x70000000); */ + + /* IDE Config registers */ + mbar2_writeLong(MCFSIM_IDECONFIG1, 0x00000020); + mbar2_writeLong(MCFSIM_IDECONFIG2, 0x00000000); + + /* + * Setup chip selects... + */ + + mbar_writeShort(MCFSIM_CSAR1, CFG_CSAR1); + mbar_writeShort(MCFSIM_CSCR1, CFG_CSCR1); + mbar_writeLong(MCFSIM_CSMR1, CFG_CSMR1); + + mbar_writeShort(MCFSIM_CSAR0, CFG_CSAR0); + mbar_writeShort(MCFSIM_CSCR0, CFG_CSCR0); + mbar_writeLong(MCFSIM_CSMR0, CFG_CSMR0); + + /* enable instruction cache now */ + icache_enable(); +} + +/* + * initialize higher level parts of CPU like timers + */ +int cpu_init_r (void) +{ + return (0); +} +#endif /* #if defined(CONFIG_M5249) */ diff --git a/cpu/mcf52x2/fec.c b/cpu/mcf52x2/fec.c new file mode 100755 index 0000000..a5c50af --- /dev/null +++ b/cpu/mcf52x2/fec.c @@ -0,0 +1,569 @@ +/* + * (C) Copyright 2000-2004 + * 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 <common.h> +#include <malloc.h> +#include <asm/fec.h> + +#ifdef CONFIG_M5272 +#include <asm/m5272.h> +#include <asm/immap_5272.h> +#endif + +#ifdef CONFIG_M5282 +#include <asm/m5282.h> +#include <asm/immap_5282.h> +#endif + +#include <net.h> +#include <command.h> + +#ifdef CONFIG_M5272 +#define FEC_ADDR (CFG_MBAR + 0x840) +#endif +#ifdef CONFIG_M5282 +#define FEC_ADDR (CFG_MBAR + 0x1000) +#endif + +#undef ET_DEBUG +#undef MII_DEBUG + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET) + +#ifdef CFG_DISCOVER_PHY +#include <miiphy.h> +static void mii_discover_phy (void); +#endif + +/* Ethernet Transmit and Receive Buffers */ +#define DBUF_LENGTH 1520 + +#define TX_BUF_CNT 2 + +#define TOUT_LOOP 100 + +#define PKT_MAXBUF_SIZE 1518 +#define PKT_MINBUF_SIZE 64 +#define PKT_MAXBLR_SIZE 1520 + + +static char txbuf[DBUF_LENGTH]; + +static uint rxIdx; /* index of the current RX buffer */ +static uint txIdx; /* index of the current TX buffer */ + +/* + * FEC Ethernet Tx and Rx buffer descriptors allocated at the + * immr->udata_bd address on Dual-Port RAM + * Provide for Double Buffering + */ + +typedef volatile struct CommonBufferDescriptor { + cbd_t rxbd[PKTBUFSRX]; /* Rx BD */ + cbd_t txbd[TX_BUF_CNT]; /* Tx BD */ +} RTXBD; + +static RTXBD *rtx = NULL; + +int eth_send (volatile void *packet, int length) +{ + int j, rc; + volatile fec_t *fecp = (fec_t *) (FEC_ADDR); + + /* section 16.9.23.3 + * Wait for ready + */ + j = 0; + while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) + && (j < TOUT_LOOP)) { + udelay (1); + j++; + } + if (j >= TOUT_LOOP) { + printf ("TX not ready\n"); + } + + rtx->txbd[txIdx].cbd_bufaddr = (uint) packet; + rtx->txbd[txIdx].cbd_datlen = length; + rtx->txbd[txIdx].cbd_sc |= BD_ENET_TX_READY | BD_ENET_TX_LAST; + + /* Activate transmit Buffer Descriptor polling */ + fecp->fec_x_des_active = 0x01000000; /* Descriptor polling active */ + + j = 0; + while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) + && (j < TOUT_LOOP)) { + udelay (1); + j++; + } + if (j >= TOUT_LOOP) { + printf ("TX timeout\n"); + } +#ifdef ET_DEBUG + printf ("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n", + __FILE__, __LINE__, __FUNCTION__, j, rtx->txbd[txIdx].cbd_sc, + (rtx->txbd[txIdx].cbd_sc & 0x003C) >> 2); +#endif + + /* return only status bits */ ; + rc = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS); + + txIdx = (txIdx + 1) % TX_BUF_CNT; + + return rc; +} + +int eth_rx (void) +{ + int length; + volatile fec_t *fecp = (fec_t *) FEC_ADDR; + + for (;;) { + /* section 16.9.23.2 */ + if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { + length = -1; + break; /* nothing received - leave for() loop */ + } + + length = rtx->rxbd[rxIdx].cbd_datlen; + + if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) { +#ifdef ET_DEBUG + printf ("%s[%d] err: %x\n", + __FUNCTION__, __LINE__, + rtx->rxbd[rxIdx].cbd_sc); +#endif + } else { + /* Pass the packet up to the protocol layers. */ + NetReceive (NetRxPackets[rxIdx], length - 4); + } + + /* Give the buffer back to the FEC. */ + rtx->rxbd[rxIdx].cbd_datlen = 0; + + /* wrap around buffer index when necessary */ + if ((rxIdx + 1) >= PKTBUFSRX) { + rtx->rxbd[PKTBUFSRX - 1].cbd_sc = + (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); + rxIdx = 0; + } else { + rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; + rxIdx++; + } + + /* Try to fill Buffer Descriptors */ + fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */ + } + + return length; +} + +/************************************************************** + * + * FEC Ethernet Initialization Routine + * + *************************************************************/ +#define FEC_ECNTRL_ETHER_EN 0x00000002 +#define FEC_ECNTRL_RESET 0x00000001 + +#define FEC_RCNTRL_BC_REJ 0x00000010 +#define FEC_RCNTRL_PROM 0x00000008 +#define FEC_RCNTRL_MII_MODE 0x00000004 +#define FEC_RCNTRL_DRT 0x00000002 +#define FEC_RCNTRL_LOOP 0x00000001 + +#define FEC_TCNTRL_FDEN 0x00000004 +#define FEC_TCNTRL_HBC 0x00000002 +#define FEC_TCNTRL_GTS 0x00000001 + +#define FEC_RESET_DELAY 50000 + +int eth_init (bd_t * bd) +{ + + int i; + volatile fec_t *fecp = (fec_t *) (FEC_ADDR); + + /* Whack a reset. + * A delay is required between a reset of the FEC block and + * initialization of other FEC registers because the reset takes + * some time to complete. If you don't delay, subsequent writes + * to FEC registers might get killed by the reset routine which is + * still in progress. + */ + fecp->fec_ecntrl = FEC_ECNTRL_RESET; + for (i = 0; + (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY); + ++i) { + udelay (1); + } + if (i == FEC_RESET_DELAY) { + printf ("FEC_RESET_DELAY timeout\n"); + return 0; + } + + /* We use strictly polling mode only + */ + fecp->fec_imask = 0; + + /* Clear any pending interrupt */ + fecp->fec_ievent = 0xffffffff; + + /* Set station address */ +#define ea bd->bi_enetaddr + fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) | + (ea[2] << 8) | (ea[3]); + fecp->fec_addr_high = (ea[4] << 24) | (ea[5] << 16); +#ifdef ET_DEBUG + printf ("Eth Addrs: %02x:%02x:%02x:%02x:%02x:%02x\n", + ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]); +#endif +#undef ea + + /* Clear multicast address hash table + */ + fecp->fec_hash_table_high = 0; + fecp->fec_hash_table_low = 0; + + /* Set maximum receive buffer size. + */ + fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; + + /* + * Setup Buffers and Buffer Desriptors + */ + rxIdx = 0; + txIdx = 0; + + if (!rtx) { + rtx = (RTXBD *) CFG_ENET_BD_BASE; + } + + /* + * Setup Receiver Buffer Descriptors (13.14.24.18) + * Settings: + * Empty, Wrap + */ + for (i = 0; i < PKTBUFSRX; i++) { + rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; + rtx->rxbd[i].cbd_datlen = 0; /* Reset */ + rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i]; + } + rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; + + /* + * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) + * Settings: + * Last, Tx CRC + */ + for (i = 0; i < TX_BUF_CNT; i++) { + rtx->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC; + rtx->txbd[i].cbd_datlen = 0; /* Reset */ + rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]); + } + rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; + + /* Set receive and transmit descriptor base + */ + fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]); + fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]); + + /* Enable MII mode + */ +#if 0 /* Full duplex mode */ + fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE; + fecp->fec_x_cntrl = FEC_TCNTRL_FDEN; +#else /* Half duplex mode */ + fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT; + fecp->fec_x_cntrl = 0; +#endif + /* Set MII speed */ + fecp->fec_mii_speed = 0x0e; + + /* Configure port B for MII. + */ + /* port initialization was already made in cpu_init_f() */ + + /* Now enable the transmit and receive processing + */ + fecp->fec_ecntrl = FEC_ECNTRL_ETHER_EN; + +#ifdef CFG_DISCOVER_PHY + /* wait for the PHY to wake up after reset */ + mii_discover_phy (); +#endif + + /* And last, try to fill Rx Buffer Descriptors */ + fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */ + + return 1; +} + +void eth_halt (void) +{ + volatile fec_t *fecp = (fec_t *) FEC_ADDR; + + fecp->fec_ecntrl = 0; +} + + +#if defined(CFG_DISCOVER_PHY) || (CONFIG_COMMANDS & CFG_CMD_MII) + +static int phyaddr = -1; /* didn't find a PHY yet */ +static uint phytype; + +/* Make MII read/write commands for the FEC. +*/ + +#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \ + (REG & 0x1f) << 18)) + +#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \ + (REG & 0x1f) << 18) | \ + (VAL & 0xffff)) + +/* Interrupt events/masks. +*/ +#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ +#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */ +#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */ +#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */ +#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */ +#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */ +#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */ +#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */ +#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */ +#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ + +/* PHY identification + */ +#define PHY_ID_LXT970 0x78100000 /* LXT970 */ +#define PHY_ID_LXT971 0x001378e0 /* LXT971 and 972 */ +#define PHY_ID_82555 0x02a80150 /* Intel 82555 */ +#define PHY_ID_QS6612 0x01814400 /* QS6612 */ +#define PHY_ID_AMD79C784 0x00225610 /* AMD 79C784 */ +#define PHY_ID_LSI80225 0x0016f870 /* LSI 80225 */ +#define PHY_ID_LSI80225B 0x0016f880 /* LSI 80225/B */ + +/* send command to phy using mii, wait for result */ +static uint mii_send (uint mii_cmd) +{ + uint mii_reply; + volatile fec_t *ep = (fec_t *) (FEC_ADDR); + + ep->fec_mii_data = mii_cmd; /* command to phy */ + + /* wait for mii complete */ + while (!(ep->fec_ievent & FEC_ENET_MII)); /* spin until done */ + mii_reply = ep->fec_mii_data; /* result from phy */ + ep->fec_ievent = FEC_ENET_MII; /* clear MII complete */ +#ifdef ET_DEBUG + printf ("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n", + __FILE__, __LINE__, __FUNCTION__, mii_cmd, mii_reply); +#endif + return (mii_reply & 0xffff); /* data read from phy */ +} +#endif /* CFG_DISCOVER_PHY || (CONFIG_COMMANDS & CFG_CMD_MII) */ + +#if defined(CFG_DISCOVER_PHY) +static void mii_discover_phy (void) +{ +#define MAX_PHY_PASSES 11 + uint phyno; + int pass; + + phyaddr = -1; /* didn't find a PHY yet */ + for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) { + if (pass > 1) { + /* PHY may need more time to recover from reset. + * The LXT970 needs 50ms typical, no maximum is + * specified, so wait 10ms before try again. + * With 11 passes this gives it 100ms to wake up. + */ + udelay (10000); /* wait 10ms */ + } + for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) { + phytype = mii_send (mk_mii_read (phyno, PHY_PHYIDR1)); +#ifdef ET_DEBUG + printf ("PHY type 0x%x pass %d type ", phytype, pass); +#endif + if (phytype != 0xffff) { + phyaddr = phyno; + phytype <<= 16; + phytype |= mii_send (mk_mii_read (phyno, + PHY_PHYIDR2)); + +#ifdef ET_DEBUG + printf ("PHY @ 0x%x pass %d type ", phyno, + pass); + switch (phytype & 0xfffffff0) { + case PHY_ID_LXT970: + printf ("LXT970\n"); + break; + case PHY_ID_LXT971: + printf ("LXT971\n"); + break; + case PHY_ID_82555: + printf ("82555\n"); + break; + case PHY_ID_QS6612: + printf ("QS6612\n"); + break; + case PHY_ID_AMD79C784: + printf ("AMD79C784\n"); + break; + case PHY_ID_LSI80225B: + printf ("LSI L80225/B\n"); + break; + default: + printf ("0x%08x\n", phytype); + break; + } +#endif + } + } + } + if (phyaddr < 0) { + printf ("No PHY device found.\n"); + } +} +#endif /* CFG_DISCOVER_PHY */ + +#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII) + +static int mii_init_done = 0; + +/**************************************************************************** + * mii_init -- Initialize the MII for MII command without ethernet + * This function is a subset of eth_init + **************************************************************************** + */ +void mii_init (void) +{ + volatile fec_t *fecp = (fec_t *) (FEC_ADDR); + + int i; + + if (mii_init_done != 0) { + return; + } + + /* Whack a reset. + * A delay is required between a reset of the FEC block and + * initialization of other FEC registers because the reset takes + * some time to complete. If you don't delay, subsequent writes + * to FEC registers might get killed by the reset routine which is + * still in progress. + */ + + fecp->fec_ecntrl = FEC_ECNTRL_RESET; + for (i = 0; + (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY); + ++i) { + udelay (1); + } + if (i == FEC_RESET_DELAY) { + printf ("FEC_RESET_DELAY timeout\n"); + return; + } + + /* We use strictly polling mode only + */ + fecp->fec_imask = 0; + + /* Clear any pending interrupt + */ + fecp->fec_ievent = 0xffffffff; + + /* Set MII speed */ + fecp->fec_mii_speed = 0x0e; + + /* Configure port B for MII. + */ + /* port initialization was already made in cpu_init_f() */ + + /* Now enable the transmit and receive processing */ + fecp->fec_ecntrl = FEC_ECNTRL_ETHER_EN; + + mii_init_done = 1; +} + +/***************************************************************************** + * Read and write a MII PHY register, routines used by MII Utilities + * + * FIXME: These routines are expected to return 0 on success, but mii_send + * does _not_ return an error code. Maybe 0xFFFF means error, i.e. + * no PHY connected... + * For now always return 0. + * FIXME: These routines only work after calling eth_init() at least once! + * Otherwise they hang in mii_send() !!! Sorry! + *****************************************************************************/ + +int mcf52x2_miiphy_read (char *devname, unsigned char addr, + unsigned char reg, unsigned short *value) +{ + short rdreg; /* register working value */ + +#ifdef MII_DEBUG + printf ("miiphy_read(0x%x) @ 0x%x = ", reg, addr); +#endif + rdreg = mii_send (mk_mii_read (addr, reg)); + + *value = rdreg; + +#ifdef MII_DEBUG + printf ("0x%04x\n", *value); +#endif + + return 0; +} + +int mcf52x2_miiphy_write (char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + short rdreg; /* register working value */ + +#ifdef MII_DEBUG + printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr); +#endif + + rdreg = mii_send (mk_mii_write (addr, reg, value)); + +#ifdef MII_DEBUG + printf ("0x%04x\n", value); +#endif + + return 0; +} +#endif /* (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII) */ +#endif /* CFG_CMD_NET, FEC_ENET */ + +int mcf52x2_miiphy_initialize(bd_t *bis) +{ +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET) +#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII) + miiphy_register("mcf52x2phy", mcf52x2_miiphy_read, mcf52x2_miiphy_write); +#endif +#endif + return 0; +} diff --git a/cpu/mcf52x2/interrupts.c b/cpu/mcf52x2/interrupts.c new file mode 100755 index 0000000..868df39 --- /dev/null +++ b/cpu/mcf52x2/interrupts.c @@ -0,0 +1,188 @@ +/* + * (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de> + * + * (C) Copyright 2000-2004 + * 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 <common.h> +#include <watchdog.h> +#include <asm/processor.h> + +#ifdef CONFIG_M5272 +#include <asm/m5272.h> +#include <asm/immap_5272.h> +#endif + +#ifdef CONFIG_M5282 +#include <asm/m5282.h> +#include <asm/immap_5282.h> +#endif + +#ifdef CONFIG_M5249 +#include <asm/m5249.h> +#endif + + +#define NR_IRQS 31 + +/* + * Interrupt vector functions. + */ +struct interrupt_action { + interrupt_handler_t *handler; + void *arg; +}; + +static struct interrupt_action irq_vecs[NR_IRQS]; + +static __inline__ unsigned short get_sr (void) +{ + unsigned short sr; + + asm volatile ("move.w %%sr,%0":"=r" (sr):); + + return sr; +} + +static __inline__ void set_sr (unsigned short sr) +{ + asm volatile ("move.w %0,%%sr"::"r" (sr)); +} + +/************************************************************************/ +/* + * Install and free an interrupt handler + */ +void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg) +{ +#ifdef CONFIG_M5272 + volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1); +#endif + int vec_base = 0; + +#ifdef CONFIG_M5272 + vec_base = intp->int_pivr & 0xe0; +#endif + + if ((vec < vec_base) || (vec > vec_base + NR_IRQS)) { + printf ("irq_install_handler: wrong interrupt vector %d\n", + vec); + return; + } + + irq_vecs[vec - vec_base].handler = handler; + irq_vecs[vec - vec_base].arg = arg; +} + +void irq_free_handler (int vec) +{ +#ifdef CONFIG_M5272 + volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1); +#endif + int vec_base = 0; + +#ifdef CONFIG_M5272 + vec_base = intp->int_pivr & 0xe0; +#endif + + if ((vec < vec_base) || (vec > vec_base + NR_IRQS)) { + return; + } + + irq_vecs[vec - vec_base].handler = NULL; + irq_vecs[vec - vec_base].arg = NULL; +} + +void enable_interrupts (void) +{ + unsigned short sr; + + sr = get_sr (); + set_sr (sr & ~0x0700); +} + +int disable_interrupts (void) +{ + unsigned short sr; + + sr = get_sr (); + set_sr (sr | 0x0700); + + return ((sr & 0x0700) == 0); /* return TRUE, if interrupts were enabled before */ +} + +void int_handler (struct pt_regs *fp) +{ +#ifdef CONFIG_M5272 + volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1); +#endif + int vec, vec_base = 0; + + vec = (fp->vector >> 2) & 0xff; +#ifdef CONFIG_M5272 + vec_base = intp->int_pivr & 0xe0; +#endif + + if (irq_vecs[vec - vec_base].handler != NULL) { + irq_vecs[vec - + vec_base].handler (irq_vecs[vec - vec_base].arg); + } else { + printf ("\nBogus External Interrupt Vector %d\n", vec); + } +} + + +#ifdef CONFIG_M5272 +int interrupt_init (void) +{ + volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1); + + /* disable all external interrupts */ + intp->int_icr1 = 0x88888888; + intp->int_icr2 = 0x88888888; + intp->int_icr3 = 0x88888888; + intp->int_icr4 = 0x88888888; + intp->int_pitr = 0x00000000; + /* initialize vector register */ + intp->int_pivr = 0x40; + + enable_interrupts (); + + return 0; +} +#endif + +#ifdef CONFIG_M5282 +int interrupt_init (void) +{ + return 0; +} +#endif + +#ifdef CONFIG_M5249 +int interrupt_init (void) +{ + enable_interrupts (); + + return 0; +} +#endif diff --git a/cpu/mcf52x2/serial.c b/cpu/mcf52x2/serial.c new file mode 100755 index 0000000..c730922 --- /dev/null +++ b/cpu/mcf52x2/serial.c @@ -0,0 +1,167 @@ +/* + * (C) Copyright 2000-2004 + * 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 <common.h> +#include <command.h> + +#include <asm/mcfuart.h> + +#ifdef CONFIG_M5272 +#include <asm/m5272.h> +#endif + +#ifdef CONFIG_M5282 +#include <asm/m5282.h> +#endif + +#ifdef CONFIG_M5249 +#include <asm/m5249.h> +#endif + +#ifdef CONFIG_M5249 +#define DoubleClock(a) ((double)(CFG_CLK/2) / 32.0 / (double)(a)) +#else +#define DoubleClock(a) ((double)(CFG_CLK) / 32.0 / (double)(a)) +#endif + +void rs_serial_setbaudrate(int port,int baudrate) +{ +#if defined(CONFIG_M5272) || defined(CONFIG_M5249) + volatile unsigned char *uartp; + double clock, fraction; + + if (port == 0) + uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1); + else + uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE2); + + clock = DoubleClock(baudrate); /* Set baud above */ + + fraction = ((clock - (int)clock) * 16.0) + 0.5; + + uartp[MCFUART_UBG1] = (((int)clock >> 8) & 0xff); /* set msb baud */ + uartp[MCFUART_UBG2] = ((int)clock & 0xff); /* set lsb baud */ + uartp[MCFUART_UFPD] = ((int)fraction & 0xf); /* set baud fraction adjust */ +#endif +}; + +void rs_serial_init(int port,int baudrate) +{ + volatile unsigned char *uartp; + + /* + * Reset UART, get it into known state... + */ + if (port == 0) + uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1); + else + uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE2); + + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR; /* reset Error pointer */ + + /* + * Set port for CONSOLE_BAUD_RATE, 8 data bits, 1 stop bit, no parity. + */ + uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8; + uartp[MCFUART_UMR] = MCFUART_MR2_STOP1; + + rs_serial_setbaudrate(port,baudrate); + + uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER; + uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; + + return; +} + +/****************************************************************************/ +/* + * Output a single character, using UART polled mode. + * This is used for console output. + */ + +void rs_put_char(char ch) +{ + volatile unsigned char *uartp; + int i; + + uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1); + + for (i = 0; (i < 0x10000); i++) { + if (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) + break; + } + uartp[MCFUART_UTB] = ch; + return; +} + +int rs_is_char(void) +{ + volatile unsigned char *uartp; + + uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1); + return((uartp[MCFUART_USR] & MCFUART_USR_RXREADY) ? 1 : 0); +} + +int rs_get_char(void) +{ + volatile unsigned char *uartp; + + uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1); + return(uartp[MCFUART_URB]); +} + +void serial_setbrg(void) { + DECLARE_GLOBAL_DATA_PTR; + rs_serial_setbaudrate(0,gd->bd->bi_baudrate); +} + +int serial_init(void) { + DECLARE_GLOBAL_DATA_PTR; + rs_serial_init(0,gd->baudrate); + return 0; +} + + +void serial_putc(const char c) { + if (c == '\n') + serial_putc ('\r'); + rs_put_char(c); +} + +void serial_puts (const char *s) { + while (*s) { + serial_putc(*s++); + } +} + +int serial_getc(void) { + while(!rs_is_char()); + return rs_get_char(); +} + +int serial_tstc() { + return rs_is_char(); +} diff --git a/cpu/mcf52x2/speed.c b/cpu/mcf52x2/speed.c new file mode 100755 index 0000000..519c992 --- /dev/null +++ b/cpu/mcf52x2/speed.c @@ -0,0 +1,41 @@ +/* + * (C) Copyright 2003 + * Josef Baumgartner <josef.baumgartner@telex.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/processor.h> + +/* + * get_clocks() fills in gd->cpu_clock and gd->bus_clk + */ +int get_clocks (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + gd->cpu_clk = CFG_CLK; +#ifdef CONFIG_M5249 + gd->bus_clk = gd->cpu_clk / 2; +#else + gd->bus_clk = gd->cpu_clk; +#endif + return (0); +} diff --git a/cpu/mcf52x2/start.S b/cpu/mcf52x2/start.S new file mode 100755 index 0000000..b4926e2 --- /dev/null +++ b/cpu/mcf52x2/start.S @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2003 Josef Baumgartner <josef.baumgartner@telex.de> + * Based on code from Bernhard Kuhn <bkuhn@metrowerks.com> + * + * 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_IDENT_STRING +#define CONFIG_IDENT_STRING "" +#endif + + +#define _START _start +#define _FAULT _fault + + +#define SAVE_ALL \ + move.w #0x2700,%sr; /* disable intrs */ \ + subl #60,%sp; /* space for 15 regs */ \ + moveml %d0-%d7/%a0-%a6,%sp@; \ + +#define RESTORE_ALL \ + moveml %sp@,%d0-%d7/%a0-%a6; \ + addl #60,%sp; /* space for 15 regs */ \ + rte + +/* If we come from a pre-loader we don't need an initial exception + * table. + */ +#if !defined(CONFIG_MONITOR_IS_IN_RAM) + +.text +/* + * Vector table. This is used for initial platform startup. + * These vectors are to catch any un-intended traps. + */ +_vectors: + +.long 0x00000000, _START +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT + +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT + +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT + +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT + +#endif + + .text + + .globl _start +_start: + nop + nop + move.w #0x2700,%sr + + /* if we come from a pre-loader we have no exception table and + * therefore no VBR to set + */ +#if !defined(CONFIG_MONITOR_IS_IN_RAM) + move.l #CFG_FLASH_BASE, %d0 + movec %d0, %VBR +#endif + +#if defined(CONFIG_M5272) || defined(CONFIG_M5249) + move.l #(CFG_MBAR + 1), %d0 /* set MBAR address + valid flag */ + move.c %d0, %MBAR + + /*** The 5249 has MBAR2 as well ***/ +#ifdef CFG_MBAR2 + move.l #(CFG_MBAR2 + 1), %d0 /* Get MBAR2 address */ + movec %d0, #0xc0e /* Set MBAR2 */ +#endif + + move.l #(CFG_INIT_RAM_ADDR + 1), %d0 + movec %d0, %RAMBAR0 +#endif /* #if defined(CONFIG_M5272) || defined(CONFIG_M5249) */ + +#ifdef CONFIG_M5282 + /* Initialize IPSBAR */ + move.l #(CFG_MBAR + 1), %d0 /* set IPSBAR address + valid flag */ + move.l %d0, 0x40000000 + + /* Initialize FLASHBAR: locate internal Flash and validate it */ + move.l #(CFG_INT_FLASH_BASE + 0x21), %d0 + movec %d0, %RAMBAR0 + + /* Initialize RAMBAR1: locate SRAM and validate it */ + move.l #(CFG_INIT_RAM_ADDR + 0x21), %d0 + movec %d0, %RAMBAR1 +#endif + + /* invalidate and disable cache */ + move.l #0x01000000, %d0 /* Invalidate cache cmd */ + movec %d0, %CACR /* Invalidate cache */ + move.l #0, %d0 + movec %d0, %ACR0 + movec %d0, %ACR1 + + /* set stackpointer to end of internal ram to get some stackspace for the first c-code */ + move.l #(CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET), %sp + clr.l %sp@- + + move.l #__got_start, %a5 /* put relocation table address to a5 */ + + bsr cpu_init_f /* run low-level CPU init code (from flash) */ + bsr board_init_f /* run low-level board init code (from flash) */ + + /* board_init_f() does not return + +/*------------------------------------------------------------------------------*/ + +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * r3 = dest + * r4 = src + * r5 = length in bytes + * r6 = cachelinesize + */ + .globl relocate_code +relocate_code: + link.w %a6,#0 + move.l 8(%a6), %sp /* set new stack pointer */ + + move.l 12(%a6), %d0 /* Save copy of Global Data pointer */ + move.l 16(%a6), %a0 /* Save copy of Destination Address */ + + move.l #CFG_MONITOR_BASE, %a1 + move.l #__init_end, %a2 + move.l %a0, %a3 + + /* copy the code to RAM */ +1: + move.l (%a1)+, (%a3)+ + cmp.l %a1,%a2 + bgt.s 1b + +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ + move.l %a0, %a1 + add.l #(in_ram - CFG_MONITOR_BASE), %a1 + jmp (%a1) + +in_ram: + +clear_bss: + /* + * Now clear BSS segment + */ + move.l %a0, %a1 + add.l #(_sbss - CFG_MONITOR_BASE),%a1 + move.l %a0, %d1 + add.l #(_ebss - CFG_MONITOR_BASE),%d1 +6: + clr.l (%a1)+ + cmp.l %a1,%d1 + bgt.s 6b + + /* + * fix got table in RAM + */ + move.l %a0, %a1 + add.l #(__got_start - CFG_MONITOR_BASE),%a1 + move.l %a1,%a5 /* * fix got pointer register a5 */ + + move.l %a0, %a2 + add.l #(__got_end - CFG_MONITOR_BASE),%a2 + +7: + move.l (%a1),%d1 + sub.l #_start,%d1 + add.l %a0,%d1 + move.l %d1,(%a1)+ + cmp.l %a2, %a1 + bne 7b + + /* calculate relative jump to board_init_r in ram */ + move.l %a0, %a1 + add.l #(board_init_r - CFG_MONITOR_BASE), %a1 + + /* set parameters for board_init_r */ + move.l %a0,-(%sp) /* dest_addr */ + move.l %d0,-(%sp) /* gd */ + jsr (%a1) + +/*------------------------------------------------------------------------------*/ +/* exception code */ + .globl _fault +_fault: + jmp _fault + + .globl _exc_handler +_exc_handler: + SAVE_ALL + movel %sp,%sp@- + bsr exc_handler + addql #4,%sp + RESTORE_ALL + + .globl _int_handler +_int_handler: + SAVE_ALL + movel %sp,%sp@- + bsr int_handler + addql #4,%sp + RESTORE_ALL + +/*------------------------------------------------------------------------------*/ +/* cache functions */ +#ifdef CONFIG_M5272 + .globl icache_enable +icache_enable: + move.l #0x01000000, %d0 /* Invalidate cache cmd */ + movec %d0, %CACR /* Invalidate cache */ + move.l #0x0000c000, %d0 /* Setup cache mask */ + movec %d0, %ACR0 /* Enable cache */ + move.l #0xff00c000, %d0 /* Setup cache mask */ + movec %d0, %ACR1 /* Enable cache */ + move.l #0x80000100, %d0 /* Setup cache mask */ + movec %d0, %CACR /* Enable cache */ + moveq #1, %d0 + move.l %d0, icache_state + rts +#endif + +#ifdef CONFIG_M5282 + .globl icache_enable +icache_enable: + move.l #0x01000000, %d0 /* Invalidate cache cmd */ + movec %d0, %CACR /* Invalidate cache */ + move.l #0x0000c000, %d0 /* Setup cache mask */ + movec %d0, %ACR0 /* Enable cache */ + move.l #0xff00c000, %d0 /* Setup cache mask */ + movec %d0, %ACR1 /* Enable cache */ + move.l #0x80400100, %d0 /* Setup cache mask, data cache disabel*/ + movec %d0, %CACR /* Enable cache */ + moveq #1, %d0 + move.l %d0, icache_state + rts +#endif + +#ifdef CONFIG_M5249 + .globl icache_enable +icache_enable: + /* + * Note: The 5249 Documentation doesn't give a bit position for CINV! + * From the 5272 and the 5307 documentation, I have deduced that it is + * probably CACR[24]. Should someone say something to Motorola? + * ~Jeremy + */ + move.l #0x01000000, %d0 /* Invalidate whole cache */ + move.c %d0,%CACR + move.l #0xff00c000, %d0 /* Set FLASH cachable: always match (SM=0b10) */ + move.c %d0, %ACR0 + move.l #0x0000c000, %d0 /* Set SDRAM cachable: always match (SM=0b10) */ + move.c %d0, %ACR1 + move.l #0x90000200, %d0 /* Set cache enable cmd */ + move.c %d0,%CACR + moveq #1, %d0 + move.l %d0, icache_state + rts +#endif + + .globl icache_disable +icache_disable: + move.l #0x00000100, %d0 /* Setup cache mask */ + movec %d0, %CACR /* Enable cache */ + clr.l %d0 /* Setup cache mask */ + movec %d0, %ACR0 /* Enable cache */ + movec %d0, %ACR1 /* Enable cache */ + moveq #0, %d0 + move.l %d0, icache_state + rts + + .globl icache_status +icache_status: + move.l icache_state, %d0 + rts + + .data +icache_state: + .long 1 + + +/*------------------------------------------------------------------------------*/ + + .globl version_string +version_string: + .ascii U_BOOT_VERSION + .ascii " (", __DATE__, " - ", __TIME__, ")" + .ascii CONFIG_IDENT_STRING, "\0" |