diff options
| -rwxr-xr-x | MAKEALL | 10 | ||||
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | board/ads5121/Makefile | 50 | ||||
| -rw-r--r-- | board/ads5121/ads5121.c | 188 | ||||
| -rw-r--r-- | board/ads5121/config.mk | 23 | ||||
| -rw-r--r-- | board/ads5121/u-boot.lds | 122 | ||||
| -rw-r--r-- | cpu/mpc512x/Makefile | 46 | ||||
| -rw-r--r-- | cpu/mpc512x/config.mk | 25 | ||||
| -rw-r--r-- | cpu/mpc512x/cpu.c | 127 | ||||
| -rw-r--r-- | cpu/mpc512x/cpu_init.c | 87 | ||||
| -rw-r--r-- | cpu/mpc512x/fec.c | 801 | ||||
| -rw-r--r-- | cpu/mpc512x/fec.h | 224 | ||||
| -rw-r--r-- | cpu/mpc512x/i2c.c | 431 | ||||
| -rw-r--r-- | cpu/mpc512x/interrupts.c | 61 | ||||
| -rw-r--r-- | cpu/mpc512x/serial.c | 197 | ||||
| -rw-r--r-- | cpu/mpc512x/speed.c | 135 | ||||
| -rw-r--r-- | cpu/mpc512x/start.S | 780 | ||||
| -rw-r--r-- | cpu/mpc512x/traps.c | 205 | ||||
| -rw-r--r-- | include/asm-ppc/e300.h | 1 | ||||
| -rw-r--r-- | include/asm-ppc/global_data.h | 4 | ||||
| -rw-r--r-- | include/asm-ppc/immap_512x.h | 569 | ||||
| -rw-r--r-- | include/common.h | 8 | ||||
| -rw-r--r-- | include/configs/ads5121.h | 410 | ||||
| -rw-r--r-- | include/mpc512x.h | 398 | ||||
| -rw-r--r-- | net/eth.c | 4 | 
25 files changed, 4911 insertions, 2 deletions
| @@ -44,6 +44,14 @@ LIST_5xxx="	\  "  ######################################################################### +## MPC512x Systems +######################################################################### + +LIST_512x="	\ +	ads5121							\ +" + +#########################################################################  ## MPC8xx Systems  #########################################################################  LIST_8xx="	\ @@ -365,7 +373,7 @@ do  	microblaze| \  	mips|mips_el| \  	nios|nios2| \ -	ppc|5xx|5xxx|8xx|8220|824x|8260|83xx|85xx|86xx|4xx|7xx|74xx| \ +	ppc|5xx|5xxx|512x|8xx|8220|824x|8260|83xx|85xx|86xx|4xx|7xx|74xx| \  	x86|I486)  			for target in `eval echo '$LIST_'${arg}`  			do @@ -642,6 +642,13 @@ motionpro_config:         unconfig  ######################################################################### +## MPC512x Systems +######################################################################### +ads5121_config: unconfig +	@$(MKCONFIG) ads5121 ppc mpc512x ads5121 + + +#########################################################################  ## MPC8xx Systems  ######################################################################### diff --git a/board/ads5121/Makefile b/board/ads5121/Makefile new file mode 100644 index 000000000..cd8148c43 --- /dev/null +++ b/board/ads5121/Makefile @@ -0,0 +1,50 @@ +# +# (C) Copyright 2007 +# 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	= $(obj)lib$(BOARD).a + +COBJS	:= $(BOARD).o + +SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS)) +SOBJS	:= $(addprefix $(obj),$(SOBJS)) + +$(LIB):	$(obj).depend $(OBJS) +	$(AR) $(ARFLAGS) $@ $(OBJS) + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/ads5121/ads5121.c b/board/ads5121/ads5121.c new file mode 100644 index 000000000..0a99a34ac --- /dev/null +++ b/board/ads5121/ads5121.c @@ -0,0 +1,188 @@ +/* + * (C) Copyright 2007 DENX Software Engineering + * + * 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 <mpc512x.h> +#include <asm/bitops.h> +#include <command.h> + +/* Clocks in use */ +#define SCCR1_CLOCKS_EN	(CLOCK_SCCR1_CFG_EN |				\ +			 CLOCK_SCCR1_LPC_EN |				\ +			 CLOCK_SCCR1_PSC_EN(CONFIG_PSC_CONSOLE) |	\ +			 CLOCK_SCCR1_PSCFIFO_EN |			\ +			 CLOCK_SCCR1_DDR_EN |				\ +			 CLOCK_SCCR1_FEC_EN) + +#define SCCR2_CLOCKS_EN	(CLOCK_SCCR2_MEM_EN |		\ +			 CLOCK_SCCR2_SPDIF_EN |		\ +			 CLOCK_SCCR2_I2C_EN) + +#define CSAW_START(start)	((start) & 0xFFFF0000) +#define CSAW_STOP(start, size)	(((start) + (size) - 1) >> 16) + +long int fixed_sdram(void); + +int board_early_init_f (void) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	u32 lpcaw; + +	/* +	 * Initialize Local Window for the CPLD registers access (CS2 selects +	 * the CPLD chip) +	 */ +	im->sysconf.lpcs2aw = CSAW_START(CFG_CPLD_BASE) | +			      CSAW_STOP(CFG_CPLD_BASE, CFG_CPLD_SIZE); +	im->lpc.cs_cfg[2] = CFG_CS2_CFG; + +	/* +	 * According to MPC5121e RM, configuring local access windows should +	 * be followed by a dummy read of the config register that was +	 * modified last and an isync +	 */ +	lpcaw = im->sysconf.lpcs2aw; +	__asm__ __volatile__ ("isync"); + +	/* +	 * Disable Boot NOR FLASH write protect - CPLD Reg 8 NOR FLASH Control +	 * +	 * Without this the flash identification routine fails, as it needs to issue +	 * write commands in order to establish the device ID. +	 */ +	*((volatile u8 *)(CFG_CPLD_BASE + 0x08)) = 0xC1; + +	/* +	 * Enable clocks +	 */ +	im->clk.sccr[0] = SCCR1_CLOCKS_EN; +	im->clk.sccr[1] = SCCR2_CLOCKS_EN; + +	return 0; +} + +long int initdram (int board_type) +{ +	u32 msize = 0; + +	puts ("Initializing\n"); +	msize = fixed_sdram (); +	puts ("   DDR RAM: "); + +	return msize; +} + +/* + * fixed sdram init -- the board doesn't use memory modules that have serial presence + * detect or similar mechanism for discovery of the DRAM settings + */ +long int fixed_sdram (void) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	u32 msize = CFG_DDR_SIZE * 1024 * 1024; +	u32 msize_log2 = __ilog2 (msize); +	u32 i; + +	/* Initialize IO Control */ +	im->io_ctrl.regs[MEM_IDX] = IOCTRL_MUX_DDR; + +	/* Initialize DDR Local Window */ +	im->sysconf.ddrlaw.bar = CFG_DDR_BASE & 0xFFFFF000; +	im->sysconf.ddrlaw.ar = msize_log2 - 1; + +	/* +	 * According to MPC5121e RM, configuring local access windows should +	 * be followed by a dummy read of the config register that was +	 * modified last and an isync +         */ +	i = im->sysconf.ddrlaw.ar; +	__asm__ __volatile__ ("isync"); + +	/* Enable DDR */ +	im->mddrc.ddr_sys_config = CFG_MDDRC_SYS_CFG_EN; + +	/* Initialize DDR Priority Manager */ +	im->mddrc.prioman_config1 = CFG_MDDRCGRP_PM_CFG1; +	im->mddrc.prioman_config2 = CFG_MDDRCGRP_PM_CFG2; +	im->mddrc.hiprio_config = CFG_MDDRCGRP_HIPRIO_CFG; +	im->mddrc.lut_table0_main_upper = CFG_MDDRCGRP_LUT0_MU; +	im->mddrc.lut_table1_main_upper = CFG_MDDRCGRP_LUT1_MU; +	im->mddrc.lut_table2_main_upper = CFG_MDDRCGRP_LUT2_MU; +	im->mddrc.lut_table3_main_upper = CFG_MDDRCGRP_LUT3_MU; +	im->mddrc.lut_table4_main_upper = CFG_MDDRCGRP_LUT4_MU; +	im->mddrc.lut_table0_main_lower = CFG_MDDRCGRP_LUT0_ML; +	im->mddrc.lut_table1_main_lower = CFG_MDDRCGRP_LUT1_ML; +	im->mddrc.lut_table2_main_lower = CFG_MDDRCGRP_LUT2_ML; +	im->mddrc.lut_table3_main_lower = CFG_MDDRCGRP_LUT3_ML; +	im->mddrc.lut_table4_main_lower = CFG_MDDRCGRP_LUT4_ML; +	im->mddrc.lut_table0_alternate_upper = CFG_MDDRCGRP_LUT0_AU; +	im->mddrc.lut_table1_alternate_upper = CFG_MDDRCGRP_LUT1_AU; +	im->mddrc.lut_table2_alternate_upper = CFG_MDDRCGRP_LUT2_AU; +	im->mddrc.lut_table3_alternate_upper = CFG_MDDRCGRP_LUT3_AU; +	im->mddrc.lut_table4_alternate_upper = CFG_MDDRCGRP_LUT4_AU; +	im->mddrc.lut_table0_alternate_lower = CFG_MDDRCGRP_LUT0_AU; +	im->mddrc.lut_table1_alternate_lower = CFG_MDDRCGRP_LUT1_AL; +	im->mddrc.lut_table2_alternate_lower = CFG_MDDRCGRP_LUT2_AL; +	im->mddrc.lut_table3_alternate_lower = CFG_MDDRCGRP_LUT3_AL; +	im->mddrc.lut_table4_alternate_lower = CFG_MDDRCGRP_LUT4_AL; + +	/* Initialize MDDRC */ +	im->mddrc.ddr_sys_config = CFG_MDDRC_SYS_CFG; +	im->mddrc.ddr_time_config0 = CFG_MDDRC_TIME_CFG0; +	im->mddrc.ddr_time_config1 = CFG_MDDRC_TIME_CFG1; +	im->mddrc.ddr_time_config2 = CFG_MDDRC_TIME_CFG2; + +	/* Initialize DDR */ +	for (i = 0; i < 10; i++) +		im->mddrc.ddr_command = CFG_MICRON_NOP; + +	im->mddrc.ddr_command = CFG_MICRON_PCHG_ALL; +	im->mddrc.ddr_command = CFG_MICRON_EM2; +	im->mddrc.ddr_command = CFG_MICRON_EM3; +	im->mddrc.ddr_command = CFG_MICRON_EN_DLL; +	im->mddrc.ddr_command = CFG_MICRON_RST_DLL; +	im->mddrc.ddr_command = CFG_MICRON_PCHG_ALL; +	im->mddrc.ddr_command = CFG_MICRON_RFSH; +	im->mddrc.ddr_command = CFG_MICRON_INIT_DEV_OP; +	im->mddrc.ddr_command = CFG_MICRON_OCD_DEFAULT; +	im->mddrc.ddr_command = CFG_MICRON_OCD_EXIT; + +	for (i = 0; i < 10; i++) +		im->mddrc.ddr_command = CFG_MICRON_NOP; + +	/* Start MDDRC */ +	im->mddrc.ddr_time_config0 = CFG_MDDRC_TIME_CFG0_RUN; +	im->mddrc.ddr_sys_config = CFG_MDDRC_SYS_CFG_RUN; + +	return msize; +} + +int checkboard (void) +{ +	ushort brd_rev = *(vu_short *) (CFG_CPLD_BASE + 0x00); +	uchar cpld_rev = *(vu_char *) (CFG_CPLD_BASE + 0x02); + +	printf ("Board: ADS5121 rev. 0x%04x (CPLD rev. 0x%02x)\n", +	        brd_rev, cpld_rev); +	return 0; +} diff --git a/board/ads5121/config.mk b/board/ads5121/config.mk new file mode 100644 index 000000000..14998f475 --- /dev/null +++ b/board/ads5121/config.mk @@ -0,0 +1,23 @@ +# +# (C) Copyright 2007 DENX Software Engineering +# +# 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 +# + +TEXT_BASE  =   0xFFF00000 diff --git a/board/ads5121/u-boot.lds b/board/ads5121/u-boot.lds new file mode 100644 index 000000000..038d84955 --- /dev/null +++ b/board/ads5121/u-boot.lds @@ -0,0 +1,122 @@ +/* + * (C) Copyright 2007 DENX Software Engineering. + * + * 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 + */ + +OUTPUT_ARCH(powerpc) +SECTIONS +{ +  /* Read-only sections, merged into text segment: */ +  . = + SIZEOF_HEADERS; +  .interp : { *(.interp) } +  .hash          : { *(.hash)		} +  .dynsym        : { *(.dynsym)		} +  .dynstr        : { *(.dynstr)		} +  .rel.text      : { *(.rel.text)		} +  .rela.text     : { *(.rela.text) 	} +  .rel.data      : { *(.rel.data)		} +  .rela.data     : { *(.rela.data) 	} +  .rel.rodata    : { *(.rel.rodata) 	} +  .rela.rodata   : { *(.rela.rodata) 	} +  .rel.got       : { *(.rel.got)		} +  .rela.got      : { *(.rela.got)		} +  .rel.ctors     : { *(.rel.ctors)	} +  .rela.ctors    : { *(.rela.ctors)	} +  .rel.dtors     : { *(.rel.dtors)	} +  .rela.dtors    : { *(.rela.dtors)	} +  .rel.bss       : { *(.rel.bss)		} +  .rela.bss      : { *(.rela.bss)		} +  .rel.plt       : { *(.rel.plt)		} +  .rela.plt      : { *(.rela.plt)		} +  .init          : { *(.init)	} +  .plt : { *(.plt) } +  .text      : +  { +    cpu/mpc512x/start.o	(.text) +    *(.text) +    *(.fixup) +    *(.got1) +    . = ALIGN(16); +    *(.rodata) +    *(.rodata1) +    *(.rodata.str1.4) +    *(.eh_frame) +  } +  .fini      : { *(.fini)    } =0 +  .ctors     : { *(.ctors)   } +  .dtors     : { *(.dtors)   } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x0FFF) & 0xFFFFF000; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    *(.got) +    _GOT2_TABLE_ = .; +    *(.got2) +    _FIXUP_TABLE_ = .; +    *(.fixup) +  } +  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2; +  __fixup_entries = (. - _FIXUP_TABLE_) >> 2; + +  .data    : +  { +    *(.data) +    *(.data1) +    *(.sdata) +    *(.sdata2) +    *(.dynamic) +    CONSTRUCTORS +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  . = .; +  __u_boot_cmd_start = .; +  .u_boot_cmd : { *(.u_boot_cmd) } +  __u_boot_cmd_end = .; + + +  . = .; +  __start___ex_table = .; +  __ex_table : { *(__ex_table) } +  __stop___ex_table = .; + +  . = ALIGN(4096); +  __init_begin = .; +  .text.init : { *(.text.init) } +  .data.init : { *(.data.init) } +  . = ALIGN(4096); +  __init_end = .; + +  __bss_start = .; +  .bss       : +  { +   *(.sbss) *(.scommon) +   *(.dynbss) +   *(.bss) +   *(COMMON) +  } +  _end = . ; +  PROVIDE (end = .); +} +ENTRY(_start) diff --git a/cpu/mpc512x/Makefile b/cpu/mpc512x/Makefile new file mode 100644 index 000000000..2be35b2bc --- /dev/null +++ b/cpu/mpc512x/Makefile @@ -0,0 +1,46 @@ +# +# (C) Copyright 2007 DENX Software Engineering +# +# 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	= $(obj)lib$(CPU).a + +START	= start.o +COBJS	= traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o fec.o i2c.o + +SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) +START	:= $(addprefix $(obj),$(START)) + +all:	$(obj).depend $(START) $(LIB) + +$(LIB):	$(OBJS) +	$(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/mpc512x/config.mk b/cpu/mpc512x/config.mk new file mode 100644 index 000000000..8a07c5a3b --- /dev/null +++ b/cpu/mpc512x/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2007 DENX Software Engineering +# +# 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 += -fPIC -ffixed-r14 -meabi + +PLATFORM_CPPFLAGS += -DCONFIG_MPC512X -DCONFIG_E300 \ +			-ffixed-r2 -ffixed-r29 -msoft-float -mcpu=603e diff --git a/cpu/mpc512x/cpu.c b/cpu/mpc512x/cpu.c new file mode 100644 index 000000000..3be565ad0 --- /dev/null +++ b/cpu/mpc512x/cpu.c @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. + * (C) Copyright 2007 DENX Software Engineering + * + * 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 + */ + +/* + * CPU specific code for the MPC512x family. + * + * Derived from the MPC83xx code. + */ + +#include <common.h> +#include <command.h> +#include <mpc512x.h> +#include <asm/processor.h> + +DECLARE_GLOBAL_DATA_PTR; + +int checkcpu (void) +{ +	volatile immap_t *immr = (immap_t *) CFG_IMMR; +	ulong clock = gd->cpu_clk; +	u32 pvr = get_pvr (); +	u32 spridr = immr->sysconf.spridr; +	char buf[32]; + +	puts("CPU: "); + +	switch (spridr & 0xffff0000) { +	case SPR_5121E: +		puts ("MPC5121e "); +		break; +	default: +		printf ("Unknown part ID %08x ", spridr & 0xffff0000); +	} +	printf ("rev. %d.%d, Core ", SVR_MJREV (spridr), SVR_MNREV (spridr)); + +	switch (pvr & 0xffff0000) { +	case PVR_E300C4: +		puts ("e300c4 "); +		break; +	default: +		puts ("unknown "); +	} +	printf ("at %s MHz, CSB at %3d MHz\n", strmhz(buf, clock), +		gd->csb_clk / 1000000); +	return 0; +} + + +int +do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ +	ulong msr; +	volatile immap_t *immap = (immap_t *) CFG_IMMR; + +	/* Interrupts and MMU off */ +	__asm__ __volatile__ ("mfmsr    %0":"=r" (msr):); + +	msr &= ~( MSR_EE | MSR_IR | MSR_DR); +	__asm__ __volatile__ ("mtmsr    %0"::"r" (msr)); + +	/* +	 * Enable Reset Control Reg - "RSTE" is the magic word that let us go +	 */ +	immap->reset.rpr = 0x52535445; + +	/* Verify Reset Control Reg is enabled */ +	while (!((immap->reset.rcer) & RCER_CRE)) +		; + +	printf ("Resetting the board.\n"); +	udelay(200); + +	/* Perform reset */ +	immap->reset.rcr = RCR_SWHR; + +	/* Unreached... */ +	return 1; +} + + +/* + * Get timebase clock frequency (like cpu_clk in Hz) + */ +unsigned long get_tbclk (void) +{ +	ulong tbclk; + +	tbclk = (gd->bus_clk + 3L) / 4L; + +	return tbclk; +} + + +#if defined(CONFIG_WATCHDOG) +void watchdog_reset (void) +{ +	int re_enable = disable_interrupts (); + +	/* Reset watchdog */ +	volatile immap_t *immr = (immap_t *) CFG_IMMR; +	immr->wdt.swsrr = 0x556c; +	immr->wdt.swsrr = 0xaa39; + +	if (re_enable) +		enable_interrupts (); +} +#endif diff --git a/cpu/mpc512x/cpu_init.c b/cpu/mpc512x/cpu_init.c new file mode 100644 index 000000000..566e08b0d --- /dev/null +++ b/cpu/mpc512x/cpu_init.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. + * (C) Copyright 2007 DENX Software Engineering + * + * 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 + * + * Derived from the MPC83xx code. + * + */ + +#include <common.h> +#include <mpc512x.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Set up the memory map, initialize registers, + */ +void cpu_init_f (volatile immap_t * im) +{ +	u32 ips_div; + +	/* Pointer is writable since we allocated a register for it */ +	gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET); + +	/* Clear initial global data */ +	memset ((void *) gd, 0, sizeof (gd_t)); + +	/* system performance tweaking */ + +#ifdef CFG_ACR_PIPE_DEP +	/* Arbiter pipeline depth */ +	im->arbiter.acr = (im->arbiter.acr & ~ACR_PIPE_DEP) | +			  (CFG_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT); +#endif + +#ifdef CFG_ACR_RPTCNT +	/* Arbiter repeat count */ +	im->arbiter.acr = ((im->arbiter.acr & ~(ACR_RPTCNT)) | +			   (CFG_ACR_RPTCNT << ACR_RPTCNT_SHIFT)); +#endif + +	/* RSR - Reset Status Register - clear all status */ +	gd->reset_status = im->reset.rsr; +	im->reset.rsr = ~(RSR_RES); + +	/* +	 * RMR - Reset Mode Register - enable checkstop reset +	 */ +	im->reset.rmr = (RMR_CSRE & (1 << RMR_CSRE_SHIFT)); + +	/* Set IPS-CSB divider: IPS = 1/2 CSB */ +	ips_div = im->clk.scfr[0]; +	ips_div &= ~(SCFR1_IPS_DIV_MASK); +	ips_div |= SCFR1_IPS_DIV << SCFR1_IPS_DIV_SHIFT; +	im->clk.scfr[0] = ips_div; + +	/* +	 * Enable Time Base/Decrementer +	 * +	 * NOTICE: TB needs to be enabled as early as possible in order to +	 * have udelay() working; if not enabled, usually leads to a hang, like +	 * during FLASH chip identification etc.  +	 */ +	im->sysconf.spcr |= SPCR_TBEN; +} + +int cpu_init_r (void) +{ +	return 0; +} diff --git a/cpu/mpc512x/fec.c b/cpu/mpc512x/fec.c new file mode 100644 index 000000000..f1b7a2563 --- /dev/null +++ b/cpu/mpc512x/fec.c @@ -0,0 +1,801 @@ +/* + * (C) Copyright 2003-2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Derived from the MPC8xx FEC driver. + * Adapted for MPC512x by Grzegorz Bernacki <gjb@semihalf.com> + */ + +#include <common.h> +#include <mpc512x.h> +#include <malloc.h> +#include <net.h> +#include <miiphy.h> +#include "fec.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define DEBUG 0 + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ +	defined(CONFIG_MPC512x_FEC) + +#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) +#error "CONFIG_MII has to be defined!" +#endif + +#if (DEBUG & 0x40) +static uint32 local_crc32(char *string, unsigned int crc_value, int len); +#endif + +int fec512x_miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal); +int fec512x_miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data); +int mpc512x_fec_init_phy(struct eth_device *dev, bd_t * bis); + +/********************************************************************/ +#if (DEBUG & 0x2) +static void mpc512x_fec_phydump (char *devname) +{ +	uint16 phyStatus, i; +	uint8 phyAddr = CONFIG_PHY_ADDR; +	uint8 reg_mask[] = { +		/* regs to print: 0...8, 21,27,31 */ +		1, 1, 1, 1,  1, 1, 1, 1,     1, 0, 0, 0,  0, 0, 0, 0, +		0, 0, 0, 0,  0, 1, 0, 0,     0, 0, 0, 1,  0, 0, 0, 1, +	}; + +	for (i = 0; i < 32; i++) { +		if (reg_mask[i]) { +			miiphy_read (devname, phyAddr, i, &phyStatus); +			printf ("Mii reg %d: 0x%04x\n", i, phyStatus); +		} +	} +} +#endif + +/********************************************************************/ +static int mpc512x_fec_bd_init (mpc512x_fec_priv *fec) +{ +	int ix; + +	/* +	 * Receive BDs init +	 */ +	for (ix = 0; ix < FEC_RBD_NUM; ix++) { +		fec->bdBase->rbd[ix].dataPointer = (uint32)&fec->bdBase->recv_frames[ix]; +		fec->bdBase->rbd[ix].status = FEC_RBD_EMPTY; +		fec->bdBase->rbd[ix].dataLength = 0; +	} + +	/* +	 * have the last RBD to close the ring +	 */ +	fec->bdBase->rbd[ix - 1].status |= FEC_RBD_WRAP; +	fec->rbdIndex = 0; + +	/* +	 * Trasmit BDs init +	 */ +	for (ix = 0; ix < FEC_TBD_NUM; ix++) { +                fec->bdBase->tbd[ix].status = 0; +        } + +        /* +         * Have the last TBD to close the ring +         */ +        fec->bdBase->tbd[ix - 1].status |= FEC_TBD_WRAP; + +        /* +         * Initialize some indices +         */ +        fec->tbdIndex = 0; +        fec->usedTbdIndex = 0; +        fec->cleanTbdNum = FEC_TBD_NUM; + +	return 0; +} + +/********************************************************************/ +static void mpc512x_fec_rbd_clean (mpc512x_fec_priv *fec, volatile FEC_RBD * pRbd) +{ +	/* +	 * Reset buffer descriptor as empty +	 */ +	if ((fec->rbdIndex) == (FEC_RBD_NUM - 1)) +		pRbd->status = (FEC_RBD_WRAP | FEC_RBD_EMPTY); +	else +		pRbd->status = FEC_RBD_EMPTY; + +	pRbd->dataLength = 0; + +	/* +	 * Increment BD count +	 */ +	fec->rbdIndex = (fec->rbdIndex + 1) % FEC_RBD_NUM; + +	/* +	 * Now, we have an empty RxBD, notify FEC +	 */ +	fec->eth->r_des_active = 0x01000000;	/* Descriptor polling active */ +} + +/********************************************************************/ +static void mpc512x_fec_tbd_scrub (mpc512x_fec_priv *fec) +{ +	volatile FEC_TBD *pUsedTbd; + +#if (DEBUG & 0x1) +	printf ("tbd_scrub: fec->cleanTbdNum = %d, fec->usedTbdIndex = %d\n", +		fec->cleanTbdNum, fec->usedTbdIndex); +#endif + +	/* +	 * process all the consumed TBDs +	 */ +	while (fec->cleanTbdNum < FEC_TBD_NUM) { +		pUsedTbd = &fec->bdBase->tbd[fec->usedTbdIndex]; +		if (pUsedTbd->status & FEC_TBD_READY) { +#if (DEBUG & 0x20) +			printf ("Cannot clean TBD %d, in use\n", fec->usedTbdIndex); +#endif +			return; +		} + +		/* +		 * clean this buffer descriptor +		 */ +		if (fec->usedTbdIndex == (FEC_TBD_NUM - 1)) +			pUsedTbd->status = FEC_TBD_WRAP; +		else +			pUsedTbd->status = 0; + +		/* +		 * update some indeces for a correct handling of the TBD ring +		 */ +		fec->cleanTbdNum++; +		fec->usedTbdIndex = (fec->usedTbdIndex + 1) % FEC_TBD_NUM; +	} +} + +/********************************************************************/ +static void mpc512x_fec_set_hwaddr (mpc512x_fec_priv *fec, char *mac) +{ +	uint8 currByte;			/* byte for which to compute the CRC */ +	int byte;			/* loop - counter */ +	int bit;			/* loop - counter */ +	uint32 crc = 0xffffffff;	/* initial value */ + +	/* +	 * The algorithm used is the following: +	 * we loop on each of the six bytes of the provided address, +	 * and we compute the CRC by left-shifting the previous +	 * value by one position, so that each bit in the current +	 * byte of the address may contribute the calculation. If +	 * the latter and the MSB in the CRC are different, then +	 * the CRC value so computed is also ex-ored with the +	 * "polynomium generator". The current byte of the address +	 * is also shifted right by one bit at each iteration. +	 * This is because the CRC generatore in hardware is implemented +	 * as a shift-register with as many ex-ores as the radixes +	 * in the polynomium. This suggests that we represent the +	 * polynomiumm itself as a 32-bit constant. +	 */ +	for (byte = 0; byte < 6; byte++) { +		currByte = mac[byte]; +		for (bit = 0; bit < 8; bit++) { +			if ((currByte & 0x01) ^ (crc & 0x01)) { +				crc >>= 1; +				crc = crc ^ 0xedb88320; +			} else { +				crc >>= 1; +			} +			currByte >>= 1; +		} +	} + +	crc = crc >> 26; + +	/* +	 * Set individual hash table register +	 */ +	if (crc >= 32) { +		fec->eth->iaddr1 = (1 << (crc - 32)); +		fec->eth->iaddr2 = 0; +	} else { +		fec->eth->iaddr1 = 0; +		fec->eth->iaddr2 = (1 << crc); +	} + +	/* +	 * Set physical address +	 */ +	fec->eth->paddr1 = (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3]; +	fec->eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808; +} + +/********************************************************************/ +static int mpc512x_fec_init (struct eth_device *dev, bd_t * bis) +{ +	mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv; + +#if (DEBUG & 0x1) +	printf ("mpc512x_fec_init... Begin\n"); +#endif + +	/* Set interrupt mask register */ +	fec->eth->imask = 0x00000000; + +	/* Clear FEC-Lite interrupt event register(IEVENT) */ +	fec->eth->ievent = 0xffffffff; + +	/* Set transmit fifo watermark register(X_WMRK), default = 64 */ +	fec->eth->x_wmrk = 0x0; + +	/* Set Opcode/Pause Duration Register */ +	fec->eth->op_pause = 0x00010020; + +	/* Frame length=1518; MII mode */ +	fec->eth->r_cntrl = 0x05ee000c; + +	/* Half-duplex, heartbeat disabled */ +	fec->eth->x_cntrl = 0x00000000;  + +	/* Enable MIB counters */ +	fec->eth->mib_control = 0x0; + +	/* Setup recv fifo start and buff size */ +	fec->eth->r_fstart = 0x500; +	fec->eth->r_buff_size = 0x5e0; + +	/* Setup BD base addresses */ +	fec->eth->r_des_start = (uint32)fec->bdBase->rbd; +	fec->eth->x_des_start = (uint32)fec->bdBase->tbd; + +	/* DMA Control */ +	fec->eth->dma_control = 0xc0000000; + +	/* Enable FEC */ +	fec->eth->ecntrl |= 0x00000006; + +	/* Initilize addresses and status words of BDs */ +	mpc512x_fec_bd_init (fec); + +	 /* Descriptor polling active */	 +	fec->eth->r_des_active = 0x01000000; + +#if (DEBUG & 0x1) +	printf("mpc512x_fec_init... Done \n"); +#endif +	return 1; +} + +/********************************************************************/ +int mpc512x_fec_init_phy (struct eth_device *dev, bd_t * bis) +{ +	mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv; +	const uint8 phyAddr = CONFIG_PHY_ADDR;	/* Only one PHY */ +	int timeout = 1; +	uint16 phyStatus; + +#if (DEBUG & 0x1) +	printf ("mpc512x_fec_init_phy... Begin\n"); +#endif + +	/* +	 * Clear FEC-Lite interrupt event register(IEVENT) +	 */ +	fec->eth->ievent = 0xffffffff; + +	/* +	 * Set interrupt mask register +	 */ +	fec->eth->imask = 0x00000000; + +	if (fec->xcv_type != SEVENWIRE) { +		/* +		 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock +		 * and do not drop the Preamble. +		 */ +		fec->eth->mii_speed = (((gd->ipb_clk / 1000000) / 5) + 1) << 1;	 + +		/* +		 * Reset PHY, then delay 300ns +		 */ +		miiphy_write (dev->name, phyAddr, 0x0, 0x8000); +		udelay (1000); + +		if (fec->xcv_type == MII10) { +		/* +		 * Force 10Base-T, FDX operation +		 */ +#if (DEBUG & 0x2) +			printf ("Forcing 10 Mbps ethernet link... "); +#endif +			miiphy_read (dev->name, phyAddr, 0x1, &phyStatus); +			 +			miiphy_write (dev->name, phyAddr, 0x0, 0x0180); + +			timeout = 20; +			do {    /* wait for link status to go down */ +				udelay (10000); +				if ((timeout--) == 0) { +#if (DEBUG & 0x2) +					printf ("hmmm, should not have waited..."); +#endif +					break; +				} +				miiphy_read (dev->name, phyAddr, 0x1, &phyStatus); +#if (DEBUG & 0x2) +				printf ("="); +#endif +			} while ((phyStatus & 0x0004)); /* !link up */ + +			timeout = 1000; +			do {    /* wait for link status to come back up */ +				udelay (10000); +				if ((timeout--) == 0) { +					printf ("failed. Link is down.\n"); +					break; +				} +				miiphy_read (dev->name, phyAddr, 0x1, &phyStatus); +#if (DEBUG & 0x2) +				printf ("+"); +#endif +			} while (!(phyStatus & 0x0004)); /* !link up */ + +#if (DEBUG & 0x2) +			printf ("done.\n"); +#endif +		} else {        /* MII100 */ +			/* +			 * Set the auto-negotiation advertisement register bits +			 */ +			miiphy_write (dev->name, phyAddr, 0x4, 0x01e1); + +			/* +			 * Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation +			 */ +			miiphy_write (dev->name, phyAddr, 0x0, 0x1200); + +			/* +			 * Wait for AN completion +			 */ +			timeout = 50000; +			do { +				udelay (1000); + +				if ((timeout--) == 0) { +#if (DEBUG & 0x2) +					printf ("PHY auto neg 0 failed...\n"); +#endif +					return -1; +				} + +				if (miiphy_read (dev->name, phyAddr, 0x1, &phyStatus) != 0) { +#if (DEBUG & 0x2) +					printf ("PHY auto neg 1 failed 0x%04x...\n", phyStatus); +#endif +					return -1; +				} +			} while (!(phyStatus & 0x0004)); + +#if (DEBUG & 0x2) +			printf ("PHY auto neg complete! \n"); +#endif +		} +	} + +#if (DEBUG & 0x2) +	if (fec->xcv_type != SEVENWIRE) +		mpc512x_fec_phydump (dev->name); +#endif + +#if (DEBUG & 0x1) +	printf ("mpc512x_fec_init_phy... Done \n"); +#endif +	return 1; +} + +/********************************************************************/ +static void mpc512x_fec_halt (struct eth_device *dev) +{ +	mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv; +	int counter = 0xffff; + +#if (DEBUG & 0x2) +	if (fec->xcv_type != SEVENWIRE) +		mpc512x_fec_phydump (dev->name); +#endif + +	/* +	 * mask FEC chip interrupts +	 */ +	fec->eth->imask = 0; + +	/* +	 * issue graceful stop command to the FEC transmitter if necessary +	 */ +	fec->eth->x_cntrl |= 0x00000001; + +	/* +	 * wait for graceful stop to register +	 */ +	while ((counter--) && (!(fec->eth->ievent & 0x10000000))) ; + +	/* +	 * Disable the Ethernet Controller +	 */ +	fec->eth->ecntrl &= 0xfffffffd; + +	/* +	 * Issue a reset command to the FEC chip +	 */ +	fec->eth->ecntrl |= 0x1; + +	/* +	 * wait at least 16 clock cycles +	 */ +	udelay (10); +#if (DEBUG & 0x3) +	printf ("Ethernet task stopped\n"); +#endif +} + +/********************************************************************/ + +static int mpc512x_fec_send (struct eth_device *dev, volatile void *eth_data, +		int data_length) +{ +	/* +	 * This routine transmits one frame.  This routine only accepts +	 * 6-byte Ethernet addresses. +	 */ +	mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv; +	volatile FEC_TBD *pTbd; + +#if (DEBUG & 0x20) +	printf("tbd status: 0x%04x\n", fec->tbdBase[fec->tbdIndex].status); +#endif + +	/* +	 * Clear Tx BD ring at first +	 */ +	mpc512x_fec_tbd_scrub (fec); + +	/* +	 * Check for valid length of data. +	 */ +	if ((data_length > 1500) || (data_length <= 0)) { +		return -1; +	} + +	/* +	 * Check the number of vacant TxBDs. +	 */ +	if (fec->cleanTbdNum < 1) { +#if (DEBUG & 0x20) +		printf ("No available TxBDs ...\n"); +#endif +		return -1; +	} + +	/* +	 * Get the first TxBD to send the mac header +	 */ +	pTbd = &fec->bdBase->tbd[fec->tbdIndex]; +	pTbd->dataLength = data_length; +	pTbd->dataPointer = (uint32)eth_data; +	pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY; +	fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM; +	 +	/* Activate transmit Buffer Descriptor polling */ +	fec->eth->x_des_active = 0x01000000;	/* Descriptor polling active	*/ + +#if (DEBUG & 0x8) +	printf ( "+" ); +#endif + +	fec->cleanTbdNum -= 1; + +	/* +	 * wait until frame is sent . +	 */ +	while (pTbd->status & FEC_TBD_READY) { +		udelay (10); +#if (DEBUG & 0x8) +		printf ("TDB status = %04x\n", pTbd->status); +#endif +	} + +	return 0; +} + + +/********************************************************************/ +static int mpc512x_fec_recv (struct eth_device *dev) +{ +	/* +	 * This command pulls one frame from the card +	 */ +	mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv; +	volatile FEC_RBD *pRbd = &fec->bdBase->rbd[fec->rbdIndex]; +	unsigned long ievent; +	int frame_length, len = 0; +	uchar buff[FEC_MAX_PKT_SIZE]; + +#if (DEBUG & 0x1) +	printf ("mpc512x_fec_recv %d Start...\n", fec->rbdIndex); +#endif +#if (DEBUG & 0x8) +	printf( "-" ); +#endif +	 +	/* +	 * Check if any critical events have happened +	 */ +	ievent = fec->eth->ievent; +	fec->eth->ievent = ievent; +	if (ievent & 0x20060000) { +		/* BABT, Rx/Tx FIFO errors */ +		mpc512x_fec_halt (dev); +		mpc512x_fec_init (dev, NULL); +		return 0; +	} +	if (ievent & 0x80000000) { +		/* Heartbeat error */ +		fec->eth->x_cntrl |= 0x00000001; +	} +	if (ievent & 0x10000000) { +		/* Graceful stop complete */ +		if (fec->eth->x_cntrl & 0x00000001) { +			mpc512x_fec_halt (dev); +			fec->eth->x_cntrl &= ~0x00000001; +			mpc512x_fec_init (dev, NULL); +		} +	} + +	if (!(pRbd->status & FEC_RBD_EMPTY)) { +		if ((pRbd->status & FEC_RBD_LAST) &&  +			!(pRbd->status & FEC_RBD_ERR) && +			((pRbd->dataLength - 4) > 14)) { +			 +			/* +			 * Get buffer size +			 */ +			frame_length = pRbd->dataLength - 4; + +#if (DEBUG & 0x20) +			{ +				int i; +				printf ("recv data hdr:"); +				for (i = 0; i < 14; i++) +					printf ("%x ", *((uint8*)pRbd->dataPointer + i)); +				printf("\n"); +			} +#endif + +			/* +			 *  Fill the buffer and pass it to upper layers +			 */ +			memcpy (buff, (void*)pRbd->dataPointer, frame_length); +			NetReceive ((uchar*)buff, frame_length); +			len = frame_length; +		} + +		/* +		 * Reset buffer descriptor as empty +		 */ +		mpc512x_fec_rbd_clean (fec, pRbd); +	} + +	/* Try to fill Buffer Descriptors */ +	fec->eth->r_des_active = 0x01000000;	/* Descriptor polling active */ +	return len; +} + +/********************************************************************/ +int mpc512x_fec_initialize (bd_t * bis) +{ + +	immap_t *im = (immap_t*) CFG_IMMR; +	mpc512x_fec_priv *fec; +	struct eth_device *dev; +	int i; +	char *tmp, *end, env_enetaddr[6]; +	uint32 *reg; +	void * bd; + +	fec = (mpc512x_fec_priv *) malloc (sizeof(*fec)); +	dev = (struct eth_device *) malloc (sizeof(*dev)); +	memset (dev, 0, sizeof *dev); + +	fec->eth = (ethernet_regs *) MPC512X_FEC; + +# ifndef CONFIG_FEC_10MBIT +	fec->xcv_type = MII100; +# else +	fec->xcv_type = MII10; +# endif +	dev->priv = (void *)fec; +	dev->iobase = MPC512X_FEC; +	dev->init = mpc512x_fec_init; +	dev->halt = mpc512x_fec_halt; +	dev->send = mpc512x_fec_send; +	dev->recv = mpc512x_fec_recv; + +	sprintf (dev->name, "FEC ETHERNET"); +	eth_register (dev); + +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) +	miiphy_register (dev->name, +			fec512x_miiphy_read, fec512x_miiphy_write); +#endif + +	/* +	 * Initialize I\O pins +	 */ +	reg = (uint32 *) &(im->io_ctrl.regs[PSC0_0_IDX]); +	 +	for (i = 0; i < 15; i++) +		reg[i] = IOCTRL_MUX_FEC | 0x00000001; + +	im->io_ctrl.regs[SPDIF_TXCLOCK_IDX] = IOCTRL_MUX_FEC | 0x00000001; +	im->io_ctrl.regs[SPDIF_TX_IDX] = IOCTRL_MUX_FEC | 0x00000001; +	im->io_ctrl.regs[SPDIF_RX_IDX] = IOCTRL_MUX_FEC | 0x00000001; + +	/* Clean up space FEC's MIB and FIFO RAM ...*/ +	memset ((void *) MPC512X_FEC + 0x200, 0x00, 0x400); +	 +	/*  +	 * Malloc space for BDs  (must be quad word-aligned) +	 * this pointer is lost, so cannot be freed  +	 */ +	bd = malloc (sizeof(mpc512x_buff_descs) + 0x1f); +	fec->bdBase = (mpc512x_buff_descs*)((uint32)bd & 0xfffffff0);  +	memset ((void *) bd, 0x00, sizeof(mpc512x_buff_descs) + 0x1f); + +	/* +	 * Set interrupt mask register +	 */ +	fec->eth->imask = 0x00000000; + +	/* +	 * Clear FEC-Lite interrupt event register(IEVENT) +	 */ +	fec->eth->ievent = 0xffffffff; + +	/* +	 * Try to set the mac address now. The fec mac address is +	 * a garbage after reset. When not using fec for booting +	 * the Linux fec driver will try to work with this garbage. +	 */ +	tmp = getenv ("ethaddr"); +	if (tmp) { +		for (i=0; i<6; i++) { +			env_enetaddr[i] = tmp ? simple_strtoul (tmp, &end, 16) : 0; +			if (tmp) +				tmp = (*end) ? end+1 : end; +		} +		mpc512x_fec_set_hwaddr (fec, env_enetaddr); +		fec->eth->gaddr1 = 0x00000000; +		fec->eth->gaddr2 = 0x00000000; +	} + +	mpc512x_fec_init_phy (dev, bis); + +	return 1; +} + +/* MII-interface related functions */ +/********************************************************************/ +int fec512x_miiphy_read (char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal) +{ +	ethernet_regs *eth = (ethernet_regs *) MPC512X_FEC; +	uint32 reg;		/* convenient holder for the PHY register */ +	uint32 phy;		/* convenient holder for the PHY */ +	int timeout = 0xffff; + +	/* +	 * reading from any PHY's register is done by properly +	 * programming the FEC's MII data register. +	 */ +	reg = regAddr << FEC_MII_DATA_RA_SHIFT; +	phy = phyAddr << FEC_MII_DATA_PA_SHIFT; + +	eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy | reg); + +	/* +	 * wait for the related interrupt +	 */ +	while ((timeout--) && (!(eth->ievent & 0x00800000))) ; + +	if (timeout == 0) { +#if (DEBUG & 0x2) +		printf ("Read MDIO failed...\n"); +#endif +		return -1; +	} + +	/* +	 * clear mii interrupt bit +	 */ +	eth->ievent = 0x00800000; + +	/* +	 * it's now safe to read the PHY's register +	 */ +	*retVal = (uint16) eth->mii_data; + +	return 0; +} + +/********************************************************************/ +int fec512x_miiphy_write (char *devname, uint8 phyAddr, uint8 regAddr, uint16 data) +{ +	ethernet_regs *eth = (ethernet_regs *) MPC512X_FEC; +	uint32 reg;		/* convenient holder for the PHY register */ +	uint32 phy;		/* convenient holder for the PHY */ +	int timeout = 0xffff; + +	reg = regAddr << FEC_MII_DATA_RA_SHIFT; +	phy = phyAddr << FEC_MII_DATA_PA_SHIFT; + +	eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR | +			FEC_MII_DATA_TA | phy | reg | data); + +	/* +	 * wait for the MII interrupt +	 */ +	while ((timeout--) && (!(eth->ievent & 0x00800000))) ; + +	if (timeout == 0) { +#if (DEBUG & 0x2) +		printf ("Write MDIO failed...\n"); +#endif +		return -1; +	} + +	/* +	 * clear MII interrupt bit +	 */ +	eth->ievent = 0x00800000; + +	return 0; +} + +#if (DEBUG & 0x40) +static uint32 local_crc32 (char *string, unsigned int crc_value, int len) +{ +	int i; +	char c; +	unsigned int crc, count; + +	/* +	 * crc32 algorithm +	 */ +	/* +	 * crc = 0xffffffff; * The initialized value should be 0xffffffff +	 */ +	crc = crc_value; + +	for (i = len; --i >= 0;) { +		c = *string++; +		for (count = 0; count < 8; count++) { +			if ((c & 0x01) ^ (crc & 0x01)) { +				crc >>= 1; +				crc = crc ^ 0xedb88320; +			} else { +				crc >>= 1; +			} +			c >>= 1; +		} +	} + +	/* +	 * In big endian system, do byte swaping for crc value +	 */ +	 /**/ return crc; +} +#endif	/* DEBUG */ + +#endif /* CONFIG_MPC512x_FEC */ diff --git a/cpu/mpc512x/fec.h b/cpu/mpc512x/fec.h new file mode 100644 index 000000000..71459197a --- /dev/null +++ b/cpu/mpc512x/fec.h @@ -0,0 +1,224 @@ +/* + * (C) Copyright 2003 - 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Derived from the MPC8xx driver's header file. + */ + +#ifndef __MPC512X_FEC_H +#define __MPC512X_FEC_H + +#include <common.h> +#include <mpc512x.h> + +typedef unsigned long uint32; +typedef unsigned short uint16; +typedef unsigned char uint8; + +typedef struct ethernet_register_set { + +/* [10:2]addr = 00 */ + +/*  Control and status Registers (offset 000-1FF) */ + +	volatile uint32 fec_id;			/* MBAR_ETH + 0x000 */ +	volatile uint32 ievent;			/* MBAR_ETH + 0x004 */ +	volatile uint32 imask;			/* MBAR_ETH + 0x008 */ + +	volatile uint32 RES0[1];		/* MBAR_ETH + 0x00C */ +	volatile uint32 r_des_active;		/* MBAR_ETH + 0x010 */ +	volatile uint32 x_des_active;		/* MBAR_ETH + 0x014 */ +	 +	volatile uint32 RES1[3];		/* MBAR_ETH + 0x018-020 */ +	volatile uint32 ecntrl;			/* MBAR_ETH + 0x024 */ + +	volatile uint32 RES2[6];		/* MBAR_ETH + 0x028-03C */ +	volatile uint32 mii_data;		/* MBAR_ETH + 0x040 */ +	volatile uint32 mii_speed;		/* MBAR_ETH + 0x044 */ + +	volatile uint32 RES3[7];		/* MBAR_ETH + 0x048-060 */ +	volatile uint32 mib_control;		/* MBAR_ETH + 0x064 */ + +	volatile uint32 RES4[7];		/* MBAR_ETH + 0x068-80 */ +	volatile uint32 r_cntrl;		/* MBAR_ETH + 0x084 */ +	volatile uint32 r_hash;			/* MBAR_ETH + 0x088 */ +	 +	volatile uint32 RES5[14];		/* MBAR_ETH + 0x08c-0C0 */ +	volatile uint32 x_cntrl;		/* MBAR_ETH + 0x0C4 */ +	 +	volatile uint32 RES6[7];		/* MBAR_ETH + 0x0C8-0E0 */ +	volatile uint32 paddr1;			/* MBAR_ETH + 0x0E4 */ +	volatile uint32 paddr2;			/* MBAR_ETH + 0x0E8 */ +	volatile uint32 op_pause;		/* MBAR_ETH + 0x0EC */ + +	volatile uint32 RES7[10];		/* MBAR_ETH + 0x0F0-114 */ +	volatile uint32 iaddr1;			/* MBAR_ETH + 0x118 */ +	volatile uint32 iaddr2;			/* MBAR_ETH + 0x11C */ +	volatile uint32 gaddr1;			/* MBAR_ETH + 0x120 */ +	volatile uint32 gaddr2;			/* MBAR_ETH + 0x124 */ + +	volatile uint32 RES8[6];		/* MBAR_ETH + 0x128-13C */ +	volatile uint32 fifo_id;		/* MBAR_ETH + 0x140 */ +	volatile uint32 x_wmrk;			/* MBAR_ETH + 0x144 */ +	volatile uint32 RES9[1];		/* MBAR_ETH + 0x148 */ +	volatile uint32 r_bound;		/* MBAR_ETH + 0x14C */ +	volatile uint32 r_fstart;		/* MBAR_ETH + 0x150 */ +	 +	volatile uint32 RES10[11];		/* MBAR_ETH + 0x154-17C */ +	volatile uint32 r_des_start;		/* MBAR_ETH + 0x180 */ +	volatile uint32 x_des_start;		/* MBAR_ETH + 0x184 */ +	volatile uint32 r_buff_size;		/* MBAR_ETH + 0x188 */ +	volatile uint32 RES11[26];		/* MBAR_ETH + 0x18C-1F0 */ +	volatile uint32 dma_control;		/* MBAR_ETH + 0x1F4 */ +	volatile uint32 RES12[2];		/* MBAR_ETH + 0x1F8-1FC */ + +/*  MIB COUNTERS (Offset 200-2FF) */ + +	volatile uint32 rmon_t_drop;		/* MBAR_ETH + 0x200 */ +	volatile uint32 rmon_t_packets;		/* MBAR_ETH + 0x204 */ +	volatile uint32 rmon_t_bc_pkt;		/* MBAR_ETH + 0x208 */ +	volatile uint32 rmon_t_mc_pkt;		/* MBAR_ETH + 0x20C */ +	volatile uint32 rmon_t_crc_align;	/* MBAR_ETH + 0x210 */ +	volatile uint32 rmon_t_undersize;	/* MBAR_ETH + 0x214 */ +	volatile uint32 rmon_t_oversize;	/* MBAR_ETH + 0x218 */ +	volatile uint32 rmon_t_frag;		/* MBAR_ETH + 0x21C */ +	volatile uint32 rmon_t_jab;		/* MBAR_ETH + 0x220 */ +	volatile uint32 rmon_t_col;		/* MBAR_ETH + 0x224 */ +	volatile uint32 rmon_t_p64;		/* MBAR_ETH + 0x228 */ +	volatile uint32 rmon_t_p65to127;	/* MBAR_ETH + 0x22C */ +	volatile uint32 rmon_t_p128to255;	/* MBAR_ETH + 0x230 */ +	volatile uint32 rmon_t_p256to511;	/* MBAR_ETH + 0x234 */ +	volatile uint32 rmon_t_p512to1023;	/* MBAR_ETH + 0x238 */ +	volatile uint32 rmon_t_p1024to2047;	/* MBAR_ETH + 0x23C */ +	volatile uint32 rmon_t_p_gte2048;	/* MBAR_ETH + 0x240 */ +	volatile uint32 rmon_t_octets;		/* MBAR_ETH + 0x244 */ +	volatile uint32 ieee_t_drop;		/* MBAR_ETH + 0x248 */ +	volatile uint32 ieee_t_frame_ok;	/* MBAR_ETH + 0x24C */ +	volatile uint32 ieee_t_1col;		/* MBAR_ETH + 0x250 */ +	volatile uint32 ieee_t_mcol;		/* MBAR_ETH + 0x254 */ +	volatile uint32 ieee_t_def;		/* MBAR_ETH + 0x258 */ +	volatile uint32 ieee_t_lcol;		/* MBAR_ETH + 0x25C */ +	volatile uint32 ieee_t_excol;		/* MBAR_ETH + 0x260 */ +	volatile uint32 ieee_t_macerr;		/* MBAR_ETH + 0x264 */ +	volatile uint32 ieee_t_cserr;		/* MBAR_ETH + 0x268 */ +	volatile uint32 ieee_t_sqe;		/* MBAR_ETH + 0x26C */ +	volatile uint32 t_fdxfc;		/* MBAR_ETH + 0x270 */ +	volatile uint32 ieee_t_octets_ok;	/* MBAR_ETH + 0x274 */ + +	volatile uint32 RES13[2];		/* MBAR_ETH + 0x278-27C */ +	volatile uint32 rmon_r_drop;		/* MBAR_ETH + 0x280 */ +	volatile uint32 rmon_r_packets;		/* MBAR_ETH + 0x284 */ +	volatile uint32 rmon_r_bc_pkt;		/* MBAR_ETH + 0x288 */ +	volatile uint32 rmon_r_mc_pkt;		/* MBAR_ETH + 0x28C */ +	volatile uint32 rmon_r_crc_align;	/* MBAR_ETH + 0x290 */ +	volatile uint32 rmon_r_undersize;	/* MBAR_ETH + 0x294 */ +	volatile uint32 rmon_r_oversize;	/* MBAR_ETH + 0x298 */ +	volatile uint32 rmon_r_frag;		/* MBAR_ETH + 0x29C */ +	volatile uint32 rmon_r_jab;		/* MBAR_ETH + 0x2A0 */ + +	volatile uint32 rmon_r_resvd_0;		/* MBAR_ETH + 0x2A4 */ + +	volatile uint32 rmon_r_p64;		/* MBAR_ETH + 0x2A8 */ +	volatile uint32 rmon_r_p65to127;	/* MBAR_ETH + 0x2AC */ +	volatile uint32 rmon_r_p128to255;	/* MBAR_ETH + 0x2B0 */ +	volatile uint32 rmon_r_p256to511;	/* MBAR_ETH + 0x2B4 */ +	volatile uint32 rmon_r_p512to1023;	/* MBAR_ETH + 0x2B8 */ +	volatile uint32 rmon_r_p1024to2047;	/* MBAR_ETH + 0x2BC */ +	volatile uint32 rmon_r_p_gte2048;	/* MBAR_ETH + 0x2C0 */ +	volatile uint32 rmon_r_octets;		/* MBAR_ETH + 0x2C4 */ +	volatile uint32 ieee_r_drop;		/* MBAR_ETH + 0x2C8 */ +	volatile uint32 ieee_r_frame_ok;	/* MBAR_ETH + 0x2CC */ +	volatile uint32 ieee_r_crc;		/* MBAR_ETH + 0x2D0 */ +	volatile uint32 ieee_r_align;		/* MBAR_ETH + 0x2D4 */ +	volatile uint32 r_macerr;		/* MBAR_ETH + 0x2D8 */ +	volatile uint32 r_fdxfc;		/* MBAR_ETH + 0x2DC */ +	volatile uint32 ieee_r_octets_ok;	/* MBAR_ETH + 0x2E0 */ + +	volatile uint32 RES14[6];		/* MBAR_ETH + 0x2E4-2FC */ + +	volatile uint32 RES15[64];		/* MBAR_ETH + 0x300-3FF */ +} ethernet_regs; + +/* Receive & Transmit Buffer Descriptor definitions */ +typedef struct BufferDescriptor { +	uint16 status; +	uint16 dataLength; +	uint32 dataPointer; +} FEC_RBD; + +typedef struct { +	uint16 status; +	uint16 dataLength; +	uint32 dataPointer; +} FEC_TBD; + +/* private structure */ +typedef enum { +	SEVENWIRE,			/* 7-wire       */ +	MII10,				/* MII 10Mbps   */ +	MII100				/* MII 100Mbps  */ +} xceiver_type; + +/* BD Numer definitions */ +#define FEC_TBD_NUM		48	/* The user can adjust this value */ +#define FEC_RBD_NUM		32	/* The user can adjust this value */ + +/* packet size limit */ +#define FEC_MAX_PKT_SIZE	1536 + +typedef struct { +	uint8 frame[FEC_MAX_PKT_SIZE]; +} mpc512x_frame; + +typedef struct { +	FEC_RBD rbd[FEC_RBD_NUM];			/* RBD ring */ +	FEC_TBD tbd[FEC_TBD_NUM];			/* TBD ring */ +	mpc512x_frame recv_frames[FEC_RBD_NUM];		/* receive buff */ +} mpc512x_buff_descs; + +typedef struct { +	ethernet_regs *eth; +	xceiver_type xcv_type;		/* transceiver type */ +	mpc512x_buff_descs *bdBase;	/* BD rings and recv buffer */ +	uint16 rbdIndex;		/* next receive BD to read */ +	uint16 tbdIndex;		/* next transmit BD to send */ +	uint16 usedTbdIndex;		/* next transmit BD to clean */ +	uint16 cleanTbdNum;		/* the number of available transmit BDs */ +} mpc512x_fec_priv; + +/* RBD bits definitions */ +#define FEC_RBD_EMPTY		0x8000	/* Buffer is empty */ +#define FEC_RBD_WRAP		0x2000	/* Last BD in ring */ +#define FEC_RBD_LAST		0x0800	/* Buffer is last in frame(useless) */ +#define FEC_RBD_MISS		0x0100	/* Miss bit for prom mode */ +#define FEC_RBD_BC		0x0080	/* The received frame is broadcast frame */ +#define FEC_RBD_MC		0x0040	/* The received frame is multicast frame */ +#define FEC_RBD_LG		0x0020	/* Frame length violation */ +#define FEC_RBD_NO		0x0010	/* Nonoctet align frame */ +#define FEC_RBD_SH		0x0008	/* Short frame */ +#define FEC_RBD_CR		0x0004	/* CRC error */ +#define FEC_RBD_OV		0x0002	/* Receive FIFO overrun */ +#define FEC_RBD_TR		0x0001	/* Frame is truncated */ +#define FEC_RBD_ERR		(FEC_RBD_LG | FEC_RBD_NO | FEC_RBD_CR | \ +				FEC_RBD_OV | FEC_RBD_TR) + +/* TBD bits definitions */ +#define FEC_TBD_READY		0x8000	/* Buffer is ready */ +#define FEC_TBD_WRAP		0x2000	/* Last BD in ring */ +#define FEC_TBD_LAST		0x0800	/* Buffer is last in frame */ +#define FEC_TBD_TC		0x0400	/* Transmit the CRC */ +#define FEC_TBD_ABC		0x0200	/* Append bad CRC */ + +/* MII-related definitios */ +#define FEC_MII_DATA_ST		0x40000000	/* Start of frame delimiter */ +#define FEC_MII_DATA_OP_RD	0x20000000	/* Perform a read operation */ +#define FEC_MII_DATA_OP_WR	0x10000000	/* Perform a write operation */ +#define FEC_MII_DATA_PA_MSK	0x0f800000	/* PHY Address field mask */ +#define FEC_MII_DATA_RA_MSK	0x007c0000	/* PHY Register field mask */ +#define FEC_MII_DATA_TA		0x00020000	/* Turnaround */ +#define FEC_MII_DATA_DATAMSK	0x0000ffff	/* PHY data field */ + +#define FEC_MII_DATA_RA_SHIFT	18	/* MII Register address bits */ +#define FEC_MII_DATA_PA_SHIFT	23	/* MII PHY address bits */ + +#endif	/* __MPC512X_FEC_H */ diff --git a/cpu/mpc512x/i2c.c b/cpu/mpc512x/i2c.c new file mode 100644 index 000000000..00e28d640 --- /dev/null +++ b/cpu/mpc512x/i2c.c @@ -0,0 +1,431 @@ +/* + * (C) Copyright 2003 - 2007 + * 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 + * + * Based on the MPC5xxx code. + */ + +#include <common.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_HARD_I2C + +#include <mpc512x.h> +#include <i2c.h> + +#define immr ((immap_t *)CFG_IMMR) + +/* by default set I2C bus 0 active */ +static unsigned int bus_num = 0; + +#define I2C_TIMEOUT	100 +#define I2C_RETRIES	3 + +struct mpc512x_i2c_tap { +	int scl2tap; +	int tap2tap; +}; + +static int  mpc_reg_in(volatile u32 *reg); +static void mpc_reg_out(volatile u32 *reg, int val, int mask); +static int  wait_for_bb(void); +static int  wait_for_pin(int *status); +static int  do_address(uchar chip, char rdwr_flag); +static int  send_bytes(uchar chip, char *buf, int len); +static int  receive_bytes(uchar chip, char *buf, int len); +static int  mpc_get_fdr(int); + +static int mpc_reg_in (volatile u32 *reg) +{ +	int ret = *reg >> 24; +	__asm__ __volatile__ ("eieio"); +	return ret; +} + +static void mpc_reg_out (volatile u32 *reg, int val, int mask) +{ +	int tmp; + +	if (!mask) { +		*reg = val << 24; +	} else { +		tmp = mpc_reg_in (reg); +		*reg = ((tmp & ~mask) | (val & mask)) << 24; +	} +	__asm__ __volatile__ ("eieio"); + +	return; +} + +static int wait_for_bb (void) +{ +	i2c512x_dev_t *regs = &immr->i2c.dev[bus_num]; +	int timeout = I2C_TIMEOUT; +	int status; + +	status = mpc_reg_in (®s->msr); + +	while (timeout-- && (status & I2C_BB)) { +		volatile int temp; +		mpc_reg_out (®s->mcr, I2C_STA, I2C_STA); +		temp = mpc_reg_in (®s->mdr); +		mpc_reg_out (®s->mcr, 0, I2C_STA); +		mpc_reg_out (®s->mcr, 0, 0); +		mpc_reg_out (®s->mcr, I2C_EN, 0); + +		udelay (1000); +		status = mpc_reg_in (®s->msr); +	} + +	return (status & I2C_BB); +} + +static int wait_for_pin (int *status) +{ +	i2c512x_dev_t *regs = &immr->i2c.dev[bus_num]; +	int timeout = I2C_TIMEOUT; + +	*status = mpc_reg_in (®s->msr); + +	while (timeout-- && !(*status & I2C_IF)) { +		udelay (1000); +		*status = mpc_reg_in (®s->msr); +	} + +	if (!(*status & I2C_IF)) { +		return -1; +	} + +	mpc_reg_out (®s->msr, 0, I2C_IF); + +	return 0; +} + +static int do_address (uchar chip, char rdwr_flag) +{ +	i2c512x_dev_t *regs = &immr->i2c.dev[bus_num]; +	int status; + +	chip <<= 1; + +	if (rdwr_flag) { +		chip |= 1; +	} + +	mpc_reg_out (®s->mcr, I2C_TX, I2C_TX); +	mpc_reg_out (®s->mdr, chip, 0); + +	if (wait_for_pin (&status)) { +		return -2; +	} + +	if (status & I2C_RXAK) { +		return -3; +	} + +	return 0; +} + +static int send_bytes (uchar chip, char *buf, int len) +{ +	i2c512x_dev_t *regs = &immr->i2c.dev[bus_num]; +	int wrcount; +	int status; + +	for (wrcount = 0; wrcount < len; ++wrcount) { + +		mpc_reg_out (®s->mdr, buf[wrcount], 0); + +		if (wait_for_pin (&status)) { +			break; +		} + +		if (status & I2C_RXAK) { +			break; +		} + +	} + +	return !(wrcount == len); +} + +static int receive_bytes (uchar chip, char *buf, int len) +{ +	i2c512x_dev_t *regs = &immr->i2c.dev[bus_num]; +	int dummy   = 1; +	int rdcount = 0; +	int status; +	int i; + +	mpc_reg_out (®s->mcr, 0, I2C_TX); + +	for (i = 0; i < len; ++i) { +		buf[rdcount] = mpc_reg_in (®s->mdr); + +		if (dummy) { +			dummy = 0; +		} else { +			rdcount++; +		} + +		if (wait_for_pin (&status)) { +			return -4; +		} +	} + +	mpc_reg_out (®s->mcr, I2C_TXAK, I2C_TXAK); +	buf[rdcount++] = mpc_reg_in (®s->mdr); + +	if (wait_for_pin (&status)) { +		return -5; +	} + +	mpc_reg_out (®s->mcr, 0, I2C_TXAK); + +	return 0; +} + +/**************** I2C API ****************/ + +void i2c_init (int speed, int saddr) +{ +	int i; +	for(i = 0; i < I2C_BUS_CNT; i++){ +		i2c512x_dev_t *regs = &immr->i2c.dev[i]; +		mpc_reg_out (®s->mcr, 0, 0); + +		/* Set clock */ +		mpc_reg_out (®s->mfdr, mpc_get_fdr (speed), 0); +		mpc_reg_out (®s->madr, saddr << 1, 0); + +		/* Enable module */ +		mpc_reg_out (®s->mcr, I2C_EN, I2C_INIT_MASK); +		mpc_reg_out (®s->msr, 0, I2C_IF); +	} + +	/* Disable interrupts */ +	immr->i2c.icr = 0; +	/* Turn off filters */ +	immr->i2c.mifr = 0; +	return; +} + +static int mpc_get_fdr (int speed) +{ +	static int fdr = -1; + +	if (fdr == -1) { +		ulong best_speed = 0; +		ulong divider; +		ulong ipb, scl; +		ulong bestmatch = 0xffffffffUL; +		int best_i = 0, best_j = 0, i, j; +		int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8}; +		struct mpc512x_i2c_tap scltap[] = { +			{4, 1}, +			{4, 2}, +			{6, 4}, +			{6, 8}, +			{14, 16}, +			{30, 32}, +			{62, 64}, +			{126, 128} +		}; + +		ipb = gd->ipb_clk; +		for (i = 7; i >= 0; i--) { +			for (j = 7; j >= 0; j--) { +				scl = 2 * (scltap[j].scl2tap + +					   (SCL_Tap[i] - 1) * scltap[j].tap2tap +					   + 2); +				if (ipb <= speed*scl) { +					if ((speed*scl - ipb) < bestmatch) { +						bestmatch = speed*scl - ipb; +						best_i = i; +						best_j = j; +						best_speed = ipb/scl; +					} +				} +			} +		} +		divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2); +		if (gd->flags & GD_FLG_RELOC) { +			fdr = divider; +		} else { +			debug("%ld kHz, \n", best_speed / 1000); +			return divider; +		} +	} + +	return fdr; +} + +int i2c_probe (uchar chip) +{ +	i2c512x_dev_t *regs = &immr->i2c.dev[bus_num]; +	int i; + +	for (i = 0; i < I2C_RETRIES; i++) { +		mpc_reg_out (®s->mcr, I2C_STA, I2C_STA); + +		if (! do_address (chip, 0)) { +			mpc_reg_out (®s->mcr, 0, I2C_STA); +			udelay (500); +			break; +		} + +		mpc_reg_out (®s->mcr, 0, I2C_STA); +		udelay (500); +	} + +	return (i == I2C_RETRIES); +} + +int i2c_read (uchar chip, uint addr, int alen, uchar *buf, int len) +{ +	char xaddr[4]; +	i2c512x_dev_t *regs = &immr->i2c.dev[bus_num]; +	int ret = -1; + +	xaddr[0] = (addr >> 24) & 0xFF; +	xaddr[1] = (addr >> 16) & 0xFF; +	xaddr[2] = (addr >>  8) & 0xFF; +	xaddr[3] =  addr	& 0xFF; + +	if (wait_for_bb ()) { +		printf ("i2c_read: bus is busy\n"); +		goto Done; +	} + +	mpc_reg_out (®s->mcr, I2C_STA, I2C_STA); +	if (do_address (chip, 0)) { +		printf ("i2c_read: failed to address chip\n"); +		goto Done; +	} + +	if (send_bytes (chip, &xaddr[4-alen], alen)) { +		printf ("i2c_read: send_bytes failed\n"); +		goto Done; +	} + +	mpc_reg_out (®s->mcr, I2C_RSTA, I2C_RSTA); +	if (do_address (chip, 1)) { +		printf ("i2c_read: failed to address chip\n"); +		goto Done; +	} + +	if (receive_bytes (chip, (char *)buf, len)) { +		printf ("i2c_read: receive_bytes failed\n"); +		goto Done; +	} + +	ret = 0; +Done: +	mpc_reg_out (®s->mcr, 0, I2C_STA); +	return ret; +} + +int i2c_write (uchar chip, uint addr, int alen, uchar *buf, int len) +{ +	char xaddr[4]; +	i2c512x_dev_t *regs = &immr->i2c.dev[bus_num]; +	int ret = -1; + +	xaddr[0] = (addr >> 24) & 0xFF; +	xaddr[1] = (addr >> 16) & 0xFF; +	xaddr[2] = (addr >>  8) & 0xFF; +	xaddr[3] =  addr	& 0xFF; + +	if (wait_for_bb ()) { +		printf ("i2c_write: bus is busy\n"); +		goto Done; +	} + +	mpc_reg_out (®s->mcr, I2C_STA, I2C_STA); +	if (do_address (chip, 0)) { +		printf ("i2c_write: failed to address chip\n"); +		goto Done; +	} + +	if (send_bytes (chip, &xaddr[4-alen], alen)) { +		printf ("i2c_write: send_bytes failed\n"); +		goto Done; +	} + +	if (send_bytes (chip, (char *)buf, len)) { +		printf ("i2c_write: send_bytes failed\n"); +		goto Done; +	} + +	ret = 0; +Done: +	mpc_reg_out (®s->mcr, 0, I2C_STA); +	return ret; +} + +uchar i2c_reg_read (uchar chip, uchar reg) +{ +	uchar buf; + +	i2c_read (chip, reg, 1, &buf, 1); + +	return buf; +} + +void i2c_reg_write (uchar chip, uchar reg, uchar val) +{ +	i2c_write (chip, reg, 1, &val, 1); + +	return; +} + + +int i2c_set_bus_num (unsigned int bus) +{ +	if (bus >= I2C_BUS_CNT) { +		return -1; +	} +	bus_num = bus; + +	return 0; +} + +unsigned int i2c_get_bus_num (void) +{ +	return bus_num; +} + +/* TODO */ +unsigned int i2c_get_bus_speed (void) +{ +	return -1; +} + +int i2c_set_bus_speed (unsigned int speed) +{ +	if (speed != CFG_I2C_SPEED) +		return -1; + +	return 0; +} + +#endif	/* CONFIG_HARD_I2C */ diff --git a/cpu/mpc512x/interrupts.c b/cpu/mpc512x/interrupts.c new file mode 100644 index 000000000..8cc241c89 --- /dev/null +++ b/cpu/mpc512x/interrupts.c @@ -0,0 +1,61 @@ +/* + * (C) Copyright 2000-2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright 2004 Freescale Semiconductor, Inc. + * + * 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 + * + * Derived from the MPC83xx code. + */ + +#include <common.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct irq_action { +	interrupt_handler_t *handler; +	void *arg; +	ulong count; +}; + +int interrupt_init_cpu (unsigned *decrementer_count) +{ +	*decrementer_count = get_tbclk () / CFG_HZ; + +	return 0; +} + +/* + * Install and free an interrupt handler. + */ +void +irq_install_handler (int irq, interrupt_handler_t * handler, void *arg) +{ +} + +void irq_free_handler (int irq) +{ +} + +void timer_interrupt_cpu (struct pt_regs *regs) +{ +	/* nothing to do here */ +	return; +} diff --git a/cpu/mpc512x/serial.c b/cpu/mpc512x/serial.c new file mode 100644 index 000000000..200ff2c49 --- /dev/null +++ b/cpu/mpc512x/serial.c @@ -0,0 +1,197 @@ +/* + * (C) Copyright 2000 - 2007 + * 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 + * + * Based ont the MPC5200 PSC driver. + * Adapted for MPC512x by Jan Wrobel <wrr@semihalf.com> + */ + +/* + * Minimal serial functions needed to use one of the PSC ports + * as serial console interface. + */ + +#include <common.h> + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_PSC_CONSOLE) + +static void fifo_init (volatile psc512x_t *psc) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; + +	/* reset Rx & Tx fifo slice */ +	psc->rfcmd = PSC_FIFO_RESET_SLICE; +	psc->tfcmd = PSC_FIFO_RESET_SLICE; + +	/* disable Tx & Rx FIFO interrupts */ +	psc->rfintmask = 0; +	psc->tfintmask = 0; + +	psc->tfsize = CONSOLE_FIFO_TX_SIZE | (CONSOLE_FIFO_TX_ADDR << 16); +	psc->rfsize = CONSOLE_FIFO_RX_SIZE | (CONSOLE_FIFO_RX_ADDR << 16); + +	/* enable Tx & Rx FIFO slice */ +	psc->rfcmd = PSC_FIFO_ENABLE_SLICE; +	psc->tfcmd = PSC_FIFO_ENABLE_SLICE; + +	im->fifoc.fifoc_cmd = FIFOC_DISABLE_CLOCK_GATE; +	__asm__ volatile ("sync"); +} + +int serial_init(void) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; +	unsigned long baseclk; +	int div; + +	fifo_init (psc); + +	/* set MR register to point to MR1 */ +	psc->command = PSC_SEL_MODE_REG_1; + +	/* disable Tx/Rx */ +	psc->command = PSC_TX_DISABLE | PSC_RX_DISABLE; + +	/* choose the prescaler	by 16 for the Tx/Rx clock generation */ +	psc->psc_clock_select =  0xdd00; + +	/* switch to UART mode */ +	psc->sicr = 0; + +	/* mode register points to mr1 */ +	/* configure parity, bit length and so on in mode register 1*/ +	psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE; +	/* now, mode register points to mr2 */ +	psc->mode = PSC_MODE_1_STOPBIT; + +	/* calculate dividor for setting PSC CTUR and CTLR registers */ +	baseclk = (gd->ipb_clk + 8) / 16; +	div = (baseclk + (gd->baudrate / 2)) / gd->baudrate; + +	psc->ctur = (div >> 8) & 0xff; +	/* set baudrate */ +	psc->ctlr = div & 0xff; + +	/* disable all interrupts */ +	psc->psc_imr = 0; + +	/* reset and enable Rx/Tx */ +	psc->command = PSC_RST_RX; +	psc->command = PSC_RST_TX; +	psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE; + +	return 0; +} + +void serial_putc (const char c) +{ +	volatile immap_t *im = (immap_t *)CFG_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; + +	if (c == '\n') +		serial_putc ('\r'); + +	/* Wait for last character to go. */ +	while (!(psc->psc_status & PSC_SR_TXEMP)) +		; + +	psc->tfdata_8 = c; +} + +void serial_putc_raw (const char c) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; + +	/* Wait for last character to go. */ +	while (!(psc->psc_status & PSC_SR_TXEMP)) +		; + +	psc->tfdata_8 = c; +} + + +void serial_puts (const char *s) +{ +	while (*s) { +		serial_putc (*s++); +	} +} + +int serial_getc (void) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; + +	/* Wait for a character to arrive. */ +	while (psc->rfstat & PSC_FIFO_EMPTY) +		; + +	return psc->rfdata_8; +} + +int serial_tstc (void) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; + +	return !(psc->rfstat & PSC_FIFO_EMPTY); +} + +void serial_setbrg (void) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; +	unsigned long baseclk, div; + +	baseclk = (gd->csb_clk + 8) / 16; +	div = (baseclk + (gd->baudrate / 2)) / gd->baudrate; + +	psc->ctur = (div >> 8) & 0xFF; +	psc->ctlr =  div & 0xff; /* set baudrate */ +} + +void serial_setrts(int s) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; + +	if (s) { +		/* Assert RTS (become LOW) */ +		psc->op1 = 0x1; +	} +	else { +		/* Negate RTS (become HIGH) */ +		psc->op0 = 0x1; +	} +} + +int serial_getcts(void) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; + +	return (psc->ip & 0x1) ? 0 : 1; +} +#endif /* CONFIG_PSC_CONSOLE */ diff --git a/cpu/mpc512x/speed.c b/cpu/mpc512x/speed.c new file mode 100644 index 000000000..9a31155ed --- /dev/null +++ b/cpu/mpc512x/speed.c @@ -0,0 +1,135 @@ +/* + * (C) Copyright 2000-2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. + * + * 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 + * + * Based on the MPC83xx code. + */ + +#include <common.h> +#include <mpc512x.h> +#include <command.h> +#include <asm/processor.h> + +DECLARE_GLOBAL_DATA_PTR; + +static int spmf_mult[] = { +	68, 1, 12, 16, +	20, 24, 28, 32, +	36, 40, 44, 48, +	52, 56, 60, 64 +}; + +static int cpmf_mult[][2] = { +	{0, 1}, {0, 1}, /* 0 and 1 are not valid */ +	{1, 1}, {3, 2}, +	{2, 1}, {5, 2}, +	{3, 1}, {7, 2}, +	{0, 1}, {0, 1}, /* and all above 7 are not valid too */ +	{0, 1}, {0, 1}, +	{0, 1}, {0, 1}, +	{0, 1}, {0, 1} +}; + +static int sys_dividors[][2] = { +	{2, 1}, {5, 2}, {3, 1}, {7, 2}, {4, 1}, +	{9, 2}, {5, 1}, {7, 1}, {6, 1}, {8, 1}, +	{9, 1}, {11, 1}, {10, 1}, {12, 1}, {13, 1}, +	{15, 1}, {14, 1}, {16, 1}, {17, 1}, {19, 1}, +	{18, 1}, {20, 1}, {21, 1}, {23, 1}, {22, 1}, +	{24, 1}, {25, 1}, {27, 1}, {26, 1}, {28, 1}, +	{29, 1}, {31, 1}, {30, 1}, {32, 1}, {33, 1} +}; + +int get_clocks (void) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	u8 spmf; +	u8 cpmf; +	u8 sys_div; +	u8 ips_div; +	u32 ref_clk = CFG_MPC512X_CLKIN; +	u32 spll; +	u32 sys_clk; +	u32 core_clk; +	u32 csb_clk; +	u32 ips_clk; + +	if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im) +		return -1; + +	spmf = (im->clk.spmr & SPMR_SPMF) >> SPMR_SPMF_SHIFT; +	spll = ref_clk * spmf_mult[spmf]; +	 +	sys_div = (im->clk.scfr[1] & SCFR2_SYS_DIV) >> SCFR2_SYS_DIV_SHIFT; +	sys_clk = (spll * sys_dividors[sys_div][1]) / sys_dividors[sys_div][0]; + +	csb_clk = sys_clk / 2; + +        cpmf = (im->clk.spmr & SPMR_CPMF) >> SPMR_CPMF_SHIFT; +        core_clk = (csb_clk * cpmf_mult[cpmf][0]) / cpmf_mult[cpmf][1]; + +	ips_div = (im->clk.scfr[0] & SCFR1_IPS_DIV_MASK) >> SCFR1_IPS_DIV_SHIFT; +	if (ips_div != 0) { +		ips_clk = csb_clk / ips_div; +	} else { +		/* in case we cannot get a sane IPS divisor, fail gracefully */ +		ips_clk = 0; +	} + +	gd->ipb_clk = ips_clk; +	gd->csb_clk = csb_clk; +	gd->cpu_clk = core_clk; +	gd->bus_clk = csb_clk; +	return 0; + +} + +/******************************************** + * get_bus_freq + * return system bus freq in Hz + *********************************************/ +ulong get_bus_freq (ulong dummy) +{ +	return gd->csb_clk; +} + +int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ +	printf ("Clock configuration:\n"); +	printf ("  CPU:                 %4d MHz\n", gd->cpu_clk / 1000000); +	printf ("  Coherent System Bus: %4d MHz\n", gd->csb_clk / 1000000); +	printf ("  IPS Bus:             %4d MHz\n", gd->ipb_clk / 1000000); +	printf ("  DDR:                 %4d MHz\n", 2 * gd->csb_clk / 1000000); +	return 0; +} + +U_BOOT_CMD(clocks, 1, 0, do_clocks, +	"clocks  - print clock configuration\n", +	"    clocks\n" +); + +int prt_mpc512x_clks (void) +{ +	do_clocks (NULL, 0, 0, NULL); +	return (0); +} diff --git a/cpu/mpc512x/start.S b/cpu/mpc512x/start.S new file mode 100644 index 000000000..8b749ac54 --- /dev/null +++ b/cpu/mpc512x/start.S @@ -0,0 +1,780 @@ +/* + * Copyright (C) 1998  Dan Malek <dmalek@jlc.net> + * Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> + * Copyright (C) 2000, 2001, 2002, 2007 Wolfgang Denk <wd@denx.de> + * Copyright Freescale Semiconductor, Inc. 2004, 2006. All rights reserved. + * + * 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 + * + * Based on the MPC83xx code. + */ + +/* + *  U-Boot - Startup Code for MPC512x based Embedded Boards + */ + +#include <config.h> +#include <mpc512x.h> +#include <version.h> + +#define CONFIG_521X	1		/* needed for Linux kernel header files*/ + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +#ifndef  CONFIG_IDENT_STRING +#define  CONFIG_IDENT_STRING "MPC512X" +#endif + +/* + * Floating Point enable, Machine Check and Recoverable Interr. + */ +#undef	MSR_KERNEL +#ifdef DEBUG +#define MSR_KERNEL (MSR_FP|MSR_RI) +#else +#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI) +#endif + +/* Macros for manipulating CSx_START/STOP */ +#define START_REG(start)	((start) >> 16) +#define STOP_REG(start, size)	(((start) + (size) - 1) >> 16) + +/* + * Set up GOT: Global Offset Table + * + * Use r14 to access the GOT + */ +	START_GOT +	GOT_ENTRY(_GOT2_TABLE_) +	GOT_ENTRY(_FIXUP_TABLE_) + +	GOT_ENTRY(_start) +	GOT_ENTRY(_start_of_vectors) +	GOT_ENTRY(_end_of_vectors) +	GOT_ENTRY(transfer_to_handler) + +	GOT_ENTRY(__init_end) +	GOT_ENTRY(_end) +	GOT_ENTRY(__bss_start) +	END_GOT + +/* + * Magic number and version string + */ +	.long	0x27051956		/* U-Boot Magic Number */ +	.globl	version_string +version_string: +	.ascii U_BOOT_VERSION +	.ascii " (", __DATE__, " - ", __TIME__, ")" +	.ascii " ", CONFIG_IDENT_STRING, "\0" + +/* + * Vector Table + */ +	.text +	. = EXC_OFF_SYS_RESET + +	.globl	_start +	/* Start from here after reset/power on */ +_start: +	li	r21, BOOTFLAG_COLD  /* Normal Power-On: Boot from FLASH */ +	b	boot_cold + +	.globl	_start_of_vectors +_start_of_vectors: + +/* Machine check */ +	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException) + +/* Data Storage exception. */ +	STD_EXCEPTION(0x300, DataStorage, UnknownException) + +/* Instruction Storage exception. */ +	STD_EXCEPTION(0x400, InstStorage, UnknownException) + +/* External Interrupt exception. */ +	STD_EXCEPTION(0x500, ExtInterrupt, UnknownException) + +/* Alignment exception. */ +	. = 0x600 +Alignment: +	EXCEPTION_PROLOG(SRR0, SRR1) +	mfspr	r4,DAR +	stw	r4,_DAR(r21) +	mfspr	r5,DSISR +	stw	r5,_DSISR(r21) +	addi	r3,r1,STACK_FRAME_OVERHEAD +	li	r20,MSR_KERNEL +	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */ +	rlwimi	r20,r23,0,25,25		/* copy IP bit from saved MSR */ +	lwz	r6,GOT(transfer_to_handler) +	mtlr	r6 +	blrl +.L_Alignment: +	.long	AlignmentException - _start + EXC_OFF_SYS_RESET +	.long	int_return - _start + EXC_OFF_SYS_RESET + +/* Program check exception */ +	. = 0x700 +ProgramCheck: +	EXCEPTION_PROLOG(SRR0, SRR1) +	addi	r3,r1,STACK_FRAME_OVERHEAD +	li	r20,MSR_KERNEL +	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */ +	rlwimi	r20,r23,0,25,25		/* copy IP bit from saved MSR */ +	lwz	r6,GOT(transfer_to_handler) +	mtlr	r6 +	blrl +.L_ProgramCheck: +	.long	ProgramCheckException - _start + EXC_OFF_SYS_RESET +	.long	int_return - _start + EXC_OFF_SYS_RESET + +/* Floating Point Unit unavailable exception */ +	STD_EXCEPTION(0x800, FPUnavailable, UnknownException) + +/* Decrementer */ +	STD_EXCEPTION(0x900, Decrementer, timer_interrupt) + +/* Critical interrupt */ +	STD_EXCEPTION(0xa00, Critical, UnknownException) + +/* System Call */ +	STD_EXCEPTION(0xc00, SystemCall, UnknownException) + +/* Trace interrupt */ +	STD_EXCEPTION(0xd00, Trace, UnknownException) + +/* Performance Monitor interrupt */ +	STD_EXCEPTION(0xf00, PerfMon, UnknownException) + +/* Intruction Translation Miss */ +	STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException) + +/* Data Load Translation Miss */ +	STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException) + +/* Data Store Translation Miss */ +	STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException) + +/* Instruction Address Breakpoint */ +	STD_EXCEPTION(0x1300, InstructionAddrBreakpoint, DebugException) + +/* System Management interrupt */ +	STD_EXCEPTION(0x1400, SystemMgmtInterrupt, UnknownException) + +	.globl	_end_of_vectors +_end_of_vectors: + +	. = 0x3000 +boot_cold: +	/* Save msr contents */ +	mfmsr	r5 + +	/* Set IMMR area to our preferred location */ +	lis	r4, CONFIG_DEFAULT_IMMR@h +	lis	r3, CFG_IMMR@h +	ori	r3, r3, CFG_IMMR@l +	stw	r3, IMMRBAR(r4) +	mtspr	MBAR, r3		/* IMMRBAR is mirrored into the MBAR SPR (311) */ + +	/* Initialise the machine */ +	bl	cpu_early_init + +	/* +	 * Set up Local Access Windows: +	 * +	 * 1) Boot/CS0 (boot FLASH) +	 * 2) On-chip SRAM (initial stack purposes) +	 */ + +	/* Boot CS/CS0 window range */ +        lis     r3, CFG_IMMR@h +        ori     r3, r3, CFG_IMMR@l + +	lis	r4, START_REG(CFG_FLASH_BASE) +	ori	r4, r4, STOP_REG(CFG_FLASH_BASE, CFG_FLASH_SIZE) +	stw	r4, LPCS0AW(r3) + +	/* +	 * The SRAM window has a fixed size (256K), so only the start address +	 * is necessary +	 */ +	lis 	r4, START_REG(CFG_SRAM_BASE) & 0xff00 +	stw	r4, SRAMBAR(r3) + +	/*  +	 * According to MPC5121e RM, configuring local access windows should +         * be followed by a dummy read of the config register that was +	 * modified last and an isync +         */ +	lwz	r4, SRAMBAR(r3) +	isync + +	/* +	 * Set configuration of the Boot/CS0, the SRAM window does not have a +	 * config register so no params can be set for it +	 */ +	lis     r3, (CFG_IMMR + LPC_OFFSET)@h +        ori     r3, r3, (CFG_IMMR + LPC_OFFSET)@l + +        lis     r4, CFG_CS0_CFG@h +        ori     r4, r4, CFG_CS0_CFG@l +        stw     r4, CS0_CONFIG(r3) + +	/* Master enable all CS's */ +	lis	r4, CS_CTRL_ME@h +	ori	r4, r4, CS_CTRL_ME@l +	stw	r4, CS_CTRL(r3) + +	lis	r4, (CFG_MONITOR_BASE)@h +	ori	r4, r4, (CFG_MONITOR_BASE)@l +	addi	r5, r4, in_flash - _start + EXC_OFF_SYS_RESET +	mtlr	r5 +	blr + +in_flash: +	lis	r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h +	ori	r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l + +	li	r0, 0		/* Make room for stack frame header and	*/ +	stwu	r0, -4(r1)	/* clear final stack frame so that	*/ +	stwu	r0, -4(r1)	/* stack backtraces terminate cleanly	*/ + +	/* let the C-code set up the rest			*/ +	/*							*/ +	/* Be careful to keep code relocatable & stack humble	*/ +	/*------------------------------------------------------*/ + +	GET_GOT			/* initialize GOT access	*/ + +	/* r3: IMMR */ +	lis	r3, CFG_IMMR@h +	/* run low-level CPU init code (in Flash) */ +	bl	cpu_init_f + +	/* r3: BOOTFLAG */ +	mr	r3, r21 +	/* run 1st part of board init code (in Flash) */ +	bl	board_init_f + +	/* NOTREACHED - board_init_f() does not return */ + +/* + * This code finishes saving the registers to the exception frame + * and jumps to the appropriate handler for the exception. + * Register r21 is pointer into trap frame, r1 has new stack pointer. + */ +	.globl	transfer_to_handler +transfer_to_handler: +	stw	r22,_NIP(r21) +	lis	r22,MSR_POW@h +	andc	r23,r23,r22 +	stw	r23,_MSR(r21) +	SAVE_GPR(7, r21) +	SAVE_4GPRS(8, r21) +	SAVE_8GPRS(12, r21) +	SAVE_8GPRS(24, r21) +	mflr	r23 +	andi.	r24,r23,0x3f00		/* get vector offset */ +	stw	r24,TRAP(r21) +	li	r22,0 +	stw	r22,RESULT(r21) +	lwz	r24,0(r23)		/* virtual address of handler */ +	lwz	r23,4(r23)		/* where to go when done */ +	mtspr	SRR0,r24 +	mtspr	SRR1,r20 +	mtlr	r23 +	SYNC +	rfi				/* jump to handler, enable MMU */ + +int_return: +	mfmsr	r28		/* Disable interrupts */ +	li	r4,0 +	ori	r4,r4,MSR_EE +	andc	r28,r28,r4 +	SYNC			/* Some chip revs need this... */ +	mtmsr	r28 +	SYNC +	lwz	r2,_CTR(r1) +	lwz	r0,_LINK(r1) +	mtctr	r2 +	mtlr	r0 +	lwz	r2,_XER(r1) +	lwz	r0,_CCR(r1) +	mtspr	XER,r2 +	mtcrf	0xFF,r0 +	REST_10GPRS(3, r1) +	REST_10GPRS(13, r1) +	REST_8GPRS(23, r1) +	REST_GPR(31, r1) +	lwz	r2,_NIP(r1)	/* Restore environment */ +	lwz	r0,_MSR(r1) +	mtspr	SRR0,r2 +	mtspr	SRR1,r0 +	lwz	r0,GPR0(r1) +	lwz	r2,GPR2(r1) +	lwz	r1,GPR1(r1) +	SYNC +	rfi + +/* + * This code initialises the machine, it expects original MSR contents to be in r5. + */ +cpu_early_init: +	/* Initialize machine status; enable machine check interrupt */ +	/*-----------------------------------------------------------*/ + +	li	r3, MSR_KERNEL			/* Set ME and RI flags */ +	rlwimi	r3, r5, 0, 25, 25		/* preserve IP bit */ +#ifdef DEBUG +	rlwimi	r3, r5, 0, 21, 22		/* debugger might set SE, BE bits */ +#endif +	mtmsr	r3 +	SYNC +	mtspr	SRR1, r3			/* Mirror current MSR state in SRR1 */ + +	lis	r3, CFG_IMMR@h + +#if defined(CONFIG_WATCHDOG) +	/* Initialise the watchdog and reset it */ +	/*--------------------------------------*/ +	lis r4, CFG_WATCHDOG_VALUE +	ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR) +	stw r4, SWCRR(r3) + +	/* reset */ +	li	r4, 0x556C +	sth	r4, SWSRR@l(r3) +	li	r4, 0x0 +	ori	r4, r4, 0xAA39 +	sth	r4, SWSRR@l(r3) +#else +	/* Disable the watchdog */ +	/*----------------------*/ +	lwz r4, SWCRR(r3) +	/* +	 * Check to see if it's enabled for disabling: once disabled by s/w +	 * it's not possible to re-enable it +	 */ +	andi. r4, r4, 0x4 +	beq 1f +	xor r4, r4, r4 +	stw r4, SWCRR(r3) +1: +#endif /* CONFIG_WATCHDOG */ + +	/* Initialize the Hardware Implementation-dependent Registers */ +	/* HID0 also contains cache control			*/ +	/*------------------------------------------------------*/ +	lis	r3, CFG_HID0_INIT@h +	ori	r3, r3, CFG_HID0_INIT@l +	SYNC +	mtspr	HID0, r3 + +	lis	r3, CFG_HID0_FINAL@h +	ori	r3, r3, CFG_HID0_FINAL@l +	SYNC +	mtspr	HID0, r3 + +	lis	r3, CFG_HID2@h +	ori	r3, r3, CFG_HID2@l +	SYNC +	mtspr	HID2, r3 +	sync +	blr + + +/* Cache functions. + * + * Note: requires that all cache bits in + * HID0 are in the low half word. + */ +	.globl	icache_enable +icache_enable: +	mfspr	r3, HID0 +	ori	r3, r3, HID0_ICE +	lis	r4, 0 +	ori	r4, r4, HID0_ILOCK +	andc	r3, r3, r4 +	ori	r4, r3, HID0_ICFI +	isync +	mtspr	HID0, r4    /* sets enable and invalidate, clears lock */ +	isync +	mtspr	HID0, r3	/* clears invalidate */ +	blr + +	.globl	icache_disable +icache_disable: +	mfspr	r3, HID0 +	lis	r4, 0 +	ori	r4, r4, HID0_ICE|HID0_ILOCK +	andc	r3, r3, r4 +	ori	r4, r3, HID0_ICFI +	isync +	mtspr	HID0, r4     /* sets invalidate, clears enable and lock*/ +	isync +	mtspr	HID0, r3	/* clears invalidate */ +	blr + +	.globl	icache_status +icache_status: +	mfspr	r3, HID0 +	rlwinm	r3, r3, (31 - HID0_ICE_SHIFT + 1), 31, 31 +	blr + +	.globl	dcache_enable +dcache_enable: +	mfspr	r3, HID0 +	li	r5, HID0_DCFI|HID0_DLOCK +	andc	r3, r3, r5 +	mtspr	HID0, r3		/* no invalidate, unlock */ +	ori	r3, r3, HID0_DCE +	ori	r5, r3, HID0_DCFI +	mtspr	HID0, r5		/* enable + invalidate */ +	mtspr	HID0, r3		/* enable */ +	sync +	blr + +	.globl	dcache_disable +dcache_disable: +	mfspr	r3, HID0 +	lis	r4, 0 +	ori	r4, r4, HID0_DCE|HID0_DLOCK +	andc	r3, r3, r4 +	ori	r4, r3, HID0_DCI +	sync +	mtspr	HID0, r4	/* sets invalidate, clears enable and lock */ +	sync +	mtspr	HID0, r3	/* clears invalidate */ +	blr + +	.globl	dcache_status +dcache_status: +	mfspr	r3, HID0 +	rlwinm	r3, r3, (31 - HID0_DCE_SHIFT + 1), 31, 31 +	blr + +	.globl get_pvr +get_pvr: +	mfspr	r3, PVR +	blr + +/*------------------------------------------------------------------------------- */ +/* Function:	 ppcDcbf */ +/* Description:	 Data Cache block flush */ +/* Input:	 r3 = effective address */ +/* Output:	 none. */ +/*------------------------------------------------------------------------------- */ +	.globl	ppcDcbf +ppcDcbf: +	dcbf	r0,r3 +	blr + +/*------------------------------------------------------------------------------- */ +/* Function:	 ppcDcbi */ +/* Description:	 Data Cache block Invalidate */ +/* Input:	 r3 = effective address */ +/* Output:	 none. */ +/*------------------------------------------------------------------------------- */ +	.globl	ppcDcbi +ppcDcbi: +	dcbi	r0,r3 +	blr + +/*-------------------------------------------------------------------------- + * Function:	 ppcDcbz + * Description:	 Data Cache block zero. + * Input:	 r3 = effective address + * Output:	 none. + *-------------------------------------------------------------------------- */ + +	.globl	ppcDcbz +ppcDcbz: +	dcbz	r0,r3 +	blr + +	.globl	ppcDWstore +ppcDWstore: +	lfd	1, 0(r4) +	stfd	1, 0(r3) +	blr + +	.globl	ppcDWload +ppcDWload: +	lfd	1, 0(r3) +	stfd	1, 0(r4) +	blr + +/*-------------------------------------------------------------------*/ + +/* + * 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: +	mr	r1,  r3		/* Set new stack pointer	*/ +	mr	r9,  r4		/* Save copy of Global Data pointer */ +	mr	r10, r5		/* Save copy of Destination Address */ + +	mr	r3,  r5				/* Destination Address */ +	lis	r4, CFG_MONITOR_BASE@h		/* Source      Address */ +	ori	r4, r4, CFG_MONITOR_BASE@l +	lwz	r5, GOT(__init_end) +	sub	r5, r5, r4 +	li	r6, CFG_CACHELINE_SIZE		/* Cache Line Size */ + +	/* +	 * Fix GOT pointer: +	 * +	 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) +	 *		+ Destination Address +	 * +	 * Offset: +	 */ +	sub	r15, r10, r4 + +	/* First our own GOT */ +	add	r14, r14, r15 +	/* then the one used by the C code */ +	add	r30, r30, r15 + +	/* +	 * Now relocate code +	 */ +	cmplw	cr1,r3,r4 +	addi	r0,r5,3 +	srwi.	r0,r0,2 +	beq	cr1,4f		/* In place copy is not necessary */ +	beq	7f		/* Protect against 0 count	  */ +	mtctr	r0 +	bge	cr1,2f +	la	r8,-4(r4) +	la	r7,-4(r3) + +	/* copy */ +1:	lwzu	r0,4(r8) +	stwu	r0,4(r7) +	bdnz	1b + +	addi	r0,r5,3 +	srwi.	r0,r0,2 +	mtctr	r0 +	la	r8,-4(r4) +	la	r7,-4(r3) + +	/* and compare */ +20:	lwzu	r20,4(r8) +	lwzu	r21,4(r7) +	xor. r22, r20, r21 +	bne  30f +	bdnz	20b +	b 4f + +	/* compare failed */ +30:	li r3, 0 +	blr + +2:	slwi	r0,r0,2 /* re copy in reverse order ... y do we needed it? */ +	add	r8,r4,r0 +	add	r7,r3,r0 +3:	lwzu	r0,-4(r8) +	stwu	r0,-4(r7) +	bdnz	3b + +/* + * Now flush the cache: note that we must start from a cache aligned + * address. Otherwise we might miss one cache line. + */ +4:	cmpwi	r6,0 +	add	r5,r3,r5 +	beq	7f		/* Always flush prefetch queue in any case */ +	subi	r0,r6,1 +	andc	r3,r3,r0 +	mr	r4,r3 +5:	dcbst	0,r4 +	add	r4,r4,r6 +	cmplw	r4,r5 +	blt	5b +	sync			/* Wait for all dcbst to complete on bus */ +	mr	r4,r3 +6:	icbi	0,r4 +	add	r4,r4,r6 +	cmplw	r4,r5 +	blt	6b +7:	sync			/* Wait for all icbi to complete on bus	*/ +	isync + +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ +	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET +	mtlr	r0 +	blr + +in_ram: +	/* +	 * Relocation Function, r14 point to got2+0x8000 +	 * +	 * Adjust got2 pointers, no need to check for 0, this code +	 * already puts a few entries in the table. +	 */ +	li	r0,__got2_entries@sectoff@l +	la	r3,GOT(_GOT2_TABLE_) +	lwz	r11,GOT(_GOT2_TABLE_) +	mtctr	r0 +	sub	r11,r3,r11 +	addi	r3,r3,-4 +1:	lwzu	r0,4(r3) +	add	r0,r0,r11 +	stw	r0,0(r3) +	bdnz	1b + +	/* +	 * Now adjust the fixups and the pointers to the fixups +	 * in case we need to move ourselves again. +	 */ +2:	li	r0,__fixup_entries@sectoff@l +	lwz	r3,GOT(_FIXUP_TABLE_) +	cmpwi	r0,0 +	mtctr	r0 +	addi	r3,r3,-4 +	beq	4f +3:	lwzu	r4,4(r3) +	lwzux	r0,r4,r11 +	add	r0,r0,r11 +	stw	r10,0(r3) +	stw	r0,0(r4) +	bdnz	3b +4: +clear_bss: +	/* +	 * Now clear BSS segment +	 */ +	lwz	r3,GOT(__bss_start) +	lwz	r4,GOT(_end) + +	cmplw	0, r3, r4 +	beq	6f + +	li	r0, 0 +5: +	stw	r0, 0(r3) +	addi	r3, r3, 4 +	cmplw	0, r3, r4 +	bne	5b +6: +	mr	r3, r9		/* Global Data pointer		*/ +	mr	r4, r10		/* Destination Address		*/ +	bl	board_init_r + +	/* +	 * Copy exception vector code to low memory +	 * +	 * r3: dest_addr +	 * r7: source address, r8: end address, r9: target address +	 */ +	.globl	trap_init +trap_init: +	lwz	r7, GOT(_start) +	lwz	r8, GOT(_end_of_vectors) + +	li	r9, 0x100	/* reset vector at 0x100 */ + +	cmplw	0, r7, r8 +	bgelr			/* return if r7>=r8 - just in case */ + +	mflr	r4		/* save link register */ +1: +	lwz	r0, 0(r7) +	stw	r0, 0(r9) +	addi	r7, r7, 4 +	addi	r9, r9, 4 +	cmplw	0, r7, r8 +	bne	1b + +	/* +	 * relocate `hdlr' and `int_return' entries +	 */ +	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET +	li	r8, Alignment - _start + EXC_OFF_SYS_RESET +2: +	bl	trap_reloc +	addi	r7, r7, 0x100		/* next exception vector */ +	cmplw	0, r7, r8 +	blt	2b + +	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET +	bl	trap_reloc + +	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET +	bl	trap_reloc + +	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET +	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET +3: +	bl	trap_reloc +	addi	r7, r7, 0x100		/* next exception vector */ +	cmplw	0, r7, r8 +	blt	3b + +	li	r7, .L_Trace - _start + EXC_OFF_SYS_RESET +	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET +4: +	bl	trap_reloc +	addi	r7, r7, 0x100		/* next exception vector */ +	cmplw	0, r7, r8 +	blt	4b + +	mfmsr	r3			/* now that the vectors have */ +	lis	r7, MSR_IP@h		/* relocated into low memory */ +	ori	r7, r7, MSR_IP@l	/* MSR[IP] can be turned off */ +	andc	r3, r3, r7		/* (if it was on) */ +	SYNC				/* Some chip revs need this... */ +	mtmsr	r3 +	SYNC + +	mtlr	r4			/* restore link register    */ +	blr + +	/* +	 * Function: relocate entries for one exception vector +	 */ +trap_reloc: +	lwz	r0, 0(r7)		/* hdlr ...		*/ +	add	r0, r0, r3		/*  ... += dest_addr	*/ +	stw	r0, 0(r7) + +	lwz	r0, 4(r7)		/* int_return ...	*/ +	add	r0, r0, r3		/*  ... += dest_addr	*/ +	stw	r0, 4(r7) + +	blr diff --git a/cpu/mpc512x/traps.c b/cpu/mpc512x/traps.c new file mode 100644 index 000000000..40281a2cb --- /dev/null +++ b/cpu/mpc512x/traps.c @@ -0,0 +1,205 @@ +/* + * (C) Copyright 2000 - 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org) + * + * 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 + * + * Derived from the MPC83xx code. + */ + +/* + * This file handles the architecture-dependent parts of hardware + * exceptions + */ + +#include <common.h> +#include <asm/processor.h> + +DECLARE_GLOBAL_DATA_PTR; + +extern unsigned long search_exception_table(unsigned long); + +#define END_OF_MEM	(gd->bd->bi_memstart + gd->bd->bi_memsize) + +/* + * Trap & Exception support + */ + +void +print_backtrace (unsigned long *sp) +{ +	int cnt = 0; +	unsigned long i; + +	puts ("Call backtrace: "); +	while (sp) { +		if ((uint)sp > END_OF_MEM) +			break; + +		i = sp[1]; +		if (cnt++ % 7 == 0) +			putc ('\n'); +		printf ("%08lX ", i); +		if (cnt > 32) break; +		sp = (unsigned long *) *sp; +	} +	putc ('\n'); +} + +void show_regs (struct pt_regs * regs) +{ +	int i; + +	printf ("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n", +	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar); +	printf ("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", +	       regs->msr, regs->msr & MSR_EE ? 1 : 0, regs->msr & MSR_PR ? 1 : 0, +	       regs->msr & MSR_FP ? 1 : 0,regs->msr & MSR_ME ? 1 : 0, +	       regs->msr & MSR_IR ? 1 : 0, +	       regs->msr & MSR_DR ? 1 : 0); + +	putc ('\n'); +	for (i = 0;  i < 32;  i++) { +		if ((i % 8) == 0) { +			printf ("GPR%02d: ", i); +		} + +		printf ("%08lX ", regs->gpr[i]); +		if ((i % 8) == 7) { +			putc ('\n'); +		} +	} +} + + +void +_exception (int signr, struct pt_regs *regs) +{ +	show_regs (regs); +	print_backtrace ((unsigned long *)regs->gpr[1]); +	panic ("Exception at pc %lx signal %d", regs->nip,signr); +} + + +void +MachineCheckException (struct pt_regs *regs) +{ +	unsigned long fixup; + +	if ((fixup = search_exception_table (regs->nip)) != 0) { +		regs->nip = fixup; +		return; +	} + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +	if (debugger_exception_handler && (*debugger_exception_handler)(regs)) +		return; +#endif + +	puts ("Machine check.\nCaused by (from msr): "); +	printf ("regs %p ",regs); +	switch (regs->msr & 0x00FF0000) { +	case (0x80000000 >> 10): +		puts ("Instruction cache parity signal\n"); +		break; +	case (0x80000000 >> 11): +		puts ("Data cache parity signal\n"); +		break; +	case (0x80000000 >> 12): +		puts ("Machine check signal\n"); +		break; +	case (0x80000000 >> 13): +		puts ("Transfer error ack signal\n"); +		break; +	case (0x80000000 >> 14): +		puts ("Data parity signal\n"); +		break; +	case (0x80000000 >> 15): +		puts ("Address parity signal\n"); +		break; +	default: +		puts ("Unknown values in msr\n"); +	} +	show_regs (regs); +	print_backtrace ((unsigned long *)regs->gpr[1]); + +	panic ("machine check"); +} + +void +AlignmentException (struct pt_regs *regs) +{ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +	if (debugger_exception_handler && (*debugger_exception_handler)(regs)) +		return; +#endif +	show_regs (regs); +	print_backtrace ((unsigned long *)regs->gpr[1]); +	panic ("Alignment Exception"); +} + +void +ProgramCheckException (struct pt_regs *regs) +{ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +	if (debugger_exception_handler && (*debugger_exception_handler)(regs)) +		return; +#endif +	show_regs (regs); +	print_backtrace ((unsigned long *)regs->gpr[1]); +	panic ("Program Check Exception"); +} + +void +SoftEmuException (struct pt_regs *regs) +{ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +	if (debugger_exception_handler && (*debugger_exception_handler)(regs)) +		return; +#endif +	show_regs (regs); +	print_backtrace ((unsigned long *)regs->gpr[1]); +	panic ("Software Emulation Exception"); +} + + +void +UnknownException (struct pt_regs *regs) +{ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +	if (debugger_exception_handler && (*debugger_exception_handler)(regs)) +		return; +#endif +	printf ("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", +	       regs->nip, regs->msr, regs->trap); +	_exception (0, regs); +} + +#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) +extern void do_bedbug_breakpoint (struct pt_regs *); +#endif + +void +DebugException (struct pt_regs *regs) +{ +	printf ("Debugger trap at @ %lx\n", regs->nip ); +	show_regs (regs); +#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) +	do_bedbug_breakpoint (regs); +#endif +} diff --git a/include/asm-ppc/e300.h b/include/asm-ppc/e300.h index d1bb159ae..de8239965 100644 --- a/include/asm-ppc/e300.h +++ b/include/asm-ppc/e300.h @@ -9,6 +9,7 @@  #define PVR_E300C1	0x80830000  #define PVR_E300C2	0x80840000  #define PVR_E300C3	0x80850000 +#define PVR_E300C4	0x80860000  /*   * Hardware Implementation-Dependent Register 0 (HID0) diff --git a/include/asm-ppc/global_data.h b/include/asm-ppc/global_data.h index cd2463643..bbaeb3f57 100644 --- a/include/asm-ppc/global_data.h +++ b/include/asm-ppc/global_data.h @@ -85,6 +85,10 @@ typedef	struct	global_data {  	unsigned long	ipb_clk;  	unsigned long	pci_clk;  #endif +#if defined(CONFIG_MPC512X) +	u32 ipb_clk; +	u32 csb_clk; +#endif /* CONFIG_MPC512X */  #if defined(CONFIG_MPC8220)  	unsigned long   bExtUart;  	unsigned long   inp_clk; diff --git a/include/asm-ppc/immap_512x.h b/include/asm-ppc/immap_512x.h new file mode 100644 index 000000000..23d10d4eb --- /dev/null +++ b/include/asm-ppc/immap_512x.h @@ -0,0 +1,569 @@ +/* + * (C) Copyright 2007 DENX Software Engineering + * + * MPC512x Internal Memory Map + * + * 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 + * + * Based on the MPC83xx header. + */ + +#ifndef __IMMAP_512x__ +#define __IMMAP_512x__ + +#include <asm/types.h> + +typedef struct law512x { +	u32 bar;	/* Base Addr Register */ +	u32 ar;		/* Attributes Register */ +} law521x_t; + +/* + * System configuration registers + */ +typedef struct sysconf512x { +	u32 immrbar;		/* Internal memory map base address register */ +	u8 res0[0x1c]; +	u32 lpbaw;		/* LP Boot Access Window */ +	u32 lpcs0aw;		/* LP CS0 Access Window */ +	u32 lpcs1aw;		/* LP CS1 Access Window */ +	u32 lpcs2aw;		/* LP CS2 Access Window */ +	u32 lpcs3aw;		/* LP CS3 Access Window */ +	u32 lpcs4aw;		/* LP CS4 Access Window */ +	u32 lpcs5aw;		/* LP CS5 Access Window */ +	u32 lpcs6aw;		/* LP CS6 Access Window */ +	u32 lpcs7aw;		/* LP CS7 Access Window */ +	u8 res1[0x1c]; +	law521x_t pcilaw[3];	/* PCI Local Access Window 0-2 Registers */ +	u8 res2[0x28]; +	law521x_t ddrlaw;	/* DDR Local Access Window */ +	u8 res3[0x18]; +	u32 mbxbar;		/* MBX Base Address */ +	u32 srambar;		/* SRAM Base Address */ +	u32 nfcbar;		/* NFC Base Address */ +	u8 res4[0x34]; +	u32 spridr;		/* System Part and Revision ID Register */ +	u32 spcr;		/* System Priority Configuration Register */ +	u8 res5[0xf8]; +} sysconf512x_t; + +/* + * Watch Dog Timer (WDT) Registers + */ +typedef struct wdt512x { +	u8 res0[4]; +	u32 swcrr;		/* System watchdog control register */ +	u32 swcnr;		/* System watchdog count register */ +	u8 res1[2]; +	u16 swsrr;		/* System watchdog service register */ +	u8 res2[0xF0]; +} wdt512x_t; + +/* + * RTC Module Registers + */ +typedef struct rtclk512x { +	u8 fixme[0x100]; +} rtclk512x_t; + +/* + * General Purpose Timer + */ +typedef struct gpt512x { +	u8 fixme[0x100]; +} gpt512x_t; + +/* + * Integrated Programmable Interrupt Controller + */ +typedef struct ipic512x { +	u8 fixme[0x100]; +} ipic512x_t; + +/* + * System Arbiter Registers + */ +typedef struct arbiter512x { +	u32 acr;		/* Arbiter Configuration Register */ +	u32 atr;		/* Arbiter Timers Register */ +	u32 ater;		/* Arbiter Transfer Error Register */ +	u32 aer;		/* Arbiter Event Register */ +	u32 aidr;		/* Arbiter Interrupt Definition Register */ +	u32 amr;		/* Arbiter Mask Register */ +	u32 aeatr;		/* Arbiter Event Attributes Register */ +	u32 aeadr;		/* Arbiter Event Address Register */ +	u32 aerr;		/* Arbiter Event Response Register */ +	u8 res1[0xDC]; +} arbiter512x_t; + +/* + * Reset Module + */ +typedef struct reset512x { +	u32 rcwl;		/* Reset Configuration Word Low Register */ +	u32 rcwh;		/* Reset Configuration Word High Register */ +	u8 res0[8]; +	u32 rsr;		/* Reset Status Register */ +	u32 rmr;		/* Reset Mode Register */ +	u32 rpr;		/* Reset protection Register */ +	u32 rcr;		/* Reset Control Register */ +	u32 rcer;		/* Reset Control Enable Register */ +	u8 res1[0xDC]; +} reset512x_t; + +/* + * Clock Module + */ +typedef struct clk512x { +	u32 spmr;		/* System PLL Mode Register */ +	u32 sccr[2];		/* System Clock Control Registers */ +	u32 scfr[2];		/* System Clock Frequency Registers */ +	u8 res0[4]; +	u32 bcr;		/* Bread Crumb Register */ +	u32 pscccr[12];		/* PSC0-11 Clock Control Registers */ +	u32 spccr;		/* SPDIF Clock Control Registers */ +	u32 cccr;		/* CFM Clock Control Registers */ +	u32 dccr;		/* DIU Clock Control Registers */ +	u8 res1[0xa8]; +} clk512x_t; + +/* + * Power Management Control Module + */ +typedef struct pmc512x { +	u8 fixme[0x100]; +} pmc512x_t; + +/* + * General purpose I/O module + */ +typedef struct gpio512x { +	u8 fixme[0x100]; +} gpio512x_t; + +/* + * DDR Memory Controller Memory Map + */ +typedef struct ddr512x { +	u32 ddr_sys_config;	/* System Configuration Register */ +	u32 ddr_time_config0;	/* Timing Configuration Register */ +	u32 ddr_time_config1;	/* Timing Configuration Register */ +	u32 ddr_time_config2;	/* Timing Configuration Register */ +	u32 ddr_command;	/* Command Register */ +	u32 ddr_compact_command;	/* Compact Command Register */ +	u32 self_refresh_cmd_0;	/* Enter/Exit Self Refresh Registers */ +	u32 self_refresh_cmd_1;	/* Enter/Exit Self Refresh Registers */ +	u32 self_refresh_cmd_2;	/* Enter/Exit Self Refresh Registers */ +	u32 self_refresh_cmd_3;	/* Enter/Exit Self Refresh Registers */ +	u32 self_refresh_cmd_4;	/* Enter/Exit Self Refresh Registers */ +	u32 self_refresh_cmd_5;	/* Enter/Exit Self Refresh Registers */ +	u32 self_refresh_cmd_6;	/* Enter/Exit Self Refresh Registers */ +	u32 self_refresh_cmd_7;	/* Enter/Exit Self Refresh Registers */ +	u32 DQS_config_offset_count;	/* DQS Config Offset Count */ +	u32 DQS_config_offset_time;	/* DQS Config Offset Time */ +	u32 DQS_delay_status;	/* DQS Delay Status */ +	u32 res0[0xF]; +	u32 prioman_config1;	/* Priority Manager Configuration */ +	u32 prioman_config2;	/* Priority Manager Configuration */ +	u32 hiprio_config;	/* High Priority Configuration */ +	u32 lut_table0_main_upper;	/* LUT0 Main Upper */ +	u32 lut_table1_main_upper;	/* LUT1 Main Upper */ +	u32 lut_table2_main_upper;	/* LUT2 Main Upper */ +	u32 lut_table3_main_upper;	/* LUT3 Main Upper */ +	u32 lut_table4_main_upper;	/* LUT4 Main Upper */ +	u32 lut_table0_main_lower;	/* LUT0 Main Lower */ +	u32 lut_table1_main_lower;	/* LUT1 Main Lower */ +	u32 lut_table2_main_lower;	/* LUT2 Main Lower */ +	u32 lut_table3_main_lower;	/* LUT3 Main Lower */ +	u32 lut_table4_main_lower;	/* LUT4 Main Lower */ +	u32 lut_table0_alternate_upper;	/* LUT0 Alternate Upper */ +	u32 lut_table1_alternate_upper; /* LUT1 Alternate Upper */ +	u32 lut_table2_alternate_upper; /* LUT2 Alternate Upper */ +	u32 lut_table3_alternate_upper; /* LUT3 Alternate Upper */ +	u32 lut_table4_alternate_upper; /* LUT4 Alternate Upper */ +	u32 lut_table0_alternate_lower; /* LUT0 Alternate Lower */ +	u32 lut_table1_alternate_lower; /* LUT1 Alternate Lower */ +	u32 lut_table2_alternate_lower; /* LUT2 Alternate Lower */ +	u32 lut_table3_alternate_lower; /* LUT3 Alternate Lower */ +	u32 lut_table4_alternate_lower; /* LUT4 Alternate Lower */ +	u32 performance_monitor_config; +	u32 event_time_counter; +	u32 event_time_preset; +	u32 performance_monitor1_address_low; +	u32 performance_monitor2_address_low; +	u32 performance_monitor1_address_hi; +	u32 performance_monitor2_address_hi; +	u32 res1[2]; +	u32 performance_monitor1_read_counter; +	u32 performance_monitor2_read_counter; +	u32 performance_monitor1_write_counter; +	u32 performance_monitor2_write_counter; +	u32 granted_ack_counter0; +	u32 granted_ack_counter1; +	u32 granted_ack_counter2; +	u32 granted_ack_counter3; +	u32 granted_ack_counter4; +	u32 cumulative_wait_counter0; +	u32 cumulative_wait_counter1; +	u32 cumulative_wait_counter2; +	u32 cumulative_wait_counter3; +	u32 cumulative_wait_counter4; +	u32 summed_priority_counter0; +	u32 summed_priority_counter1; +	u32 summed_priority_counter2; +	u32 summed_priority_counter3; +	u32 summed_priority_counter4; +	u32 res2[0x3AD]; +} ddr512x_t; + + +/* + * DMA/Messaging Unit + */ +typedef struct dma512x { +	u8 fixme[0x1800]; +} dma512x_t; + +/* + * PCI Software Configuration Registers + */ +typedef struct pciconf512x { +	u8 fixme[0x80]; +} pciconf512x_t; + +/* + * Sequencer + */ +typedef struct ios512x { +	u8 fixme[0x100]; +} ios512x_t; + +/* + * PCI Controller + */ +typedef struct pcictrl512x { +	u8 fixme[0x100]; +} pcictrl512x_t; + + +/* + * MSCAN + */ +typedef struct mscan512x { +	u8 fixme[0x100]; +} mscan512x_t; + +/* + * BDLC + */ +typedef struct bdlc512x { +	u8 fixme[0x100]; +} bdlc512x_t; + +/* + * SDHC + */ +typedef struct sdhc512x { +	u8 fixme[0x100]; +} sdhc512x_t; + +/* + * SPDIF + */ +typedef struct spdif512x { +	u8 fixme[0x100]; +} spdif512x_t; + +/* + * I2C + */ +typedef struct i2c512x_dev { +	volatile u32 madr;		/* I2Cn + 0x00 */ +	volatile u32 mfdr;		/* I2Cn + 0x04 */ +	volatile u32 mcr;		/* I2Cn + 0x08 */ +	volatile u32 msr;		/* I2Cn + 0x0C */ +	volatile u32 mdr;		/* I2Cn + 0x10 */ +	u8 res0[0x0C]; +} i2c512x_dev_t; + +typedef struct i2c512x { +	i2c512x_dev_t dev[3]; +	volatile u32 icr; +	volatile u32 mifr; +	u8 res0[0x98]; +} i2c512x_t; + +/* + * AXE + */ +typedef struct axe512x { +	u8 fixme[0x100]; +} axe512x_t; + +/* + * DIU + */ +typedef struct diu512x { +	u8 fixme[0x100]; +} diu512x_t; + +/* + * CFM + */ +typedef struct cfm512x { +	u8 fixme[0x100]; +} cfm512x_t; + +/* + * FEC + */ +typedef struct fec512x { +	u8 fixme[0x800]; +} fec512x_t; + +/* + * ULPI + */ +typedef struct ulpi512x { +	u8 fixme[0x600]; +} ulpi512x_t; + +/* + * UTMI + */ +typedef struct utmi512x { +	u8 fixme[0x3000]; +} utmi512x_t; + +/* + * PCI DMA + */ +typedef struct pcidma512x { +	u8 fixme[0x300]; +} pcidma512x_t; + +/* + * IO Control + */ +typedef struct ioctrl512x { +	u32 regs[0x400]; +} ioctrl512x_t; + +/* + * IIM + */ +typedef struct iim512x { +	u8 fixme[0x1000]; +} iim512x_t; + +/* + * LPC + */ +typedef struct lpc512x { +	u32	cs_cfg[8];	/* Chip Select N Configuration Registers +				   No dedicated entry for CS Boot as == CS0 */ +	u32	cs_cr;		/* Chip Select Control Register */ +	u32	cs_sr;		/* Chip Select Status Register */ +	u32	cs_bcr;		/* Chip Select Burst Control Register */ +	u32	cs_dccr;	/* Chip Select Deadcycle Control Register */ +	u32	cs_hccr;	/* Chip Select Holdcycle Control Register */ +	u8	res0[0xcc]; +	u32	sclpc_psr;	/* SCLPC Packet Size Register */ +	u32	sclpc_sar;	/* SCLPC Start Address Register */ +	u32	sclpc_cr;	/* SCLPC Control Register */ +	u32	sclpc_er;	/* SCLPC Enable Register */ +	u32	sclpc_nar;	/* SCLPC NextAddress Register */ +	u32	sclpc_sr;	/* SCLPC Status Register */ +	u32	sclpc_bdr;	/* SCLPC Bytes Done Register */ +	u32	emb_scr;	/* EMB Share Counter Register */ +	u32	emb_pcr;	/* EMB Pause Control Register */ +	u8	res1[0x1c]; +	u32	lpc_fdwr;	/* LPC RX/TX FIFO Data Word Register */ +	u32	lpc_fsr;	/* LPC RX/TX FIFO Status Register */ +	u32	lpc_cr;		/* LPC RX/TX FIFO Control Register */ +	u32	lpc_ar;		/* LPC RX/TX FIFO Alarm Register */ +	u8	res2[0xb0]; +} lpc512x_t; + +/* + * PATA + */ +typedef struct pata512x { +	u8 fixme[0x100]; +} pata512x_t; + +/* + * PSC + */ +typedef struct psc512x { +	volatile u8	mode;		/* PSC + 0x00 */ +	volatile u8	res0[3]; +	union {				/* PSC + 0x04 */ +		volatile u16	status; +		volatile u16	clock_select; +	} sr_csr; +#define psc_status	sr_csr.status +#define psc_clock_select sr_csr.clock_select +	volatile u16	res1; +	volatile u8	command;	/* PSC + 0x08 */ +	volatile u8	res2[3]; +	union {				/* PSC + 0x0c */ +		volatile u8	buffer_8; +		volatile u16	buffer_16; +		volatile u32	buffer_32; +	} buffer; +#define psc_buffer_8	buffer.buffer_8 +#define psc_buffer_16	buffer.buffer_16 +#define psc_buffer_32	buffer.buffer_32 +	union {				/* PSC + 0x10 */ +		volatile u8	ipcr; +		volatile u8	acr; +	} ipcr_acr; +#define psc_ipcr	ipcr_acr.ipcr +#define psc_acr		ipcr_acr.acr +	volatile u8	res3[3]; +	union {				/* PSC + 0x14 */ +		volatile u16	isr; +		volatile u16	imr; +	} isr_imr; +#define psc_isr		isr_imr.isr +#define psc_imr		isr_imr.imr +	volatile u16	res4; +	volatile u8	ctur;		/* PSC + 0x18 */ +	volatile u8	res5[3]; +	volatile u8	ctlr;		/* PSC + 0x1c */ +	volatile u8	res6[3]; +	volatile u32	ccr;		/* PSC + 0x20 */ +	volatile u8	res7[12]; +	volatile u8	ivr;		/* PSC + 0x30 */ +	volatile u8	res8[3]; +	volatile u8	ip;		/* PSC + 0x34 */ +	volatile u8	res9[3]; +	volatile u8	op1;		/* PSC + 0x38 */ +	volatile u8	res10[3]; +	volatile u8	op0;		/* PSC + 0x3c */ +	volatile u8	res11[3]; +	volatile u32	sicr;		/* PSC + 0x40 */ +	volatile u8	res12[60]; +	volatile u32	tfcmd;		/* PSC + 0x80 */ +	volatile u32	tfalarm;	/* PSC + 0x84 */ +	volatile u32	tfstat;		/* PSC + 0x88 */ +	volatile u32	tfintstat;	/* PSC + 0x8C */ +	volatile u32	tfintmask;	/* PSC + 0x90 */ +	volatile u32	tfcount;	/* PSC + 0x94 */ +	volatile u16	tfwptr;		/* PSC + 0x98 */ +	volatile u16	tfrptr;		/* PSC + 0x9A */ +	volatile u32	tfsize;		/* PSC + 0x9C */ +	volatile u8	res13[28]; +	union {				/* PSC + 0xBC */ +		volatile u8	buffer_8; +		volatile u16	buffer_16; +		volatile u32	buffer_32; +	} tfdata_buffer; +#define tfdata_8	tfdata_buffer.buffer_8 +#define tfdata_16	tfdata_buffer.buffer_16 +#define tfdata_32	tfdata_buffer.buffer_32 + +	volatile u32	rfcmd;		/* PSC + 0xC0 */ +	volatile u32	rfalarm;	/* PSC + 0xC4 */ +	volatile u32	rfstat;		/* PSC + 0xC8 */ +	volatile u32	rfintstat;	/* PSC + 0xCC */ +	volatile u32	rfintmask;	/* PSC + 0xD0 */ +	volatile u32	rfcount;	/* PSC + 0xD4 */ +	volatile u16	rfwptr;		/* PSC + 0xD8 */ +	volatile u16	rfrptr;		/* PSC + 0xDA */ +	volatile u32	rfsize;		/* PSC + 0xDC */ +	volatile u8	res18[28]; +	union {				/* PSC + 0xFC */ +		volatile u8	buffer_8; +		volatile u16	buffer_16; +		volatile u32	buffer_32; +	} rfdata_buffer; +#define rfdata_8	rfdata_buffer.buffer_8 +#define rfdata_16	rfdata_buffer.buffer_16 +#define rfdata_32	rfdata_buffer.buffer_32 +} psc512x_t; + +/* + * FIFOC + */ +typedef struct fifoc512x { +	u32 fifoc_cmd; +	u32 fifoc_int; +	u32 fifoc_dma; +	u32 fifoc_axe; +	u32 fifoc_debug; +	u8 fixme[0xEC]; +} fifoc512x_t; + +/* + * SATA + */ +typedef struct sata512x { +	u8 fixme[0x2000]; +} sata512x_t; + +typedef struct immap { +	sysconf512x_t		sysconf;	/* System configuration */ +	u8			res0[0x700]; +	wdt512x_t		wdt;		/* Watch Dog Timer (WDT) */ +	rtclk512x_t		rtc;		/* Real Time Clock Module */ +	gpt512x_t		gpt;		/* General Purpose Timer */ +	ipic512x_t		ipic;		/* Integrated Programmable Interrupt Controller */ +	arbiter512x_t		arbiter;	/* CSB Arbiter */ +	reset512x_t		reset;		/* Reset Module */ +	clk512x_t		clk;		/* Clock Module */ +	pmc512x_t		pmc;		/* Power Management Control Module */ +	gpio512x_t		gpio;		/* General purpose I/O module */ +	u8			res1[0x100]; +	mscan512x_t		mscan;		/* MSCAN */ +	bdlc512x_t		bdlc;		/* BDLC */ +	sdhc512x_t		sdhc;		/* SDHC */ +	spdif512x_t		spdif;		/* SPDIF */ +	i2c512x_t		i2c;		/* I2C Controllers */ +	u8			res2[0x800]; +	axe512x_t		axe;		/* AXE */ +	diu512x_t		diu;		/* Display Interface Unit */ +	cfm512x_t		cfm;		/* Clock Frequency Measurement */ +	u8			res3[0x500]; +	fec512x_t		fec;		/* Fast Ethernet Controller */ +	ulpi512x_t		ulpi;		/* USB ULPI */ +	u8			res4[0xa00]; +	utmi512x_t		utmi;		/* USB UTMI */ +	u8			res5[0x1000]; +	pcidma512x_t		pci_dma;	/* PCI DMA */ +	pciconf512x_t		pci_conf;	/* PCI Configuration */ +	u8			res6[0x80]; +	ios512x_t		ios;		/* PCI Sequencer */ +	pcictrl512x_t		pci_ctrl;	/* PCI Controller Control and Status */ +	u8			res7[0xa00]; +	ddr512x_t		mddrc;		/* Multi-port DDR Memory Controller */ +	ioctrl512x_t		io_ctrl;	/* IO Control */ +	iim512x_t		iim;		/* IC Identification module */ +	u8			res8[0x4000]; +	lpc512x_t		lpc;		/* LocalPlus Controller */ +	pata512x_t		pata;		/* Parallel ATA */ +	u8			res9[0xd00]; +	psc512x_t		psc[12];	/* PSCs */ +	u8			res10[0x300]; +	fifoc512x_t		fifoc;		/* FIFO Controller */ +	u8			res11[0x2000]; +	dma512x_t		dma;		/* DMA */ +	u8			res12[0xa800]; +	sata512x_t		sata;		/* Serial ATA */ +	u8			res13[0xde000]; +} immap_t; +#endif /* __IMMAP_512x__ */ diff --git a/include/common.h b/include/common.h index 23f93907e..d823733b6 100644 --- a/include/common.h +++ b/include/common.h @@ -1,5 +1,5 @@  /* - * (C) Copyright 2000-2004 + * (C) Copyright 2000-2007   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.   *   * See file CREDITS for list of people who contributed to this @@ -65,6 +65,9 @@ typedef volatile unsigned char	vu_char;  #include <asm/5xx_immap.h>  #elif defined(CONFIG_MPC5xxx)  #include <mpc5xxx.h> +#elif defined(CONFIG_MPC512X) +#include <mpc512x.h> +#include <asm/immap_512x.h>  #elif defined(CONFIG_MPC8220)  #include <asm/immap_8220.h>  #elif defined(CONFIG_8260) @@ -448,6 +451,9 @@ int	prt_8260_clks (void);  #elif defined(CONFIG_MPC5xxx)  int	prt_mpc5xxx_clks (void);  #endif +#if defined(CONFIG_MPC512x) +int	prt_mpc512xxx_clks (void); +#endif  #if defined(CONFIG_MPC8220)  int	prt_mpc8220_clks (void);  #endif diff --git a/include/configs/ads5121.h b/include/configs/ads5121.h new file mode 100644 index 000000000..a1b8eefa0 --- /dev/null +++ b/include/configs/ads5121.h @@ -0,0 +1,410 @@ +/* + * (C) Copyright 2007 DENX Software Engineering + * + * 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 + */ + +/* + * ADS5121 board configuration file + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define DEBUG +#undef DEBUG + +/* + * Memory map for the ADS5121 board: + * + * 0x0000_0000 - 0x0FFF_FFFF	DDR RAM (256 MB) + * 0x3000_0000 - 0x3001_FFFF	SRAM (128 KB) + * 0x8000_0000 - 0x803F_FFFF	IMMR (4 MB) + * 0x8200_0000 - 0x8200_001F	CPLD (32 B) + * 0xFC00_0000 - 0xFFFF_FFFF	NOR Boot FLASH (64 MB) + */ + +/* + * High Level Configuration Options + */ +#define CONFIG_E300		1	/* E300 Family */ +#define CONFIG_MPC512X		1	/* MPC512X family */ + +#undef CONFIG_PCI + +#define CFG_MPC512X_CLKIN	66000000	/* in Hz */ + +#define CONFIG_BOARD_EARLY_INIT_F		/* call board_early_init_f() */ + +#define CFG_IMMR		0x80000000 + +#define CFG_MEMTEST_START	0x00200000      /* memtest region */ +#define CFG_MEMTEST_END		0x00400000 + +/* + * DDR Setup - manually set all parameters as there's no SPD etc. + */ +#define CFG_DDR_SIZE		256		/* MB */ +#define CFG_DDR_BASE		0x00000000	/* DDR is system memory*/ +#define CFG_SDRAM_BASE		CFG_DDR_BASE + +/* DDR Controller Configuration + +SYS_CFG: + 	[31:31]	MDDRC Soft Reset:	Diabled +	[30:30]	DRAM CKE pin:		Enabled +	[29:29]	DRAM CLK:		Enabled +	[28:28]	Command Mode:		Enabled (For initialization only)     +	[27:25]	DRAM Row Select:	dram_row[15:0] = magenta_address[25:10] +	[24:21]	DRAM Bank Select:	dram_bank[1:0] = magenta_address[11:10] +	[20:19]	Read Test:		DON'T USE +	[18:18]	Self Refresh:		Enabled +	[17:17]	16bit Mode:		Disabled +	[16:13] Ready Delay:		2 +	[12:12]	Half DQS Delay:		Disabled +	[11:11]	Quarter DQS Delay:	Disabled +	[10:08]	Write Delay:		2 +	[07:07]	Early ODT:		Disabled +	[06:06]	On DIE Termination:	Disabled +	[05:05]	FIFO Overflow Clear:	DON'T USE here +	[04:04]	FIFO Underflow Clear:	DON'T USE here +	[03:03]	FIFO Overflow Pending:	DON'T USE here +	[02:02]	FIFO Underlfow Pending:	DON'T USE here +	[01:01]	FIFO Overlfow Enabled:	Enabled +	[00:00]	FIFO Underflow Enabled:	Enabled + TIME_CFG0 + 	[31:16]	DRAM Refresh Time:	0 CSB clocks	 +	[15:8]	DRAM Command Time:	0 CSB clocks +	[07:00]	DRAM Precharge Time:	0 CSB clocks + TIME_CFG1 + 	[31:26]	DRAM tRFC: +	[25:21]	DRAM tWR1: +	[20:17]	DRAM tWRT1: +	[16:11]	DRAM tDRR: +	[10:05]	DRAM tRC: +	[04:00]	DRAM tRAS: + TIME_CFG2 + 	[31:28]	DRAM tRCD: +	[27:23]	DRAM tFAW: +	[22:19]	DRAM tRTW1: +	[18:15]	DRAM tCCD: +	[14:10] DRAM tRTP: +	[09:05]	DRAM tRP: +	[04:00] DRAM tRPA */ + +#define CFG_MDDRC_SYS_CFG	0xF8604200 +#define CFG_MDDRC_SYS_CFG_RUN	0xE8604200 +#define CFG_MDDRC_SYS_CFG_EN	0x30000000 +#define CFG_MDDRC_TIME_CFG0	0x0000281E +#define CFG_MDDRC_TIME_CFG0_RUN	0x01F4281E +#define CFG_MDDRC_TIME_CFG1	0x54EC1168 +#define CFG_MDDRC_TIME_CFG2	0x35210864 + +#define CFG_MICRON_NOP		0x01380000 +#define CFG_MICRON_PCHG_ALL	0x01100400 +#define CFG_MICRON_MR		0x01000022 +#define CFG_MICRON_EM2		0x01020000 +#define CFG_MICRON_EM3		0x01030000 +#define CFG_MICRON_EN_DLL	0x01010000 +#define CFG_MICRON_RST_DLL	0x01000932 +#define CFG_MICRON_RFSH		0x01080000 +#define CFG_MICRON_INIT_DEV_OP	0x01000832 +#define CFG_MICRON_OCD_DEFAULT	0x01010780 +#define CFG_MICRON_OCD_EXIT	0x01010400 + +/* DDR Priority Manager Configuration */ +#define CFG_MDDRCGRP_PM_CFG1	0x000777AA +#define CFG_MDDRCGRP_PM_CFG2	0x00000055 +#define CFG_MDDRCGRP_HIPRIO_CFG	0x00000000 +#define CFG_MDDRCGRP_LUT0_MU    0x11111117 +#define CFG_MDDRCGRP_LUT0_ML	0x7777777A +#define CFG_MDDRCGRP_LUT1_MU    0x4444EEEE +#define CFG_MDDRCGRP_LUT1_ML	0xEEEEEEEE +#define CFG_MDDRCGRP_LUT2_MU    0x44444444 +#define CFG_MDDRCGRP_LUT2_ML	0x44444444 +#define CFG_MDDRCGRP_LUT3_MU    0x55555555 +#define CFG_MDDRCGRP_LUT3_ML	0x55555558 +#define CFG_MDDRCGRP_LUT4_MU    0x11111111 +#define CFG_MDDRCGRP_LUT4_ML	0x1111117C +#define CFG_MDDRCGRP_LUT0_AU    0x33333377 +#define CFG_MDDRCGRP_LUT0_AL	0x7777EEEE +#define CFG_MDDRCGRP_LUT1_AU    0x11111111 +#define CFG_MDDRCGRP_LUT1_AL	0x11111111 +#define CFG_MDDRCGRP_LUT2_AU    0x11111111 +#define CFG_MDDRCGRP_LUT2_AL	0x11111111 +#define CFG_MDDRCGRP_LUT3_AU    0x11111111 +#define CFG_MDDRCGRP_LUT3_AL	0x11111111 +#define CFG_MDDRCGRP_LUT4_AU    0x11111111 +#define CFG_MDDRCGRP_LUT4_AL	0x11111111 + +/* + * NOR FLASH on the Local Bus + */ +#define CFG_FLASH_CFI				/* use the Common Flash Interface */ +#define CFG_FLASH_CFI_DRIVER			/* use the CFI driver */ +#define CFG_FLASH_BASE		0xFC000000	/* start of FLASH   */ +#define CFG_FLASH_SIZE		0x04000000	/* max flash size in bytes */ +#define CFG_FLASH_USE_BUFFER_WRITE + +#define CFG_MAX_FLASH_BANKS	1		/* number of banks */ +#define CFG_FLASH_BANKS_LIST 	{CFG_FLASH_BASE} +#define CFG_MAX_FLASH_SECT	256		/* max sectors per device */ + +#undef CFG_FLASH_CHECKSUM + +/* + * CPLD registers area is really only 32 bytes in size, but the smallest possible LP + * window is 64KB + */ +#define CFG_CPLD_BASE		0x82000000 +#define CFG_CPLD_SIZE		0x00010000	/* 64 KB */ + +#define CFG_SRAM_BASE		0x30000000 +#define CFG_SRAM_SIZE		0x00020000	/* 128 KB */ + +#define CFG_CS0_CFG		0x05059310	/* ALE active low, data size 4bytes */ +#define CFG_CS2_CFG		0x05059010	/* ALE active low, data size 1byte */ + +/* Use SRAM for initial stack */ +#define CFG_INIT_RAM_ADDR	CFG_SRAM_BASE		/* Initial RAM address */ +#define CFG_INIT_RAM_END	CFG_SRAM_SIZE		/* End of used area in RAM */ + +#define CFG_GBL_DATA_SIZE	0x100			/* num bytes initial data */ +#define CFG_GBL_DATA_OFFSET	(CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET	CFG_GBL_DATA_OFFSET + +#define CFG_MONITOR_BASE	TEXT_BASE		/* Start of monitor */ +#define CFG_MONITOR_LEN		(256 * 1024)		/* Reserve 256 kB for Mon */ +#define CFG_MALLOC_LEN		(512 * 1024)		/* Reserved for malloc */ + +/* + * Serial Port + */ +#define CONFIG_CONS_INDEX     1 +#undef CONFIG_SERIAL_SOFTWARE_FIFO + +/* + * Serial console configuration + */ +#define CONFIG_PSC_CONSOLE	3	/* console is on PSC3 */ +#if CONFIG_PSC_CONSOLE != 3 +#error CONFIG_PSC_CONSOLE must be 3 +#endif +#define CONFIG_BAUDRATE		115200	/* ... at 115200 bps */ +#define CFG_BAUDRATE_TABLE  \ +	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400,115200} + +#define CONSOLE_FIFO_TX_SIZE	FIFOC_PSC3_TX_SIZE +#define CONSOLE_FIFO_TX_ADDR	FIFOC_PSC3_TX_ADDR +#define CONSOLE_FIFO_RX_SIZE	FIFOC_PSC3_RX_SIZE +#define CONSOLE_FIFO_RX_ADDR	FIFOC_PSC3_RX_ADDR + +#define CONFIG_CMDLINE_EDITING	1	/* add command line history	*/ +/* Use the HUSH parser */ +#define CFG_HUSH_PARSER +#ifdef  CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + +/* I2C */ +#define CONFIG_HARD_I2C			/* I2C with hardware support */ +#undef CONFIG_SOFT_I2C			/* so disable bit-banged I2C */ +#define CONFIG_I2C_MULTI_BUS +#define CONFIG_I2C_CMD_TREE +#define CFG_I2C_SPEED		100000	/* I2C speed and slave address */ +#define CFG_I2C_SLAVE		0x7F +#if 0 +#define CFG_I2C_NOPROBES	{{0,0x69}}	* Don't probe these addrs */ +#endif + +/* + * Ethernet configuration + */ +#define CONFIG_MPC512x_FEC	1 +#define CONFIG_NET_MULTI +#define CONFIG_PHY_ADDR		0x1 +#define CONFIG_MII		1	/* MII PHY management		*/ +#define CONFIG_ETHADDR		00:e0:5e:00:e5:14 + +#if 0 +/* + * Configure on-board RTC + */ +#define CONFIG_RTC_DS1374			/* use ds1374 rtc via i2c	*/ +#define CFG_I2C_RTC_ADDR		0x68	/* at address 0x68		*/ +#endif + +/* + * Environment + */ +#define CFG_ENV_IS_IN_FLASH	1 +/* This has to be a multiple of the Flash sector size */ +#define CFG_ENV_ADDR		(CFG_MONITOR_BASE + CFG_MONITOR_LEN) +#define CFG_ENV_SIZE		0x2000 +#define CFG_ENV_SECT_SIZE	0x40000	/* one sector (256K) for env */ + +/* Address and size of Redundant Environment Sector	*/ +#define CFG_ENV_ADDR_REDUND	(CFG_ENV_ADDR + CFG_ENV_SECT_SIZE) +#define CFG_ENV_SIZE_REDUND	(CFG_ENV_SIZE) + +#define CONFIG_LOADS_ECHO	1	/* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE	1	/* allow baudrate change */ + +#if defined(CONFIG_PCI) +#define  CONFIG_COMMANDS	(CONFIG_CMD_DFL		\ +				| CFG_CMD_PCI		\ +				| CFG_CMD_NET		\ +				| CFG_CMD_PING		\ +				) +#else +#define  CONFIG_COMMANDS	(CONFIG_CMD_DFL		\ +				| CFG_CMD_NET		\ +				| CFG_CMD_PING		\ +          			| CFG_CMD_MII		\ +				| CFG_CMD_I2C) +#endif + +#include <cmd_confdefs.h> + +/* + * Watchdog timeout = CFG_WATCHDOG_VALUE * 65536 / IPS clock. + * For example, when IPS is set to 66MHz and CFG_WATCHDOG_VALUE is set + * to 0xFFFF, watchdog timeouts after about 64s. For details refer + * to chapter 36 of the MPC5121e Reference Manual. + */ +#define CONFIG_WATCHDOG			/* enable watchdog */ +#define CFG_WATCHDOG_VALUE 0xFFFF + + /* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP			/* undef to save memory */ +#define CFG_LOAD_ADDR	0x2000000	/* default load address */ +#define CFG_PROMPT	"=> "		/* Monitor Command Prompt */ + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +	#define CFG_CBSIZE	1024		/* Console I/O Buffer Size */ +#else +	#define CFG_CBSIZE	256		/* Console I/O Buffer Size */ +#endif + + +#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) /* Print Buffer Size */ +#define CFG_MAXARGS	16		/* max number of command args */ +#define CFG_BARGSIZE	CFG_CBSIZE	/* Boot Argument Buffer Size */ +#define CFG_HZ		1000		/* decrementer freq: 1ms ticks */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ	(8 << 20)	/* Initial Memory map for Linux*/ + +/* Cache Configuration */ +#define CFG_DCACHE_SIZE		32768 +#define CFG_CACHELINE_SIZE	32 +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT	5	/*log base 2 of the above value*/ +#endif + +#define CFG_HID0_INIT	0x000000000 +#define CFG_HID0_FINAL	HID0_ENABLE_MACHINE_CHECK +#define CFG_HID2	HID2_HBE + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD	0x01	/* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM	0x02	/* Software reboot */ + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE	230400	/* speed of kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX	2	/* which serial port to use */ +#endif + +/* + * Environment Configuration + */ +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_HOSTNAME		ads5121 +#define CONFIG_ROOTPATH		/nfsroot/rootfs +#define CONFIG_BOOTFILE		uImage + +#define CONFIG_IPADDR		192.168.160.77 +#define CONFIG_SERVERIP		192.168.1.1 +#define CONFIG_GATEWAYIP	192.168.1.1 +#define CONFIG_NETMASK		255.255.0.0 + +#define CONFIG_LOADADDR		200000	/* default location for tftp and bootm */ + +//#define CONFIG_BOOTDELAY	6	/* -1 disables auto-boot */ +#define CONFIG_BOOTDELAY	-1 +#undef  CONFIG_BOOTARGS			/* the boot command will set bootargs */ + +#define CONFIG_BAUDRATE		115200 + +#define CONFIG_PREBOOT	"echo;"	\ +	"echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ +	"echo" + +#define	CONFIG_EXTRA_ENV_SETTINGS					\ +	"netdev=eth0\0"							\ +	"nfsargs=setenv bootargs root=/dev/nfs rw "			\ +		"nfsroot=${serverip}:${rootpath}\0"			\ +	"ramargs=setenv bootargs root=/dev/ram rw\0"			\ +	"addip=setenv bootargs ${bootargs} "				\ +		"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}"	\ +		":${hostname}:${netdev}:off panic=1\0"			\ +	"addtty=setenv bootargs ${bootargs} console=ttyS0,${baudrate}\0"\ +	"flash_nfs=run nfsargs addip addtty;"				\ +		"bootm ${kernel_addr}\0"				\ +	"flash_self=run ramargs addip addtty;"				\ +		"bootm ${kernel_addr} ${ramdisk_addr}\0"		\ +	"net_nfs=tftp 200000 ${bootfile};run nfsargs addip addtty;"	\ +		"bootm\0"						\ +	"load=tftp 100000 /tftpboot/ads5121/u-boot.bin\0"		\ +	"update=protect off fff00000 fff3ffff; "			\ +		"era fff00000 fff3ffff; cp.b 100000 fff00000 ${filesize}\0"	\ +	"upd=run load;run update\0"					\ +	"" + +#define CONFIG_NFSBOOTCOMMAND	                                        \ +   "setenv bootargs root=/dev/nfs rw "                                  \ +      "nfsroot=$serverip:$rootpath "                                    \ +      "ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname:$netdev:off " \ +      "console=$consoledev,$baudrate $othbootargs;"                     \ +   "tftp $loadaddr $bootfile;"                                          \ +   "tftp $fdtaddr $fdtfile;"						\ +   "bootm $loadaddr - $fdtaddr" + +#define CONFIG_RAMBOOTCOMMAND						\ +   "setenv bootargs root=/dev/ram rw "                                  \ +      "console=$consoledev,$baudrate $othbootargs;"                     \ +   "tftp $ramdiskaddr $ramdiskfile;"                                    \ +   "tftp $loadaddr $bootfile;"                                          \ +   "tftp $fdtaddr $fdtfile;"						\ +   "bootm $loadaddr $ramdiskaddr $fdtaddr" + +#define CONFIG_BOOTCOMMAND	"run flash_self" + +#endif	/* __CONFIG_H */ diff --git a/include/mpc512x.h b/include/mpc512x.h new file mode 100644 index 000000000..03e0e9a14 --- /dev/null +++ b/include/mpc512x.h @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. + * (C) Copyright 2007 DENX Software Engineering + * + * 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. + * + * Derived from the MPC83xx header. + */ + +#ifndef __MPC512X_H__ +#define __MPC512X_H__ + +#include <config.h> +#if defined(CONFIG_E300) +#include <asm/e300.h> +#endif + +/* System reset offset (PowerPC standard) + */ +#define EXC_OFF_SYS_RESET		0x0100 +#define	_START_OFFSET			EXC_OFF_SYS_RESET + + +/* IMMRBAR - Internal Memory Register Base Address + */ +#define CONFIG_DEFAULT_IMMR		0xFF400000	/* Default IMMR base address */ +#define IMMRBAR				0x0000		/* Register offset to immr */ +#define IMMRBAR_BASE_ADDR		0xFFF00000	/* Base address mask */ +#define IMMRBAR_RES			~(IMMRBAR_BASE_ADDR) + +/* LAWBAR - Local Access Window Base Address Register + */ +#define LPBAW			0x0020		/* Register offset to immr */ +#define LPCS0AW			0x0024 +#define LPCS1AW			0x0028 +#define LPCS2AW			0x002C +#define LPCS3AW			0x0030 +#define LPCS4AW			0x0034 +#define LPCS5AW			0x0038 +#define LPCS6AW			0x003C +#define LPCA7AW			0x0040 +#define SRAMBAR			0x00C4 + +#define LPC_OFFSET		0x10000 + +#define CS0_CONFIG		0x00000 +#define CS1_CONFIG		0x00004 +#define CS2_CONFIG		0x00008 +#define CS3_CONFIG		0x0000C +#define CS4_CONFIG		0x00010 +#define CS5_CONFIG		0x00014 +#define CS6_CONFIG		0x00018 +#define CS7_CONFIG		0x0001C + +#define CS_CTRL			0x00020 +#define CS_CTRL_ME		0x01000000	/* CS Master Enable bit */ +#define CS_CTRL_IE		0x08000000	/* CS Interrupt Enable bit */  + +/* SPRIDR - System Part and Revision ID Register + */ +#define SPRIDR_PARTID		0xFFFF0000	/* Part Identification */ +#define SPRIDR_REVID		0x0000FFFF	/* Revision Identification */ + +#define SPR_5121E		0x80180000 + +/* SPCR - System Priority Configuration Register + */ +#define SPCR_PCIHPE			0x10000000	/* PCI Highest Priority Enable */ +#define SPCR_PCIHPE_SHIFT		(31-3) +#define SPCR_PCIPR			0x03000000	/* PCI bridge system bus request priority */ +#define SPCR_PCIPR_SHIFT		(31-7) +#define SPCR_TBEN			0x00400000	/* E300 PowerPC core time base unit enable */ +#define SPCR_TBEN_SHIFT			(31-9) +#define SPCR_COREPR			0x00300000	/* E300 PowerPC Core system bus request priority */ +#define SPCR_COREPR_SHIFT		(31-11) + +/* SWCRR - System Watchdog Control Register + */ +#define SWCRR				0x0904		/* Register offset to immr */ +#define SWCRR_SWTC			0xFFFF0000	/* Software Watchdog Time Count */ +#define SWCRR_SWEN			0x00000004	/* Watchdog Enable bit */ +#define SWCRR_SWRI			0x00000002	/* Software Watchdog Reset/Interrupt Select bit */ +#define SWCRR_SWPR			0x00000001	/* Software Watchdog Counter Prescale bit */ +#define SWCRR_RES			~(SWCRR_SWTC | SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR) + +/* SWCNR - System Watchdog Counter Register + */ +#define SWCNR				0x0908		/* Register offset to immr */ +#define SWCNR_SWCN			0x0000FFFF	/* Software Watchdog Count mask */ +#define SWCNR_RES			~(SWCNR_SWCN) + +/* SWSRR - System Watchdog Service Register + */ +#define SWSRR				0x090E		/* Register offset to immr */ + +/* ACR - Arbiter Configuration Register + */ +#define ACR_COREDIS			0x10000000	/* Core disable */ +#define ACR_COREDIS_SHIFT		(31-7) +#define ACR_PIPE_DEP			0x00070000	/* Pipeline depth */ +#define ACR_PIPE_DEP_SHIFT		(31-15) +#define ACR_PCI_RPTCNT			0x00007000	/* PCI repeat count */ +#define ACR_PCI_RPTCNT_SHIFT		(31-19) +#define ACR_RPTCNT			0x00000700	/* Repeat count */ +#define ACR_RPTCNT_SHIFT		(31-23) +#define ACR_APARK			0x00000030	/* Address parking */ +#define ACR_APARK_SHIFT			(31-27) +#define ACR_PARKM			0x0000000F	/* Parking master */ +#define ACR_PARKM_SHIFT			(31-31) + +/* ATR - Arbiter Timers Register + */ +#define ATR_DTO				0x00FF0000	/* Data time out */ +#define ATR_ATO				0x000000FF	/* Address time out */ + +/* AER - Arbiter Event Register + */ +#define AER_ETEA			0x00000020	/* Transfer error */ +#define AER_RES				0x00000010	/* Reserved transfer type */ +#define AER_ECW				0x00000008	/* External control word transfer type */ +#define AER_AO				0x00000004	/* Address Only transfer type */ +#define AER_DTO				0x00000002	/* Data time out */ +#define AER_ATO				0x00000001	/* Address time out */ + +/* AEATR - Arbiter Event Address Register + */ +#define AEATR_EVENT			0x07000000	/* Event type */ +#define AEATR_MSTR_ID			0x001F0000	/* Master Id */ +#define AEATR_TBST			0x00000800	/* Transfer burst */ +#define AEATR_TSIZE			0x00000700	/* Transfer Size */ +#define AEATR_TTYPE			0x0000001F	/* Transfer Type */ + +/* RSR - Reset Status Register + */ +#define RSR_SWSR			0x00002000	/* software soft reset */ +#define RSR_SWSR_SHIFT			13 +#define RSR_SWHR			0x00001000	/* software hard reset */ +#define RSR_SWHR_SHIFT			12 +#define RSR_JHRS			0x00000200	/* jtag hreset */ +#define RSR_JHRS_SHIFT			9 +#define RSR_JSRS			0x00000100	/* jtag sreset status */ +#define RSR_JSRS_SHIFT			8 +#define RSR_CSHR			0x00000010	/* checkstop reset status */ +#define RSR_CSHR_SHIFT			4 +#define RSR_SWRS			0x00000008	/* software watchdog reset status */ +#define RSR_SWRS_SHIFT			3 +#define RSR_BMRS			0x00000004	/* bus monitop reset status */ +#define RSR_BMRS_SHIFT			2 +#define RSR_SRS				0x00000002	/* soft reset status */ +#define RSR_SRS_SHIFT			1 +#define RSR_HRS				0x00000001	/* hard reset status */ +#define RSR_HRS_SHIFT			0 +#define RSR_RES				~(RSR_SWSR | RSR_SWHR |\ +					 RSR_JHRS | RSR_JSRS | RSR_CSHR | RSR_SWRS |\ +					 RSR_BMRS | RSR_SRS | RSR_HRS) +/* RMR - Reset Mode Register + */ +#define RMR_CSRE			0x00000001	/* checkstop reset enable */ +#define RMR_CSRE_SHIFT			0 +#define RMR_RES				~(RMR_CSRE) + +/* RCR - Reset Control Register + */ +#define RCR_SWHR			0x00000002	/* software hard reset */ +#define RCR_SWSR			0x00000001	/* software soft reset */ +#define RCR_RES				~(RCR_SWHR | RCR_SWSR) + +/* RCER - Reset Control Enable Register + */ +#define RCER_CRE			0x00000001	/* software hard reset */ +#define RCER_RES			~(RCER_CRE) + +/* SPMR - System PLL Mode Register + */ +#define SPMR_SPMF			0x0F000000 +#define SPMR_SPMF_SHIFT			24 +#define SPMR_CPMF			0x000F0000 +#define SPMR_CPMF_SHIFT			16 + +/* SCFR1 System Clock Frequency Register 1 + */ +#define SCFR1_IPS_DIV			0x2 +#define SCFR1_IPS_DIV_MASK		0x03800000 +#define SCFR1_IPS_DIV_SHIFT		23 + +/* SCFR2 System Clock Frequency Register 2 + */ +#define SCFR2_SYS_DIV			0xFC000000 +#define SCFR2_SYS_DIV_SHIFT		26 + +/* SCCR - System Clock Control Registers + */ + +/* System Clock Control Register 1 commands */ +#define CLOCK_SCCR1_CFG_EN		0x80000000 +#define CLOCK_SCCR1_LPC_EN		0x40000000 +#define CLOCK_SCCR1_NFC_EN		0x20000000 +#define CLOCK_SCCR1_PATA_EN		0x10000000 +#define CLOCK_SCCR1_PSC_EN(cn)		(0x08000000 >> (cn)) +#define CLOCK_SCCR1_PSCFIFO_EN		0x00008000 +#define CLOCK_SCCR1_SATA_EN		0x00004000 +#define CLOCK_SCCR1_FEC_EN		0x00002000 +#define CLOCK_SCCR1_TPR_EN		0x00001000 +#define CLOCK_SCCR1_PCI_EN		0x00000800 +#define CLOCK_SCCR1_DDR_EN		0x00000400 + +/* System Clock Control Register 2 commands */ +#define CLOCK_SCCR2_DIU_EN		0x80000000 +#define CLOCK_SCCR2_AXE_EN		0x40000000 +#define CLOCK_SCCR2_MEM_EN		0x20000000 +#define CLOCK_SCCR2_USB2_EN		0x10000000 +#define CLOCK_SCCR2_USB1_EN		0x08000000 +#define CLOCK_SCCR2_I2C_EN		0x04000000 +#define CLOCK_SCCR2_BDLC_EN		0x02000000 +#define CLOCK_SCCR2_SDHC_EN		0x01000000 +#define CLOCK_SCCR2_SPDIF_EN		0x00800000 +#define CLOCK_SCCR2_MBX_BUS_EN		0x00400000 +#define CLOCK_SCCR2_MBX_EN		0x00200000 +#define CLOCK_SCCR2_MBX_3D_EN		0x00100000 +#define CLOCK_SCCR2_IIM_EN		0x00080000 + +/* PSC FIFO Command values */ +#define PSC_FIFO_RESET_SLICE		0x80 +#define PSC_FIFO_ENABLE_SLICE		0x01 + +/* PSC FIFO Controller Command values */ +#define FIFOC_ENABLE_CLOCK_GATE		0x01 +#define FIFOC_DISABLE_CLOCK_GATE	0x00 + +/* PSC FIFO status */ +#define PSC_FIFO_EMPTY			0x01 + +/* PSC Command values */ +#define PSC_RX_ENABLE		0x01 +#define PSC_RX_DISABLE		0x02 +#define PSC_TX_ENABLE		0x04 +#define PSC_TX_DISABLE		0x08 +#define PSC_SEL_MODE_REG_1	0x10 +#define PSC_RST_RX		0x20 +#define PSC_RST_TX		0x30 +#define PSC_RST_ERR_STAT	0x40 +#define PSC_RST_BRK_CHG_INT	0x50 +#define PSC_START_BRK		0x60 +#define PSC_STOP_BRK		0x70 + +/* PSC status register bits */ +#define PSC_SR_CDE		0x0080 +#define PSC_SR_TXEMP		0x0800 +#define PSC_SR_OE		0x1000 +#define PSC_SR_PE		0x2000 +#define PSC_SR_FE		0x4000 +#define PSC_SR_RB		0x8000 + +/* PSC mode fields */ +#define PSC_MODE_5_BITS		0x00 +#define PSC_MODE_6_BITS		0x01 +#define PSC_MODE_7_BITS		0x02 +#define PSC_MODE_8_BITS		0x03 +#define PSC_MODE_PAREVEN	0x00 +#define PSC_MODE_PARODD		0x04 +#define PSC_MODE_PARFORCE	0x08 +#define PSC_MODE_PARNONE	0x10 +#define PSC_MODE_ENTIMEOUT	0x20 +#define PSC_MODE_RXRTS		0x80 +#define PSC_MODE_1_STOPBIT	0x07 + +/* + * Centralized FIFO Controller has internal memory for all 12 PSCs FIFOs + * + * NOTE: individual PSC units are free to use whatever area (and size) of the + * FIFOC internal memory, so make sure memory areas for FIFO slices used by + * different PSCs do not overlap! + * + * Overall size of FIFOC memory is not documented in the MPC5121e RM, but + * tests indicate that it is 1024 words total. + */ +#define FIFOC_PSC0_TX_SIZE	0x0	/* number of 4-byte words for FIFO slice */ +#define FIFOC_PSC0_TX_ADDR	0x0 +#define FIFOC_PSC0_RX_SIZE	0x0 +#define FIFOC_PSC0_RX_ADDR	0x0 + +#define FIFOC_PSC1_TX_SIZE	0x0 +#define FIFOC_PSC1_TX_ADDR	0x0 +#define FIFOC_PSC1_RX_SIZE	0x0 +#define FIFOC_PSC1_RX_ADDR	0x0 + +#define FIFOC_PSC2_TX_SIZE	0x0 +#define FIFOC_PSC2_TX_ADDR	0x0 +#define FIFOC_PSC2_RX_SIZE	0x0 +#define FIFOC_PSC2_RX_ADDR	0x0 + +#define FIFOC_PSC3_TX_SIZE	0x04 +#define FIFOC_PSC3_TX_ADDR	0x0 +#define FIFOC_PSC3_RX_SIZE	0x04 +#define FIFOC_PSC3_RX_ADDR	0x10 + +#define FIFOC_PSC4_TX_SIZE	0x0 +#define FIFOC_PSC4_TX_ADDR	0x0 +#define FIFOC_PSC4_RX_SIZE	0x0 +#define FIFOC_PSC4_RX_ADDR	0x0 + +#define FIFOC_PSC5_TX_SIZE	0x0 +#define FIFOC_PSC5_TX_ADDR	0x0 +#define FIFOC_PSC5_RX_SIZE	0x0 +#define FIFOC_PSC5_RX_ADDR	0x0 + +#define FIFOC_PSC6_TX_SIZE	0x0 +#define FIFOC_PSC6_TX_ADDR	0x0 +#define FIFOC_PSC6_RX_SIZE	0x0 +#define FIFOC_PSC6_RX_ADDR	0x0 + +#define FIFOC_PSC7_TX_SIZE	0x0 +#define FIFOC_PSC7_TX_ADDR	0x0 +#define FIFOC_PSC7_RX_SIZE	0x0 +#define FIFOC_PSC7_RX_ADDR	0x0 + +#define FIFOC_PSC8_TX_SIZE	0x0 +#define FIFOC_PSC8_TX_ADDR	0x0 +#define FIFOC_PSC8_RX_SIZE	0x0 +#define FIFOC_PSC8_RX_ADDR	0x0 + +#define FIFOC_PSC9_TX_SIZE	0x0 +#define FIFOC_PSC9_TX_ADDR	0x0 +#define FIFOC_PSC9_RX_SIZE	0x0 +#define FIFOC_PSC9_RX_ADDR	0x0 + +#define FIFOC_PSC10_TX_SIZE	0x0 +#define FIFOC_PSC10_TX_ADDR	0x0 +#define FIFOC_PSC10_RX_SIZE	0x0 +#define FIFOC_PSC10_RX_ADDR	0x0 + +#define FIFOC_PSC11_TX_SIZE	0x0 +#define FIFOC_PSC11_TX_ADDR	0x0 +#define FIFOC_PSC11_RX_SIZE	0x0 +#define FIFOC_PSC11_RX_ADDR	0x0 + +/* IO Control Register + */ + +/* Indexes in regs array */ +#define MEM_IDX			0x00 +#define SPDIF_TXCLOCK_IDX	0x73 +#define SPDIF_TX_IDX		0x74 +#define SPDIF_RX_IDX		0x75 +#define PSC0_0_IDX		0x83 +#define PSC0_1_IDX		0x84 +#define PSC0_2_IDX		0x85 +#define PSC0_3_IDX		0x86 +#define PSC0_4_IDX		0x87 +#define PSC1_0_IDX		0x88 +#define PSC1_1_IDX		0x89 +#define PSC1_2_IDX		0x8a +#define PSC1_3_IDX		0x8b +#define PSC1_4_IDX		0x8c +#define PSC2_0_IDX		0x8d +#define PSC2_1_IDX		0x8e +#define PSC2_2_IDX		0x8f +#define PSC2_3_IDX		0x90 +#define PSC2_4_IDX		0x91 + +#define IOCTRL_FUNCMUX_SHIFT	7 +#define IOCTRL_FUNCMUX_FEC	1 +#define IOCTRL_MUX_FEC		(IOCTRL_FUNCMUX_FEC << IOCTRL_FUNCMUX_SHIFT) + +/* Set for DDR */ +#define IOCTRL_MUX_DDR		0x00000036 + + /* Register Offset Base */ +#define MPC512X_FEC		(CFG_IMMR + 0x02800) + +/* Number of I2C buses */ +#define I2C_BUS_CNT	3 + +/* I2Cn control register bits */ +#define I2C_EN		0x80 +#define I2C_IEN		0x40 +#define I2C_STA		0x20 +#define I2C_TX		0x10 +#define I2C_TXAK	0x08 +#define I2C_RSTA	0x04 +#define I2C_INIT_MASK	(I2C_EN | I2C_STA | I2C_TX | I2C_RSTA) + +/* I2Cn status register bits */ +#define I2C_CF		0x80 +#define I2C_AAS		0x40 +#define I2C_BB		0x20 +#define I2C_AL		0x10 +#define I2C_SRW		0x04 +#define I2C_IF		0x02 +#define I2C_RXAK	0x01 + +#endif	/* __MPC512X_H__ */ @@ -40,6 +40,7 @@ extern int eth_3com_initialize(bd_t*);  extern int fec_initialize(bd_t*);  extern int inca_switch_initialize(bd_t*);  extern int mpc5xxx_fec_initialize(bd_t*); +extern int mpc512x_fec_initialize(bd_t*);  extern int mpc8220_fec_initialize(bd_t*);  extern int mv6436x_eth_initialize(bd_t *);  extern int mv6446x_eth_initialize(bd_t *); @@ -168,6 +169,9 @@ int eth_initialize(bd_t *bis)  #if defined(CONFIG_MPC5xxx_FEC)  	mpc5xxx_fec_initialize(bis);  #endif +#if defined(CONFIG_MPC512x_FEC) +	mpc512x_fec_initialize (bis); +#endif  #if defined(CONFIG_MPC8220_FEC)  	mpc8220_fec_initialize(bis);  #endif |