From: Rafal Jaworowski Date: Fri, 27 Jul 2007 12:43:59 +0000 (+0200) Subject: [ADS5121] Support for the ADS5121 board X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=8993e54b6f397973794f3d6f47d3b3c0c98dd4f6;p=u-boot.git [ADS5121] Support for the ADS5121 board The following MPC5121e subsystems are supported: - low-level CPU init - NOR Boot Flash (common CFI driver) - DDR SDRAM - FEC - I2C - Watchdog Signed-off-by: Grzegorz Bernacki Signed-off-by: Rafal Jaworowski Signed-off-by: Jan Wrobel --- diff --git a/MAKEALL b/MAKEALL index 127faa83a3..2a03b68708 100755 --- a/MAKEALL +++ b/MAKEALL @@ -43,6 +43,14 @@ LIST_5xxx=" \ TQM5200S v38b \ " +######################################################################### +## MPC512x Systems +######################################################################### + +LIST_512x=" \ + ads5121 \ +" + ######################################################################### ## MPC8xx Systems ######################################################################### @@ -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 diff --git a/Makefile b/Makefile index 3af9962e67..5b87aad5b9 100644 --- a/Makefile +++ b/Makefile @@ -641,6 +641,13 @@ motionpro_config: unconfig @$(MKCONFIG) motionpro ppc mpc5xxx motionpro +######################################################################### +## 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 0000000000..cd8148c43e --- /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 0000000000..0a99a34ac0 --- /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 +#include +#include +#include + +/* 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 0000000000..14998f4750 --- /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 0000000000..038d849553 --- /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 0000000000..2be35b2bc6 --- /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 0000000000..8a07c5a3b6 --- /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 0000000000..3be565ad03 --- /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 +#include +#include +#include + +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 0000000000..566e08b0dd --- /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 +#include + +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 0000000000..f1b7a2563e --- /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 + */ + +#include +#include +#include +#include +#include +#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 0000000000..71459197a5 --- /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 +#include + +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 0000000000..00e28d6404 --- /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 + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_HARD_I2C + +#include +#include + +#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 0000000000..8cc241c899 --- /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 + +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 0000000000..200ff2c496 --- /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 + */ + +/* + * Minimal serial functions needed to use one of the PSC ports + * as serial console interface. + */ + +#include + +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 0000000000..9a31155ed2 --- /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 +#include +#include +#include + +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 0000000000..8b749ac54e --- /dev/null +++ b/cpu/mpc512x/start.S @@ -0,0 +1,780 @@ +/* + * Copyright (C) 1998 Dan Malek + * Copyright (C) 1999 Magnus Damm + * Copyright (C) 2000, 2001, 2002, 2007 Wolfgang Denk + * 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 +#include +#include + +#define CONFIG_521X 1 /* needed for Linux kernel header files*/ + +#include +#include + +#include +#include + +#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 0000000000..40281a2cbb --- /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 +#include + +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 d1bb159aef..de8239965a 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 cd2463643c..bbaeb3f575 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 0000000000..23d10d4eb4 --- /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 + +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 23f93907ee..d823733b67 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 #elif defined(CONFIG_MPC5xxx) #include +#elif defined(CONFIG_MPC512X) +#include +#include #elif defined(CONFIG_MPC8220) #include #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 0000000000..a1b8eefa02 --- /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 + +/* + * 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 0000000000..03e0e9a147 --- /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 +#if defined(CONFIG_E300) +#include +#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__ */ diff --git a/net/eth.c b/net/eth.c index 9fb3a10edb..68e2c54b2e 100644 --- a/net/eth.c +++ b/net/eth.c @@ -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