From 4e26f1074c3ac1bd8fd094f0dc4a1c4a0b15a592 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 29 Nov 2006 12:03:57 +0100 Subject: [PATCH 1/5] [PATCH] include/ppc440.h minor error affecting interrupts Fixed include/ppc440.c for UIC address Bug Corrects bug affecting the addresses for the universal interrupt controller UIC2 and UIC3 on the PPC440 Epx, GRx, and SPE chips. Signed-off-by: Jeff Mann Signed-off-by: Stefan Roese --- include/ppc440.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/include/ppc440.h b/include/ppc440.h index 407daaebe8..50f4ec403b 100644 --- a/include/ppc440.h +++ b/include/ppc440.h @@ -1350,26 +1350,26 @@ #if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) #define UIC2_DCR_BASE 0xe0 -#define uic2sr (UIC0_DCR_BASE+0x0) /* UIC2 status-Read Clear */ -#define uic2srs (UIC0_DCR_BASE+0x1) /* UIC2 status-Read Set */ -#define uic2er (UIC0_DCR_BASE+0x2) /* UIC2 enable */ -#define uic2cr (UIC0_DCR_BASE+0x3) /* UIC2 critical */ -#define uic2pr (UIC0_DCR_BASE+0x4) /* UIC2 polarity */ -#define uic2tr (UIC0_DCR_BASE+0x5) /* UIC2 triggering */ -#define uic2msr (UIC0_DCR_BASE+0x6) /* UIC2 masked status */ -#define uic2vr (UIC0_DCR_BASE+0x7) /* UIC2 vector */ -#define uic2vcr (UIC0_DCR_BASE+0x8) /* UIC2 vector configuration */ +#define uic2sr (UIC2_DCR_BASE+0x0) /* UIC2 status-Read Clear */ +#define uic2srs (UIC2_DCR_BASE+0x1) /* UIC2 status-Read Set */ +#define uic2er (UIC2_DCR_BASE+0x2) /* UIC2 enable */ +#define uic2cr (UIC2_DCR_BASE+0x3) /* UIC2 critical */ +#define uic2pr (UIC2_DCR_BASE+0x4) /* UIC2 polarity */ +#define uic2tr (UIC2_DCR_BASE+0x5) /* UIC2 triggering */ +#define uic2msr (UIC2_DCR_BASE+0x6) /* UIC2 masked status */ +#define uic2vr (UIC2_DCR_BASE+0x7) /* UIC2 vector */ +#define uic2vcr (UIC2_DCR_BASE+0x8) /* UIC2 vector configuration */ #define UIC3_DCR_BASE 0xf0 -#define uic3sr (UIC1_DCR_BASE+0x0) /* UIC3 status-Read Clear */ -#define uic3srs (UIC0_DCR_BASE+0x1) /* UIC3 status-Read Set */ -#define uic3er (UIC1_DCR_BASE+0x2) /* UIC3 enable */ -#define uic3cr (UIC1_DCR_BASE+0x3) /* UIC3 critical */ -#define uic3pr (UIC1_DCR_BASE+0x4) /* UIC3 polarity */ -#define uic3tr (UIC1_DCR_BASE+0x5) /* UIC3 triggering */ -#define uic3msr (UIC1_DCR_BASE+0x6) /* UIC3 masked status */ -#define uic3vr (UIC1_DCR_BASE+0x7) /* UIC3 vector */ -#define uic3vcr (UIC1_DCR_BASE+0x8) /* UIC3 vector configuration */ +#define uic3sr (UIC3_DCR_BASE+0x0) /* UIC3 status-Read Clear */ +#define uic3srs (UIC3_DCR_BASE+0x1) /* UIC3 status-Read Set */ +#define uic3er (UIC3_DCR_BASE+0x2) /* UIC3 enable */ +#define uic3cr (UIC3_DCR_BASE+0x3) /* UIC3 critical */ +#define uic3pr (UIC3_DCR_BASE+0x4) /* UIC3 polarity */ +#define uic3tr (UIC3_DCR_BASE+0x5) /* UIC3 triggering */ +#define uic3msr (UIC3_DCR_BASE+0x6) /* UIC3 masked status */ +#define uic3vr (UIC3_DCR_BASE+0x7) /* UIC3 vector */ +#define uic3vcr (UIC3_DCR_BASE+0x8) /* UIC3 vector configuration */ #endif /* CONFIG_440SPE */ #if defined(CONFIG_440GX) From 1bdd46832aeb569f5e04b1f20f64318525b6525a Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 29 Nov 2006 12:53:15 +0100 Subject: [PATCH 2/5] [PATCH] common/cmd_elf.c: Enable loadaddr as parameter in bootvx command In the bootvx command the load address was only read from the env variable "loadaddr" and not optionally passed as paramter as described in the help. This is fixed with this patch. The behaviour is now the same as in the bootelf command. Signed-off-by: Stefan Roese --- common/cmd_elf.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/common/cmd_elf.c b/common/cmd_elf.c index 1d92bb37d3..0e3d56f6bb 100644 --- a/common/cmd_elf.c +++ b/common/cmd_elf.c @@ -79,7 +79,7 @@ int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) * be either an ELF image or a raw binary. Will attempt to setup the * bootline and other parameters correctly. * ====================================================================== */ -int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { unsigned long addr; /* Address of image */ unsigned long bootaddr; /* Address to put the bootline */ @@ -96,12 +96,10 @@ int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) * If we don't know where the image is then we're done. */ - if ((tmp = getenv ("loadaddr")) != NULL) { - addr = simple_strtoul (tmp, NULL, 16); - } else { - puts ("No load address provided\n"); - return 1; - } + if (argc < 2) + addr = load_addr; + else + addr = simple_strtoul (argv[1], NULL, 16); #if (CONFIG_COMMANDS & CFG_CMD_NET) /* Check to see if we need to tftp the image ourselves before starting */ From 1eac2a71417b6675b11aace72102a2e7fde8f5c6 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 29 Nov 2006 15:42:37 +0100 Subject: [PATCH 3/5] [PATCH] Add support for Prodrive P3M750 & P3M7448 (P3Mx) boards This patch adds support for the Prodrive P3M750 (PPC750 & MV64460) and the P3M7448 (MPC7448 & MV64460) PMC modules. Both modules are quite similar and share the same board directory "prodrive/p3mx" and the same config file "p3mx.h". Signed-off-by: Stefan Roese --- MAINTAINERS | 4 + MAKEALL | 5 +- Makefile | 10 + board/prodrive/p3mx/64460.h | 52 + board/prodrive/p3mx/Makefile | 55 + board/prodrive/p3mx/config.mk | 28 + board/prodrive/p3mx/eth.h | 43 + board/prodrive/p3mx/misc.S | 245 ++ board/prodrive/p3mx/mpsc.c | 1013 +++++++++ board/prodrive/p3mx/mpsc.h | 156 ++ board/prodrive/p3mx/mv_eth.c | 3418 ++++++++++++++++++++++++++++ board/prodrive/p3mx/mv_eth.h | 840 +++++++ board/prodrive/p3mx/mv_regs.h | 1125 +++++++++ board/prodrive/p3mx/p3mx.c | 809 +++++++ board/prodrive/p3mx/pci.c | 1025 +++++++++ board/prodrive/p3mx/ppc_error_no.h | 164 ++ board/prodrive/p3mx/sdram_init.c | 433 ++++ board/prodrive/p3mx/serial.c | 107 + board/prodrive/p3mx/serial.h | 89 + board/prodrive/p3mx/u-boot.lds | 138 ++ cpu/74xx_7xx/cpu.c | 8 + cpu/74xx_7xx/cpu_init.c | 1 + cpu/74xx_7xx/speed.c | 1 + cpu/74xx_7xx/start.S | 8 +- include/74xx_7xx.h | 1 + include/configs/p3mx.h | 450 ++++ net/eth.c | 7 +- 27 files changed, 10225 insertions(+), 10 deletions(-) create mode 100644 board/prodrive/p3mx/64460.h create mode 100644 board/prodrive/p3mx/Makefile create mode 100644 board/prodrive/p3mx/config.mk create mode 100644 board/prodrive/p3mx/eth.h create mode 100644 board/prodrive/p3mx/misc.S create mode 100644 board/prodrive/p3mx/mpsc.c create mode 100644 board/prodrive/p3mx/mpsc.h create mode 100644 board/prodrive/p3mx/mv_eth.c create mode 100644 board/prodrive/p3mx/mv_eth.h create mode 100644 board/prodrive/p3mx/mv_regs.h create mode 100644 board/prodrive/p3mx/p3mx.c create mode 100644 board/prodrive/p3mx/pci.c create mode 100644 board/prodrive/p3mx/ppc_error_no.h create mode 100644 board/prodrive/p3mx/sdram_init.c create mode 100644 board/prodrive/p3mx/serial.c create mode 100644 board/prodrive/p3mx/serial.h create mode 100644 board/prodrive/p3mx/u-boot.lds create mode 100644 include/configs/p3mx.h diff --git a/MAINTAINERS b/MAINTAINERS index d4539671f9..df0f567397 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -277,6 +277,8 @@ Daniel Poirot Stefan Roese + P3M7448 MPC7448 + uc100 MPC857 TQM85xx MPC8540/8541/8555/8560 @@ -294,6 +296,8 @@ Stefan Roese yellowstone PPC440GR yosemite PPC440EP + P3M750 PPC750FX/GX/GL + Yusdi Santoso HIDDEN_DRAGON MPC8241/MPC8245 diff --git a/MAKEALL b/MAKEALL index 84a708a983..a3d026a5b1 100755 --- a/MAKEALL +++ b/MAKEALL @@ -151,11 +151,12 @@ LIST_85xx=" \ LIST_74xx=" \ DB64360 DB64460 EVB64260 P3G4 \ - PCIPPC2 PCIPPC6 ZUMA \ + p3m7448 PCIPPC2 PCIPPC6 ZUMA \ " LIST_7xx=" \ - BAB7xx CPCI750 ELPPC ppmc7xx \ + BAB7xx CPCI750 ELPPC p3m750 \ + ppmc7xx \ " LIST_ppc="${LIST_5xx} ${LIST_5xxx} \ diff --git a/Makefile b/Makefile index 37d782dee2..69e1e559dc 100644 --- a/Makefile +++ b/Makefile @@ -1724,6 +1724,16 @@ EVB64260_750CX_config: unconfig P3G4_config: unconfig @$(MKCONFIG) $(@:_config=) ppc 74xx_7xx evb64260 +p3m750_config \ +p3m7448_config: unconfig + @mkdir -p $(obj)include + @if [ "$(findstring 750_,$@)" ] ; then \ + echo "#define CONFIG_P3M750" >>$(obj)include/config.h ; \ + else \ + echo "#define CONFIG_P3M7448" >>$(obj)include/config.h ; \ + fi + @$(MKCONFIG) -a p3mx ppc 74xx_7xx p3mx prodrive + PCIPPC2_config \ PCIPPC6_config: unconfig @$(MKCONFIG) $(@:_config=) ppc 74xx_7xx pcippc2 diff --git a/board/prodrive/p3mx/64460.h b/board/prodrive/p3mx/64460.h new file mode 100644 index 0000000000..8bb0ebfd21 --- /dev/null +++ b/board/prodrive/p3mx/64460.h @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus + * + * 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 + */ + +/* + * main board support/init for the Galileo Eval board DB64460. + */ + +#ifndef __64460_H__ +#define __64460_H__ + +/* CPU Configuration bits */ +#define CPU_CONF_ADDR_MISS_EN (1 << 8) +#define CPU_CONF_SINGLE_CPU (1 << 11) +#define CPU_CONF_ENDIANESS (1 << 12) +#define CPU_CONF_PIPELINE (1 << 13) +#define CPU_CONF_STOP_RETRY (1 << 17) +#define CPU_CONF_MULTI_DECODE (1 << 18) +#define CPU_CONF_DP_VALID (1 << 19) +#define CPU_CONF_PERR_PROP (1 << 22) +#define CPU_CONF_AACK_DELAY_2 (1 << 25) +#define CPU_CONF_AP_VALID (1 << 26) +#define CPU_CONF_REMAP_WR_DIS (1 << 27) + +/* CPU Master Control bits */ +#define CPU_MAST_CTL_ARB_EN (1 << 8) +#define CPU_MAST_CTL_MASK_BR_1 (1 << 9) +#define CPU_MAST_CTL_M_WR_TRIG (1 << 10) +#define CPU_MAST_CTL_M_RD_TRIG (1 << 11) +#define CPU_MAST_CTL_CLEAN_BLK (1 << 12) +#define CPU_MAST_CTL_FLUSH_BLK (1 << 13) + +#endif /* __64460_H__ */ diff --git a/board/prodrive/p3mx/Makefile b/board/prodrive/p3mx/Makefile new file mode 100644 index 0000000000..bf74a5a83b --- /dev/null +++ b/board/prodrive/p3mx/Makefile @@ -0,0 +1,55 @@ +# +# (C) Copyright 2002-2006 +# 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 +ifneq ($(OBJTREE),$(SRCTREE)) +$(shell mkdir -p $(obj)../../Marvell/common) +endif + +LIB = $(obj)lib$(BOARD).a + +SOBJS = misc.o +COBJS = $(BOARD).o mpsc.o mv_eth.o pci.o sdram_init.o serial.o \ + ../../Marvell/common/i2c.o ../../Marvell/common/memory.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +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/prodrive/p3mx/config.mk b/board/prodrive/p3mx/config.mk new file mode 100644 index 0000000000..35bf1c1554 --- /dev/null +++ b/board/prodrive/p3mx/config.mk @@ -0,0 +1,28 @@ +# +# (C) Copyright 2002-2006 +# 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 +# + +# +# p3mx boards (P3M750 & P3M7448) +# + +TEXT_BASE = 0xfff00000 diff --git a/board/prodrive/p3mx/eth.h b/board/prodrive/p3mx/eth.h new file mode 100644 index 0000000000..aab32d2a5a --- /dev/null +++ b/board/prodrive/p3mx/eth.h @@ -0,0 +1,43 @@ +/* + * (C) Copyright 2001 + * Josh Huber , Mission Critical Linux, 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 + */ + +/* + * eth.h - header file for the polled mode GT ethernet driver + */ + +#ifndef __EVB64360_ETH_H__ +#define __EVB64360_ETH_H__ + +#include +#include +#include +#include + + +int db64360_eth0_poll(void); +int db64360_eth0_transmit(unsigned int s, volatile char *p); +void db64360_eth0_disable(void); +bool network_start(bd_t *bis); + + +#endif /* __EVB64360_ETH_H__ */ diff --git a/board/prodrive/p3mx/misc.S b/board/prodrive/p3mx/misc.S new file mode 100644 index 0000000000..160b1d31f7 --- /dev/null +++ b/board/prodrive/p3mx/misc.S @@ -0,0 +1,245 @@ +#include +#include <74xx_7xx.h> +#include "version.h" + +#include +#include + +#include +#include + +#include "../../Marvell/include/mv_gen_reg.h" + +#ifdef CONFIG_ECC + /* Galileo specific asm code for initializing ECC */ + .globl board_relocate_rom +board_relocate_rom: + mflr r7 + /* update the location of the GT registers */ + lis r11, CFG_GT_REGS@h + /* if we're using ECC, we must use the DMA engine to copy ourselves */ + bl start_idma_transfer_0 + bl wait_for_idma_0 + bl stop_idma_engine_0 + + mtlr r7 + blr + + .globl board_init_ecc +board_init_ecc: + mflr r7 + /* NOTE: r10 still contains the location we've been relocated to + * which happens to be TOP_OF_RAM - CFG_MONITOR_LEN */ + + /* now that we're running from ram, init the rest of main memory + * for ECC use */ + lis r8, CFG_MONITOR_LEN@h + ori r8, r8, CFG_MONITOR_LEN@l + + divw r3, r10, r8 + + /* set up the counter, and init the starting address */ + mtctr r3 + li r12, 0 + + /* bytes per transfer */ + mr r5, r8 +about_to_init_ecc: +1: mr r3, r12 + mr r4, r12 + bl start_idma_transfer_0 + bl wait_for_idma_0 + bl stop_idma_engine_0 + add r12, r12, r8 + bdnz 1b + + mtlr r7 + blr + + /* r3: dest addr + * r4: source addr + * r5: byte count + * r11: gt regbase + * trashes: r6, r5 + */ +start_idma_transfer_0: + /* set the byte count, including the OWN bit */ + mr r6, r11 + ori r6, r6, CHANNEL0_DMA_BYTE_COUNT + stwbrx r5, 0, (r6) + + /* set the source address */ + mr r6, r11 + ori r6, r6, CHANNEL0_DMA_SOURCE_ADDRESS + stwbrx r4, 0, (r6) + + /* set the dest address */ + mr r6, r11 + ori r6, r6, CHANNEL0_DMA_DESTINATION_ADDRESS + stwbrx r3, 0, (r6) + + /* set the next record pointer */ + li r5, 0 + mr r6, r11 + ori r6, r6, CHANNEL0NEXT_RECORD_POINTER + stwbrx r5, 0, (r6) + + /* set the low control register */ + /* bit 9 is NON chained mode, bit 31 is new style descriptors. + bit 12 is channel enable */ + ori r5, r5, (1 << 12) | (1 << 12) | (1 << 11) + /* 15 shifted by 16 (oris) == bit 31 */ + oris r5, r5, (1 << 15) + mr r6, r11 + ori r6, r6, CHANNEL0CONTROL + stwbrx r5, 0, (r6) + + blr + + /* this waits for the bytecount to return to zero, indicating + * that the trasfer is complete */ +wait_for_idma_0: + mr r5, r11 + lis r6, 0xff + ori r6, r6, 0xffff + ori r5, r5, CHANNEL0_DMA_BYTE_COUNT +1: lwbrx r4, 0, (r5) + and. r4, r4, r6 + bne 1b + + blr + + /* this turns off channel 0 of the idma engine */ +stop_idma_engine_0: + /* shut off the DMA engine */ + li r5, 0 + mr r6, r11 + ori r6, r6, CHANNEL0CONTROL + stwbrx r5, 0, (r6) + + blr +#endif + +#ifdef CFG_BOARD_ASM_INIT + /* NOTE: trashes r3-r7 */ + .globl board_asm_init +board_asm_init: + /* just move the GT registers to where they belong */ + lis r3, CFG_DFL_GT_REGS@h + ori r3, r3, CFG_DFL_GT_REGS@l + lis r4, CFG_GT_REGS@h + ori r4, r4, CFG_GT_REGS@l + li r5, INTERNAL_SPACE_DECODE + + /* test to see if we've already moved */ + lwbrx r6, r5, r4 + andi. r6, r6, 0xffff + /* check loading of R7 is: 0x0F80 should: 0xf800: DONE */ +/* rlwinm r7, r4, 8, 16, 31 + rlwinm r7, r4, 12, 16, 31 */ /* original */ + rlwinm r7, r4, 16, 16, 31 + /* -----------------------------------------------------*/ + cmp cr0, r7, r6 + beqlr + + /* nope, have to move the registers */ + lwbrx r6, r5, r3 + andis. r6, r6, 0xffff + or r6, r6, r7 + stwbrx r6, r5, r3 + + /* now, poll for the change */ +1: lwbrx r7, r5, r4 + cmp cr0, r7, r6 + bne 1b + + lis r3, CFG_INT_SRAM_BASE@h + ori r3, r3, CFG_INT_SRAM_BASE@l + rlwinm r3, r3, 16, 16, 31 + lis r4, CFG_GT_REGS@h + ori r4, r4, CFG_GT_REGS@l + li r5, INTEGRATED_SRAM_BASE_ADDR + stwbrx r3, r5, r4 + +2: lwbrx r6, r5, r4 + cmp cr0, r3, r6 + bne 2b + + /* done! */ + blr +#endif + +/* For use of the debug LEDs */ + .global led_on0_relocated +led_on0_relocated: + xor r21, r21, r21 + xor r18, r18, r18 + lis r18, 0xFC80 + ori r18, r18, 0x8000 +/* stw r21, 0x0(r18) */ + sync + blr + + .global led_off0_relocated +led_off0_relocated: + xor r21, r21, r21 + xor r18, r18, r18 + lis r18, 0xFC81 + ori r18, r18, 0x4000 +/* stw r21, 0x0(r18) */ + sync + blr + + .global led_on0 +led_on0: + xor r18, r18, r18 + lis r18, 0x1c80 + ori r18, r18, 0x8000 +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_off0 +led_off0: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0x4000 +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_on1 +led_on1: + xor r18, r18, r18 + lis r18, 0x1c80 + ori r18, r18, 0xc000 +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_off1 +led_off1: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0x8000 +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_on2 +led_on2: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0x0000 +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_off2 +led_off2: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0xc000 +/* stw r18, 0x0(r18) */ + sync + blr diff --git a/board/prodrive/p3mx/mpsc.c b/board/prodrive/p3mx/mpsc.c new file mode 100644 index 0000000000..da95cfa777 --- /dev/null +++ b/board/prodrive/p3mx/mpsc.c @@ -0,0 +1,1013 @@ +/* + * (C) Copyright 2001 + * John Clemens , Mission Critical Linux, 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 + */ + +/************************************************************************* + * changes for Marvell DB64460 eval board 2003 by Ingo Assmus + * + ************************************************************************/ + +/* + * mpsc.c - driver for console over the MPSC. + */ + + +#include +#include +#include + +#include +#include "mpsc.h" + +#include "mv_regs.h" + +#include "../../Marvell/include/memory.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* Define this if you wish to use the MPSC as a register based UART. + * This will force the serial port to not use the SDMA engine at all. + */ +#undef CONFIG_MPSC_DEBUG_PORT + + +int (*mpsc_putchar) (char ch) = mpsc_putchar_early; +char (*mpsc_getchar) (void) = mpsc_getchar_debug; +int (*mpsc_test_char) (void) = mpsc_test_char_debug; + + +static volatile unsigned int *rx_desc_base = NULL; +static unsigned int rx_desc_index = 0; +static volatile unsigned int *tx_desc_base = NULL; +static unsigned int tx_desc_index = 0; + +/* local function declarations */ +static int galmpsc_connect (int channel, int connect); +static int galmpsc_route_rx_clock (int channel, int brg); +static int galmpsc_route_tx_clock (int channel, int brg); +static int galmpsc_write_config_regs (int mpsc, int mode); +static int galmpsc_config_channel_regs (int mpsc); +static int galmpsc_set_char_length (int mpsc, int value); +static int galmpsc_set_stop_bit_length (int mpsc, int value); +static int galmpsc_set_parity (int mpsc, int value); +static int galmpsc_enter_hunt (int mpsc); +static int galmpsc_set_brkcnt (int mpsc, int value); +static int galmpsc_set_tcschar (int mpsc, int value); +static int galmpsc_set_snoop (int mpsc, int value); +static int galmpsc_shutdown (int mpsc); + +static int galsdma_set_RFT (int channel); +static int galsdma_set_SFM (int channel); +static int galsdma_set_rxle (int channel); +static int galsdma_set_txle (int channel); +static int galsdma_set_burstsize (int channel, unsigned int value); +static int galsdma_set_RC (int channel, unsigned int value); + +static int galbrg_set_CDV (int channel, int value); +static int galbrg_enable (int channel); +static int galbrg_disable (int channel); +static int galbrg_set_clksrc (int channel, int value); +static int galbrg_set_CUV (int channel, int value); + +static void galsdma_enable_rx (void); +static int galsdma_set_mem_space (unsigned int memSpace, + unsigned int memSpaceTarget, + unsigned int memSpaceAttr, + unsigned int baseAddress, + unsigned int size); + + +#define SOFTWARE_CACHE_MANAGEMENT + +#ifdef SOFTWARE_CACHE_MANAGEMENT +#define FLUSH_DCACHE(a,b) if(dcache_status()){clean_dcache_range((u32)(a),(u32)(b));} +#define FLUSH_AND_INVALIDATE_DCACHE(a,b) if(dcache_status()){flush_dcache_range((u32)(a),(u32)(b));} +#define INVALIDATE_DCACHE(a,b) if(dcache_status()){invalidate_dcache_range((u32)(a),(u32)(b));} +#else +#define FLUSH_DCACHE(a,b) +#define FLUSH_AND_INVALIDATE_DCACHE(a,b) +#define INVALIDATE_DCACHE(a,b) +#endif + +#ifdef CONFIG_MPSC_DEBUG_PORT +static void mpsc_debug_init (void) +{ + + volatile unsigned int temp; + + /* Clear the CFR (CHR4) */ + /* Write random 'Z' bit (bit 29) of CHR4 to enable debug uart *UNDOCUMENTED FEATURE* */ + temp = GTREGREAD (GALMPSC_CHANNELREG_4 + (CHANNEL * GALMPSC_REG_GAP)); + temp &= 0xffffff00; + temp |= BIT29; + GT_REG_WRITE (GALMPSC_CHANNELREG_4 + (CHANNEL * GALMPSC_REG_GAP), + temp); + + /* Set the Valid bit 'V' (bit 12) and int generation bit 'INT' (bit 15) */ + temp = GTREGREAD (GALMPSC_CHANNELREG_5 + (CHANNEL * GALMPSC_REG_GAP)); + temp |= (BIT12 | BIT15); + GT_REG_WRITE (GALMPSC_CHANNELREG_5 + (CHANNEL * GALMPSC_REG_GAP), + temp); + + /* Set int mask */ + temp = GTREGREAD (GALMPSC_0_INT_MASK); + temp |= BIT6; + GT_REG_WRITE (GALMPSC_0_INT_MASK, temp); +} +#endif + +char mpsc_getchar_debug (void) +{ + volatile int temp; + volatile unsigned int cause; + + cause = GTREGREAD (GALMPSC_0_INT_CAUSE); + while ((cause & BIT6) == 0) { + cause = GTREGREAD (GALMPSC_0_INT_CAUSE); + } + + temp = GTREGREAD (GALMPSC_CHANNELREG_10 + + (CHANNEL * GALMPSC_REG_GAP)); + /* By writing 1's to the set bits, the register is cleared */ + GT_REG_WRITE (GALMPSC_CHANNELREG_10 + (CHANNEL * GALMPSC_REG_GAP), + temp); + GT_REG_WRITE (GALMPSC_0_INT_CAUSE, cause & ~BIT6); + return (temp >> 16) & 0xff; +} + +/* special function for running out of flash. doesn't modify any + * global variables [josh] */ +int mpsc_putchar_early (char ch) +{ + int mpsc = CHANNEL; + int temp = + GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); + galmpsc_set_tcschar (mpsc, ch); + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), + temp | 0x200); + +#define MAGIC_FACTOR (10*1000000) + + udelay (MAGIC_FACTOR / gd->baudrate); + return 0; +} + +/* This is used after relocation, see serial.c and mpsc_init2 */ +static int mpsc_putchar_sdma (char ch) +{ + volatile unsigned int *p; + unsigned int temp; + + + /* align the descriptor */ + p = tx_desc_base; + memset ((void *) p, 0, 8 * sizeof (unsigned int)); + + /* fill one 64 bit buffer */ + /* word swap, pad with 0 */ + p[4] = 0; /* x */ + p[5] = (unsigned int) ch; /* x */ + + /* CHANGED completely according to GT64260A dox - NTL */ + p[0] = 0x00010001; /* 0 */ + p[1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; /* 4 */ + p[2] = 0; /* 8 */ + p[3] = (unsigned int) &p[4]; /* c */ + +#if 0 + p[9] = DESC_FIRST | DESC_LAST; + p[10] = (unsigned int) &p[0]; + p[11] = (unsigned int) &p[12]; +#endif + + FLUSH_DCACHE (&p[0], &p[8]); + + GT_REG_WRITE (GALSDMA_0_CUR_TX_PTR + (CHANNEL * GALSDMA_REG_DIFF), + (unsigned int) &p[0]); + GT_REG_WRITE (GALSDMA_0_FIR_TX_PTR + (CHANNEL * GALSDMA_REG_DIFF), + (unsigned int) &p[0]); + + temp = GTREGREAD (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF)); + temp |= (TX_DEMAND | TX_STOP); + GT_REG_WRITE (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF), temp); + + INVALIDATE_DCACHE (&p[1], &p[2]); + + while (p[1] & DESC_OWNER_BIT) { + udelay (100); + INVALIDATE_DCACHE (&p[1], &p[2]); + } + return 0; +} + +char mpsc_getchar_sdma (void) +{ + static unsigned int done = 0; + volatile char ch; + unsigned int len = 0, idx = 0, temp; + + volatile unsigned int *p; + + + do { + p = &rx_desc_base[rx_desc_index * 8]; + + INVALIDATE_DCACHE (&p[0], &p[1]); + /* Wait for character */ + while (p[1] & DESC_OWNER_BIT) { + udelay (100); + INVALIDATE_DCACHE (&p[0], &p[1]); + } + + /* Handle error case */ + if (p[1] & (1 << 15)) { + printf ("oops, error: %08x\n", p[1]); + + temp = GTREGREAD (GALMPSC_CHANNELREG_2 + + (CHANNEL * GALMPSC_REG_GAP)); + temp |= (1 << 23); + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + + (CHANNEL * GALMPSC_REG_GAP), temp); + + /* Can't poll on abort bit, so we just wait. */ + udelay (100); + + galsdma_enable_rx (); + } + + /* Number of bytes left in this descriptor */ + len = p[0] & 0xffff; + + if (len) { + /* Where to look */ + idx = 5; + if (done > 3) + idx = 4; + if (done > 7) + idx = 7; + if (done > 11) + idx = 6; + + INVALIDATE_DCACHE (&p[idx], &p[idx + 1]); + ch = p[idx] & 0xff; + done++; + } + + if (done < len) { + /* this descriptor has more bytes still + * shift down the char we just read, and leave the + * buffer in place for the next time around + */ + p[idx] = p[idx] >> 8; + FLUSH_DCACHE (&p[idx], &p[idx + 1]); + } + + if (done == len) { + /* nothing left in this descriptor. + * go to next one + */ + p[1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; + p[0] = 0x00100000; + FLUSH_DCACHE (&p[0], &p[1]); + /* Next descriptor */ + rx_desc_index = (rx_desc_index + 1) % RX_DESC; + done = 0; + } + } while (len == 0); /* galileo bug.. len might be zero */ + + return ch; +} + + +int mpsc_test_char_debug (void) +{ + if ((GTREGREAD (GALMPSC_0_INT_CAUSE) & BIT6) == 0) + return 0; + else { + return 1; + } +} + + +int mpsc_test_char_sdma (void) +{ + volatile unsigned int *p = &rx_desc_base[rx_desc_index * 8]; + + INVALIDATE_DCACHE (&p[1], &p[2]); + + if (p[1] & DESC_OWNER_BIT) + return 0; + else + return 1; +} + +int mpsc_init (int baud) +{ + /* BRG CONFIG */ + galbrg_set_baudrate (CHANNEL, baud); + galbrg_set_clksrc (CHANNEL, 8); /* set source=Tclk */ + galbrg_set_CUV (CHANNEL, 0); /* set up CountUpValue */ + galbrg_enable (CHANNEL); /* Enable BRG */ + + /* Set up clock routing */ + galmpsc_connect (CHANNEL, GALMPSC_CONNECT); /* connect it */ + + galmpsc_route_rx_clock (CHANNEL, CHANNEL); /* chosse BRG0 for Rx */ + galmpsc_route_tx_clock (CHANNEL, CHANNEL); /* chose BRG0 for Tx */ + + /* reset MPSC state */ + galmpsc_shutdown (CHANNEL); + + /* SDMA CONFIG */ + galsdma_set_burstsize (CHANNEL, L1_CACHE_BYTES / 8); /* in 64 bit words (8 bytes) */ + galsdma_set_txle (CHANNEL); + galsdma_set_rxle (CHANNEL); + galsdma_set_RC (CHANNEL, 0xf); + galsdma_set_SFM (CHANNEL); + galsdma_set_RFT (CHANNEL); + + /* MPSC CONFIG */ + galmpsc_write_config_regs (CHANNEL, GALMPSC_UART); + galmpsc_config_channel_regs (CHANNEL); + galmpsc_set_char_length (CHANNEL, GALMPSC_CHAR_LENGTH_8); /* 8 */ + galmpsc_set_parity (CHANNEL, GALMPSC_PARITY_NONE); /* N */ + galmpsc_set_stop_bit_length (CHANNEL, GALMPSC_STOP_BITS_1); /* 1 */ + +#ifdef CONFIG_MPSC_DEBUG_PORT + mpsc_debug_init (); +#endif + + /* COMM_MPSC CONFIG */ +#ifdef SOFTWARE_CACHE_MANAGEMENT + galmpsc_set_snoop (CHANNEL, 0); /* disable snoop */ +#else + galmpsc_set_snoop (CHANNEL, 1); /* enable snoop */ +#endif + + return 0; +} + + +void mpsc_sdma_init (void) +{ + /* Setup SDMA channel0 SDMA_CONFIG_REG*/ + GT_REG_WRITE (SDMA_CONFIG_REG (0), 0x000020ff); + + /* Enable MPSC-Window0 for DRAM Bank 0 */ + if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT, + MV64460_SDMA_DRAM_CS_0_TARGET, + 0, + memoryGetBankBaseAddress(0), + memoryGetBankSize(0)) != true) + printf ("%s: SDMA_Window0 memory setup failed !!! \n", + __FUNCTION__); + + + /* Enable MPSC-Window1 for DRAM Bank 1 */ + if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_1_BIT, + MV64460_SDMA_DRAM_CS_1_TARGET, + 0, + memoryGetBankBaseAddress(1), + memoryGetBankSize(1)) != true) + printf ("%s: SDMA_Window1 memory setup failed !!! \n", + __FUNCTION__); + + + /* Disable MPSC-Window2 */ + if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_2_BIT, + MV64460_SDMA_DRAM_CS_2_TARGET, + 0, + memoryGetBankBaseAddress(2), + memoryGetBankSize(2)) != true) + printf ("%s: SDMA_Window2 memory setup failed !!! \n", + __FUNCTION__); + + + /* Disable MPSC-Window3 */ + if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_3_BIT, + MV64460_SDMA_DRAM_CS_3_TARGET, + 0, + memoryGetBankBaseAddress(3), + memoryGetBankSize(3)) != true) + printf ("%s: SDMA_Window3 memory setup failed !!! \n", + __FUNCTION__); + + /* Setup MPSC0 access mode Window0 full access */ + GT_SET_REG_BITS (MPSC0_ACCESS_PROTECTION_REG, + (MV64460_SDMA_WIN_ACCESS_FULL << + (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT * 2))); + + /* Setup MPSC1 access mode Window1 full access */ + GT_SET_REG_BITS (MPSC1_ACCESS_PROTECTION_REG, + (MV64460_SDMA_WIN_ACCESS_FULL << + (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT * 2))); + + /* Setup MPSC internal address space base address */ + GT_REG_WRITE (CUNIT_INTERNAL_SPACE_BASE_ADDR_REG, CFG_GT_REGS); + + /* no high address remap*/ + GT_REG_WRITE (CUNIT_HIGH_ADDR_REMAP_REG0, 0x00); + GT_REG_WRITE (CUNIT_HIGH_ADDR_REMAP_REG1, 0x00); + + /* clear interrupt cause register for MPSC (fault register)*/ + GT_REG_WRITE (CUNIT_INTERRUPT_CAUSE_REG, 0x00); +} + + +void mpsc_init2 (void) +{ + int i; + +#ifndef CONFIG_MPSC_DEBUG_PORT + mpsc_putchar = mpsc_putchar_sdma; + mpsc_getchar = mpsc_getchar_sdma; + mpsc_test_char = mpsc_test_char_sdma; +#endif + /* RX descriptors */ + rx_desc_base = (unsigned int *) malloc (((RX_DESC + 1) * 8) * + sizeof (unsigned int)); + + /* align descriptors */ + rx_desc_base = (unsigned int *) + (((unsigned int) rx_desc_base + 32) & 0xFFFFFFF0); + + rx_desc_index = 0; + + memset ((void *) rx_desc_base, 0, + (RX_DESC * 8) * sizeof (unsigned int)); + + for (i = 0; i < RX_DESC; i++) { + rx_desc_base[i * 8 + 3] = (unsigned int) &rx_desc_base[i * 8 + 4]; /* Buffer */ + rx_desc_base[i * 8 + 2] = (unsigned int) &rx_desc_base[(i + 1) * 8]; /* Next descriptor */ + rx_desc_base[i * 8 + 1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; /* Command & control */ + rx_desc_base[i * 8] = 0x00100000; + } + rx_desc_base[(i - 1) * 8 + 2] = (unsigned int) &rx_desc_base[0]; + + FLUSH_DCACHE (&rx_desc_base[0], &rx_desc_base[RX_DESC * 8]); + GT_REG_WRITE (GALSDMA_0_CUR_RX_PTR + (CHANNEL * GALSDMA_REG_DIFF), + (unsigned int) &rx_desc_base[0]); + + /* TX descriptors */ + tx_desc_base = (unsigned int *) malloc (((TX_DESC + 1) * 8) * + sizeof (unsigned int)); + + /* align descriptors */ + tx_desc_base = (unsigned int *) + (((unsigned int) tx_desc_base + 32) & 0xFFFFFFF0); + + tx_desc_index = -1; + + memset ((void *) tx_desc_base, 0, + (TX_DESC * 8) * sizeof (unsigned int)); + + for (i = 0; i < TX_DESC; i++) { + tx_desc_base[i * 8 + 5] = (unsigned int) 0x23232323; + tx_desc_base[i * 8 + 4] = (unsigned int) 0x23232323; + tx_desc_base[i * 8 + 3] = + (unsigned int) &tx_desc_base[i * 8 + 4]; + tx_desc_base[i * 8 + 2] = + (unsigned int) &tx_desc_base[(i + 1) * 8]; + tx_desc_base[i * 8 + 1] = + DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; + + /* set sbytecnt and shadow byte cnt to 1 */ + tx_desc_base[i * 8] = 0x00010001; + } + tx_desc_base[(i - 1) * 8 + 2] = (unsigned int) &tx_desc_base[0]; + + FLUSH_DCACHE (&tx_desc_base[0], &tx_desc_base[TX_DESC * 8]); + + udelay (100); + + galsdma_enable_rx (); + + return; +} + +int galbrg_set_baudrate (int channel, int rate) +{ + int clock; + + galbrg_disable (channel); /*ok */ + +#ifdef ZUMA_NTL + /* from tclk */ + clock = (CFG_TCLK / (16 * rate)) - 1; +#else + clock = (CFG_TCLK / (16 * rate)) - 1; +#endif + + galbrg_set_CDV (channel, clock); /* set timer Reg. for BRG */ + + galbrg_enable (channel); + + gd->baudrate = rate; + + return 0; +} + +/* ------------------------------------------------------------------ */ + +/* Below are all the private functions that no one else needs */ + +static int galbrg_set_CDV (int channel, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp &= 0xFFFF0000; + temp |= (value & 0x0000FFFF); + GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + + return 0; +} + +static int galbrg_enable (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp |= 0x00010000; + GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + + return 0; +} + +static int galbrg_disable (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp &= 0xFFFEFFFF; + GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + + return 0; +} + +static int galbrg_set_clksrc (int channel, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp &= 0xFFC3FFFF; /* Bit 18 - 21 (MV 64260 18-22) */ + temp |= (value << 18); + GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + return 0; +} + +static int galbrg_set_CUV (int channel, int value) +{ + /* set CountUpValue */ + GT_REG_WRITE (GALBRG_0_BTREG + (channel * GALBRG_REG_GAP), value); + + return 0; +} + +#if 0 +static int galbrg_reset (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp |= 0x20000; + GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + + return 0; +} +#endif + +static int galsdma_set_RFT (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp |= 0x00000001; + GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), + temp); + + return 0; +} + +static int galsdma_set_SFM (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp |= 0x00000002; + GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), + temp); + + return 0; +} + +static int galsdma_set_rxle (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp |= 0x00000040; + GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), + temp); + + return 0; +} + +static int galsdma_set_txle (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp |= 0x00000080; + GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), + temp); + + return 0; +} + +static int galsdma_set_RC (int channel, unsigned int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp &= ~0x0000003c; + temp |= (value << 2); + GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), + temp); + + return 0; +} + +static int galsdma_set_burstsize (int channel, unsigned int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp &= 0xFFFFCFFF; + switch (value) { + case 8: + GT_REG_WRITE (GALSDMA_0_CONF_REG + + (channel * GALSDMA_REG_DIFF), + (temp | (0x3 << 12))); + break; + + case 4: + GT_REG_WRITE (GALSDMA_0_CONF_REG + + (channel * GALSDMA_REG_DIFF), + (temp | (0x2 << 12))); + break; + + case 2: + GT_REG_WRITE (GALSDMA_0_CONF_REG + + (channel * GALSDMA_REG_DIFF), + (temp | (0x1 << 12))); + break; + + case 1: + GT_REG_WRITE (GALSDMA_0_CONF_REG + + (channel * GALSDMA_REG_DIFF), + (temp | (0x0 << 12))); + break; + + default: + return -1; + break; + } + + return 0; +} + +static int galmpsc_connect (int channel, int connect) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_ROUTING_REGISTER); + + if ((channel == 0) && connect) + temp &= ~0x00000007; + else if ((channel == 1) && connect) + temp &= ~(0x00000007 << 6); + else if ((channel == 0) && !connect) + temp |= 0x00000007; + else + temp |= (0x00000007 << 6); + + /* Just in case... */ + temp &= 0x3fffffff; + + GT_REG_WRITE (GALMPSC_ROUTING_REGISTER, temp); + + return 0; +} + +static int galmpsc_route_rx_clock (int channel, int brg) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_RxC_ROUTE); + + if (channel == 0) { + temp &= ~0x0000000F; + temp |= brg; + } else { + temp &= ~0x00000F00; + temp |= (brg << 8); + } + + GT_REG_WRITE (GALMPSC_RxC_ROUTE, temp); + + return 0; +} + +static int galmpsc_route_tx_clock (int channel, int brg) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_TxC_ROUTE); + + if (channel == 0) { + temp &= ~0x0000000F; + temp |= brg; + } else { + temp &= ~0x00000F00; + temp |= (brg << 8); + } + + GT_REG_WRITE (GALMPSC_TxC_ROUTE, temp); + + return 0; +} + +static int galmpsc_write_config_regs (int mpsc, int mode) +{ + if (mode == GALMPSC_UART) { + /* Main config reg Low (Null modem, Enable Tx/Rx, UART mode) */ + GT_REG_WRITE (GALMPSC_MCONF_LOW + (mpsc * GALMPSC_REG_GAP), + 0x000004c4); + + /* Main config reg High (32x Rx/Tx clock mode, width=8bits */ + GT_REG_WRITE (GALMPSC_MCONF_HIGH + (mpsc * GALMPSC_REG_GAP), + 0x024003f8); + /* 22 2222 1111 */ + /* 54 3210 9876 */ + /* 0000 0010 0000 0000 */ + /* 1 */ + /* 098 7654 3210 */ + /* 0000 0011 1111 1000 */ + } else + return -1; + + return 0; +} + +static int galmpsc_config_channel_regs (int mpsc) +{ + GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_3 + (mpsc * GALMPSC_REG_GAP), 1); + GT_REG_WRITE (GALMPSC_CHANNELREG_4 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_5 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_6 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_7 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_8 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_9 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_10 + (mpsc * GALMPSC_REG_GAP), 0); + + galmpsc_set_brkcnt (mpsc, 0x3); + galmpsc_set_tcschar (mpsc, 0xab); + + return 0; +} + +static int galmpsc_set_brkcnt (int mpsc, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP)); + temp &= 0x0000FFFF; + temp |= (value << 16); + GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), temp); + + return 0; +} + +static int galmpsc_set_tcschar (int mpsc, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP)); + temp &= 0xFFFF0000; + temp |= value; + GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), temp); + + return 0; +} + +static int galmpsc_set_char_length (int mpsc, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP)); + temp &= 0xFFFFCFFF; + temp |= (value << 12); + GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), temp); + + return 0; +} + +static int galmpsc_set_stop_bit_length (int mpsc, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP)); + temp &= 0xFFFFBFFF; + temp |= (value << 14); + GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), temp); + + return 0; +} + +static int galmpsc_set_parity (int mpsc, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); + if (value != -1) { + temp &= 0xFFF3FFF3; + temp |= ((value << 18) | (value << 2)); + temp |= ((value << 17) | (value << 1)); + } else { + temp &= 0xFFF1FFF1; + } + + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); + + return 0; +} + +static int galmpsc_enter_hunt (int mpsc) +{ + int temp; + + temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); + temp |= 0x80000000; + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); + + while (GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)) & + MPSC_ENTER_HUNT) { + udelay (1); + } + return 0; +} + + +static int galmpsc_shutdown (int mpsc) +{ + unsigned int temp; + + /* cause RX abort (clears RX) */ + temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); + temp |= MPSC_RX_ABORT | MPSC_TX_ABORT; + temp &= ~MPSC_ENTER_HUNT; + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); + + GT_REG_WRITE (GALSDMA_0_COM_REG, 0); + GT_REG_WRITE (GALSDMA_0_COM_REG, SDMA_TX_ABORT | SDMA_RX_ABORT); + + /* shut down the MPSC */ + GT_REG_WRITE (GALMPSC_MCONF_LOW, 0); + GT_REG_WRITE (GALMPSC_MCONF_HIGH, 0); + GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), 0); + + udelay (100); + + /* shut down the sdma engines. */ + /* reset config to default */ + GT_REG_WRITE (GALSDMA_0_CONF_REG, 0x000000fc); + + udelay (100); + + /* clear the SDMA current and first TX and RX pointers */ + GT_REG_WRITE (GALSDMA_0_CUR_RX_PTR, 0); + GT_REG_WRITE (GALSDMA_0_CUR_TX_PTR, 0); + GT_REG_WRITE (GALSDMA_0_FIR_TX_PTR, 0); + + udelay (100); + + return 0; +} + +static void galsdma_enable_rx (void) +{ + int temp; + + /* Enable RX processing */ + temp = GTREGREAD (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF)); + temp |= RX_ENABLE; + GT_REG_WRITE (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF), temp); + + galmpsc_enter_hunt (CHANNEL); +} + +static int galmpsc_set_snoop (int mpsc, int value) +{ + int reg = + mpsc ? MPSC_1_ADDRESS_CONTROL_LOW : + MPSC_0_ADDRESS_CONTROL_LOW; + int temp = GTREGREAD (reg); + + if (value) + temp |= (1 << 6) | (1 << 14) | (1 << 22) | (1 << 30); + else + temp &= ~((1 << 6) | (1 << 14) | (1 << 22) | (1 << 30)); + GT_REG_WRITE (reg, temp); + return 0; +} + +/******************************************************************************* +* galsdma_set_mem_space - Set MV64460 IDMA memory decoding map. +* +* DESCRIPTION: +* the MV64460 SDMA has its own address decoding map that is de-coupled +* from the CPU interface address decoding windows. The SDMA channels +* share four address windows. Each region can be individually configured +* by this function by associating it to a target interface and setting +* base and size values. +* +* NOTE!!! +* The size must be in 64Kbyte granularity. +* The base address must be aligned to the size. +* The size must be a series of 1s followed by a series of zeros +* +* OUTPUT: +* None. +* +* RETURN: +* True for success, false otherwise. +* +*******************************************************************************/ + +static int galsdma_set_mem_space (unsigned int memSpace, + unsigned int memSpaceTarget, + unsigned int memSpaceAttr, + unsigned int baseAddress, unsigned int size) +{ + unsigned int temp; + + if (size == 0) { + GT_RESET_REG_BITS (MV64460_CUNIT_BASE_ADDR_ENABLE_REG, + 1 << memSpace); + return true; + } + + /* The base address must be aligned to the size. */ + if (baseAddress % size != 0) { + return false; + } + if (size < 0x10000) { + return false; + } + + /* Align size and base to 64K */ + baseAddress &= 0xffff0000; + size &= 0xffff0000; + temp = size >> 16; + + /* Checking that the size is a sequence of '1' followed by a + sequence of '0' starting from LSB to MSB. */ + while ((temp > 0) && (temp & 0x1)) { + temp = temp >> 1; + } + + if (temp != 0) { + GT_REG_WRITE (MV64460_CUNIT_BASE_ADDR_REG0 + memSpace * 8, + (baseAddress | memSpaceTarget | memSpaceAttr)); + GT_REG_WRITE ((MV64460_CUNIT_SIZE0 + memSpace * 8), + (size - 1) & 0xffff0000); + GT_RESET_REG_BITS (MV64460_CUNIT_BASE_ADDR_ENABLE_REG, + 1 << memSpace); + } else { + /* An invalid size was specified */ + return false; + } + return true; +} diff --git a/board/prodrive/p3mx/mpsc.h b/board/prodrive/p3mx/mpsc.h new file mode 100644 index 0000000000..a03d1cc0f8 --- /dev/null +++ b/board/prodrive/p3mx/mpsc.h @@ -0,0 +1,156 @@ +/* + * (C) Copyright 2001 + * John Clemens , Mission Critical Linux, 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 + */ + +/************************************************************************* + * changes for Marvell DB64360 eval board 2003 by Ingo Assmus + * + ************************************************************************/ + + +/* + * mpsc.h - header file for MPSC in uart mode (console driver) + */ + +#ifndef __MPSC_H__ +#define __MPSC_H__ + +/* include actual Galileo defines */ +#include "../../Marvell/include/mv_gen_reg.h" + +/* driver related defines */ + +int mpsc_init(int baud); +void mpsc_sdma_init(void); +void mpsc_init2(void); +int galbrg_set_baudrate(int channel, int rate); + +int mpsc_putchar_early(char ch); +char mpsc_getchar_debug(void); +int mpsc_test_char_debug(void); + +int mpsc_test_char_sdma(void); + +extern int (*mpsc_putchar)(char ch); +extern char (*mpsc_getchar)(void); +extern int (*mpsc_test_char)(void); + +#define CHANNEL CONFIG_MPSC_PORT + +#define TX_DESC 5 +#define RX_DESC 20 + +#define DESC_FIRST 0x00010000 +#define DESC_LAST 0x00020000 +#define DESC_OWNER_BIT 0x80000000 + +#define TX_DEMAND 0x00800000 +#define TX_STOP 0x00010000 +#define RX_ENABLE 0x00000080 + +#define SDMA_RX_ABORT (1 << 15) +#define SDMA_TX_ABORT (1 << 31) +#define MPSC_TX_ABORT (1 << 7) +#define MPSC_RX_ABORT (1 << 23) +#define MPSC_ENTER_HUNT (1 << 31) + +/* MPSC defines */ + +#define GALMPSC_CONNECT 0x1 +#define GALMPSC_DISCONNECT 0x0 + +#define GALMPSC_UART 0x1 + +#define GALMPSC_STOP_BITS_1 0x0 +#define GALMPSC_STOP_BITS_2 0x1 +#define GALMPSC_CHAR_LENGTH_8 0x3 +#define GALMPSC_CHAR_LENGTH_7 0x2 + +#define GALMPSC_PARITY_ODD 0x0 +#define GALMPSC_PARITY_EVEN 0x2 +#define GALMPSC_PARITY_MARK 0x3 +#define GALMPSC_PARITY_SPACE 0x1 +#define GALMPSC_PARITY_NONE -1 + +#define GALMPSC_SERIAL_MULTIPLEX SERIAL_PORT_MULTIPLEX /* 0xf010 */ +#define GALMPSC_ROUTING_REGISTER MAIN_ROUTING_REGISTER /* 0xb400 */ +#define GALMPSC_RxC_ROUTE RECEIVE_CLOCK_ROUTING_REGISTER /* 0xb404 */ +#define GALMPSC_TxC_ROUTE TRANSMIT_CLOCK_ROUTING_REGISTER /* 0xb408 */ +#define GALMPSC_MCONF_LOW MPSC0_MAIN_CONFIGURATION_LOW /* 0x8000 */ +#define GALMPSC_MCONF_HIGH MPSC0_MAIN_CONFIGURATION_HIGH /* 0x8004 */ +#define GALMPSC_PROTOCONF_REG MPSC0_PROTOCOL_CONFIGURATION /* 0x8008 */ + +#define GALMPSC_REG_GAP 0x1000 + +#define GALMPSC_MCONF_CHREG_BASE CHANNEL0_REGISTER1 /* 0x800c */ +#define GALMPSC_CHANNELREG_1 CHANNEL0_REGISTER1 /* 0x800c */ +#define GALMPSC_CHANNELREG_2 CHANNEL0_REGISTER2 /* 0x8010 */ +#define GALMPSC_CHANNELREG_3 CHANNEL0_REGISTER3 /* 0x8014 */ +#define GALMPSC_CHANNELREG_4 CHANNEL0_REGISTER4 /* 0x8018 */ +#define GALMPSC_CHANNELREG_5 CHANNEL0_REGISTER5 /* 0x801c */ +#define GALMPSC_CHANNELREG_6 CHANNEL0_REGISTER6 /* 0x8020 */ +#define GALMPSC_CHANNELREG_7 CHANNEL0_REGISTER7 /* 0x8024 */ +#define GALMPSC_CHANNELREG_8 CHANNEL0_REGISTER8 /* 0x8028 */ +#define GALMPSC_CHANNELREG_9 CHANNEL0_REGISTER9 /* 0x802c */ +#define GALMPSC_CHANNELREG_10 CHANNEL0_REGISTER10 /* 0x8030 */ +#define GALMPSC_CHANNELREG_11 CHANNEL0_REGISTER11 /* 0x8034 */ + +#define GALSDMA_COMMAND_FIRST (1 << 16) +#define GALSDMA_COMMAND_LAST (1 << 17) +#define GALSDMA_COMMAND_ENABLEINT (1 << 23) +#define GALSDMA_COMMAND_AUTO (1 << 30) +#define GALSDMA_COMMAND_OWNER (1 << 31) + +#define GALSDMA_RX 0 +#define GALSDMA_TX 1 + +/* CHANNEL2 should be CHANNEL1, according to documentation, + * but to work with the current GTREGS file... + */ +#define GALSDMA_0_CONF_REG CHANNEL0_CONFIGURATION_REGISTER /* 0x4000 */ +#define GALSDMA_1_CONF_REG CHANNEL2_CONFIGURATION_REGISTER /* 0x6000 */ +#define GALSDMA_0_COM_REG CHANNEL0_COMMAND_REGISTER /* 0x4008 */ +#define GALSDMA_1_COM_REG CHANNEL2_COMMAND_REGISTER /* 0x6008 */ +#define GALSDMA_0_CUR_RX_PTR CHANNEL0_CURRENT_RX_DESCRIPTOR_POINTER /* 0x4810 */ +#define GALSDMA_0_CUR_TX_PTR CHANNEL0_CURRENT_TX_DESCRIPTOR_POINTER /* 0x4c10 */ +#define GALSDMA_0_FIR_TX_PTR CHANNEL0_FIRST_TX_DESCRIPTOR_POINTER /* 0x4c14 */ +#define GALSDMA_1_CUR_RX_PTR CHANNEL2_CURRENT_RX_DESCRIPTOR_POINTER /* 0x6810 */ +#define GALSDMA_1_CUR_TX_PTR CHANNEL2_CURRENT_TX_DESCRIPTOR_POINTER /* 0x6c10 */ +#define GALSDMA_1_FIR_TX_PTR CHANNEL2_FIRST_TX_DESCRIPTOR_POINTER /* 0x6c14 */ +#define GALSDMA_REG_DIFF 0x2000 + +/* WRONG in gt64260R.h */ +#define GALSDMA_INT_CAUSE 0xb800 /* SDMA_CAUSE */ +#define GALSDMA_INT_MASK 0xb880 /* SDMA_MASK */ +#define GALMPSC_0_INT_CAUSE 0xb804 +#define GALMPSC_0_INT_MASK 0xb884 + +#define GALSDMA_MODE_UART 0 +#define GALSDMA_MODE_BISYNC 1 +#define GALSDMA_MODE_HDLC 2 +#define GALSDMA_MODE_TRANSPARENT 3 + +#define GALBRG_0_CONFREG BRG0_CONFIGURATION_REGISTER /* 0xb200 */ +#define GALBRG_REG_GAP 0x0008 +#define GALBRG_0_BTREG BRG0_BAUDE_TUNING_REGISTER /* 0xb204 */ + +#endif /* __MPSC_H__ */ diff --git a/board/prodrive/p3mx/mv_eth.c b/board/prodrive/p3mx/mv_eth.c new file mode 100644 index 0000000000..1127673648 --- /dev/null +++ b/board/prodrive/p3mx/mv_eth.c @@ -0,0 +1,3418 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus + * + * based on - Driver for MV64460X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + * + * 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 + 3 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 + */ + +/* + * mv_eth.c - header file for the polled mode GT ethernet driver + */ +#include +#include +#include +#include + +#include "mv_eth.h" + +/* enable Debug outputs */ + +#undef DEBUG_MV_ETH + +#ifdef DEBUG_MV_ETH +#define DEBUG +#define DP(x) x +#else +#define DP(x) +#endif + +/* PHY DFCDL Registers */ +#define ETH_PHY_DFCDL_CONFIG0_REG 0x2100 +#define ETH_PHY_DFCDL_CONFIG1_REG 0x2104 +#define ETH_PHY_DFCDL_ADDR_REG 0x2110 +#define ETH_PHY_DFCDL_DATA0_REG 0x2114 + +#define PHY_AUTONEGOTIATE_TIMEOUT 4000 /* 4000 ms autonegotiate timeout */ +#define PHY_UPDATE_TIMEOUT 10000 + +#undef MV64460_CHECKSUM_OFFLOAD +/************************************************************************* +************************************************************************** +************************************************************************** +* The first part is the high level driver of the gigE ethernet ports. * +************************************************************************** +************************************************************************** +*************************************************************************/ + +/* Definition for configuring driver */ +/* #define UPDATE_STATS_BY_SOFTWARE */ +#undef MV64460_RX_QUEUE_FILL_ON_TASK + + +/* Constants */ +#define MAGIC_ETH_RUNNING 8031971 +#define MV64460_INTERNAL_SRAM_SIZE _256K +#define EXTRA_BYTES 32 +#define WRAP ETH_HLEN + 2 + 4 + 16 +#define BUFFER_MTU dev->mtu + WRAP +#define INT_CAUSE_UNMASK_ALL 0x0007ffff +#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff +#ifdef MV64460_RX_FILL_ON_TASK +#define INT_CAUSE_MASK_ALL 0x00000000 +#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL +#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT +#endif + +/* Read/Write to/from MV64460 internal registers */ +#define MV_REG_READ(offset) my_le32_to_cpu(* (volatile unsigned int *) (INTERNAL_REG_BASE_ADDR + offset)) +#define MV_REG_WRITE(offset,data) *(volatile unsigned int *) (INTERNAL_REG_BASE_ADDR + offset) = my_cpu_to_le32 (data) +#define MV_SET_REG_BITS(regOffset,bits) ((*((volatile unsigned int*)((INTERNAL_REG_BASE_ADDR) + (regOffset)))) |= ((unsigned int)my_cpu_to_le32(bits))) +#define MV_RESET_REG_BITS(regOffset,bits) ((*((volatile unsigned int*)((INTERNAL_REG_BASE_ADDR) + (regOffset)))) &= ~((unsigned int)my_cpu_to_le32(bits))) + +#define my_cpu_to_le32(x) my_le32_to_cpu((x)) + +/* Static function declarations */ +static int mv64460_eth_real_open (struct eth_device *eth); +static int mv64460_eth_real_stop (struct eth_device *eth); +static struct net_device_stats *mv64460_eth_get_stats (struct eth_device + *dev); +static void eth_port_init_mac_tables (ETH_PORT eth_port_num); +static void mv64460_eth_update_stat (struct eth_device *dev); +bool db64460_eth_start (struct eth_device *eth); +unsigned int eth_read_mib_counter (ETH_PORT eth_port_num, + unsigned int mib_offset); +int mv64460_eth_receive (struct eth_device *dev); + +int mv64460_eth_xmit (struct eth_device *, volatile void *packet, int length); + +int mv_miiphy_read(char *devname, unsigned char phy_addr, + unsigned char phy_reg, unsigned short *value); +int mv_miiphy_write(char *devname, unsigned char phy_addr, + unsigned char phy_reg, unsigned short value); + +int phy_setup_aneg (char *devname, unsigned char addr); + +#ifndef UPDATE_STATS_BY_SOFTWARE +static void mv64460_eth_print_stat (struct eth_device *dev); +#endif +/* Processes a received packet */ +extern void NetReceive (volatile uchar *, int); + +extern unsigned int INTERNAL_REG_BASE_ADDR; + +unsigned long my_le32_to_cpu (unsigned long x) +{ + return (((x & 0x000000ffU) << 24) | + ((x & 0x0000ff00U) << 8) | + ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24)); +} + +/************************************************* + *Helper functions - used inside the driver only * + *************************************************/ +#ifdef DEBUG_MV_ETH +void print_globals (struct eth_device *dev) +{ + printf ("Ethernet PRINT_Globals-Debug function\n"); + printf ("Base Address for ETH_PORT_INFO: %08x\n", + (unsigned int) dev->priv); + printf ("Base Address for mv64460_eth_priv: %08x\n", + (unsigned int) &(((ETH_PORT_INFO *) dev->priv)-> + port_private)); + + printf ("GT Internal Base Address: %08x\n", + INTERNAL_REG_BASE_ADDR); + printf ("Base Address for TX-DESCs: %08x Number of allocated Buffers %d\n", (unsigned int) ((ETH_PORT_INFO *) dev->priv)->p_tx_desc_area_base[0], MV64460_TX_QUEUE_SIZE); + printf ("Base Address for RX-DESCs: %08x Number of allocated Buffers %d\n", (unsigned int) ((ETH_PORT_INFO *) dev->priv)->p_rx_desc_area_base[0], MV64460_RX_QUEUE_SIZE); + printf ("Base Address for RX-Buffer: %08x allocated Bytes %d\n", + (unsigned int) ((ETH_PORT_INFO *) dev->priv)-> + p_rx_buffer_base[0], + (MV64460_RX_QUEUE_SIZE * MV64460_RX_BUFFER_SIZE) + 32); + printf ("Base Address for TX-Buffer: %08x allocated Bytes %d\n", + (unsigned int) ((ETH_PORT_INFO *) dev->priv)-> + p_tx_buffer_base[0], + (MV64460_TX_QUEUE_SIZE * MV64460_TX_BUFFER_SIZE) + 32); +} +#endif + + + +/********************************************************************** + * mv64460_eth_print_phy_status + * + * Prints gigabit ethenret phy status + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + **********************************************************************/ +void mv64460_eth_print_phy_status (struct eth_device *dev) +{ + struct mv64460_eth_priv *port_private; + unsigned int port_num; + ETH_PORT_INFO *ethernet_private = (ETH_PORT_INFO *) dev->priv; + unsigned int port_status, phy_reg_data; + + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Check Link status on phy */ + eth_port_read_smi_reg (port_num, 1, &phy_reg_data); + if (!(phy_reg_data & 0x20)) { + printf ("Ethernet port changed link status to DOWN\n"); + } else { + port_status = + MV_REG_READ (MV64460_ETH_PORT_STATUS_REG (port_num)); + printf ("Ethernet status port %d: Link up", port_num); + printf (", %s", + (port_status & BIT2) ? "Full Duplex" : "Half Duplex"); + if (port_status & BIT4) + printf (", Speed 1 Gbps"); + else + printf (", %s", + (port_status & BIT5) ? "Speed 100 Mbps" : + "Speed 10 Mbps"); + printf ("\n"); + } +} + +/********************************************************************** + * u-boot entry functions for mv64460_eth + * + **********************************************************************/ +int db64460_eth_probe (struct eth_device *dev) +{ + return ((int) db64460_eth_start (dev)); +} + +int db64460_eth_poll (struct eth_device *dev) +{ + return mv64460_eth_receive (dev); +} + +int db64460_eth_transmit (struct eth_device *dev, volatile void *packet, + int length) +{ + mv64460_eth_xmit (dev, packet, length); + return 0; +} + +void db64460_eth_disable (struct eth_device *dev) +{ + mv64460_eth_stop (dev); +} + + +#define DFCDL(write,read) ((write << 6) | read) +unsigned int ethDfcdls[] = { DFCDL(0,0), + DFCDL(1,1), + DFCDL(2,2), + DFCDL(3,3), + DFCDL(4,4), + DFCDL(5,5), + DFCDL(6,6), + DFCDL(7,7), + DFCDL(8,8), + DFCDL(9,9), + DFCDL(10,10), + DFCDL(11,11), + DFCDL(12,12), + DFCDL(13,13), + DFCDL(14,14), + DFCDL(15,15), + DFCDL(16,16), + DFCDL(17,17), + DFCDL(18,18), + DFCDL(19,19), + DFCDL(20,20), + DFCDL(21,21), + DFCDL(22,22), + DFCDL(23,23), + DFCDL(24,24), + DFCDL(25,25), + DFCDL(26,26), + DFCDL(27,27), + DFCDL(28,28), + DFCDL(29,29), + DFCDL(30,30), + DFCDL(31,31), + DFCDL(32,32), + DFCDL(33,33), + DFCDL(34,34), + DFCDL(35,35), + DFCDL(36,36), + DFCDL(37,37), + DFCDL(38,38), + DFCDL(39,39), + DFCDL(40,40), + DFCDL(41,41), + DFCDL(42,42), + DFCDL(43,43), + DFCDL(44,44), + DFCDL(45,45), + DFCDL(46,46), + DFCDL(47,47), + DFCDL(48,48), + DFCDL(49,49), + DFCDL(50,50), + DFCDL(51,51), + DFCDL(52,52), + DFCDL(53,53), + DFCDL(54,54), + DFCDL(55,55), + DFCDL(56,56), + DFCDL(57,57), + DFCDL(58,58), + DFCDL(59,59), + DFCDL(60,60), + DFCDL(61,61), + DFCDL(62,62), + DFCDL(63,63) }; + +void mv_eth_phy_init(void) +{ + int i; + + MV_REG_WRITE(ETH_PHY_DFCDL_ADDR_REG, 0); + + for (i = 0 ; i < 64; i++) { + MV_REG_WRITE(ETH_PHY_DFCDL_DATA0_REG, ethDfcdls[i]); + } + + MV_REG_WRITE(ETH_PHY_DFCDL_CONFIG0_REG,0x300000); +} + +void mv6446x_eth_initialize (bd_t * bis) +{ + struct eth_device *dev; + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + int devnum, x, temp; + char *s, *e, buf[64]; + +/* P3M750 only + * Set RGMII clock drives strength + */ + temp = MV_REG_READ(0x20A0); + temp |= 0x04000080; + MV_REG_WRITE(0x20A0, temp); + + mv_eth_phy_init(); + + for (devnum = 0; devnum < MV_ETH_DEVS; devnum++) { + dev = calloc (sizeof (*dev), 1); + if (!dev) { + printf ("%s: mv_enet%d allocation failure, %s\n", + __FUNCTION__, devnum, "eth_device structure"); + return; + } + + /* must be less than NAMESIZE (16) */ + sprintf (dev->name, "mv_enet%d", devnum); + +#ifdef DEBUG + printf ("Initializing %s\n", dev->name); +#endif + + /* Extract the MAC address from the environment */ + switch (devnum) { + case 0: + s = "ethaddr"; + break; + + case 1: + s = "eth1addr"; + break; + + case 2: + s = "eth2addr"; + break; + + default: /* this should never happen */ + printf ("%s: Invalid device number %d\n", + __FUNCTION__, devnum); + return; + } + + temp = getenv_r (s, buf, sizeof (buf)); + s = (temp > 0) ? buf : NULL; + +#ifdef DEBUG + printf ("Setting MAC %d to %s\n", devnum, s); +#endif + for (x = 0; x < 6; ++x) { + dev->enetaddr[x] = s ? simple_strtoul (s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + /* ronen - set the MAC addr in the HW */ + eth_port_uc_addr_set (devnum, dev->enetaddr, 0); + + dev->init = (void *) db64460_eth_probe; + dev->halt = (void *) ethernet_phy_reset; + dev->send = (void *) db64460_eth_transmit; + dev->recv = (void *) db64460_eth_poll; + + ethernet_private = calloc (sizeof (*ethernet_private), 1); + dev->priv = (void *)ethernet_private; + if (!ethernet_private) { + printf ("%s: %s allocation failure, %s\n", + __FUNCTION__, dev->name, + "Private Device Structure"); + free (dev); + return; + } + /* start with an zeroed ETH_PORT_INFO */ + memset (ethernet_private, 0, sizeof (ETH_PORT_INFO)); + memcpy (ethernet_private->port_mac_addr, dev->enetaddr, 6); + + /* set pointer to memory for stats data structure etc... */ + port_private = calloc (sizeof (*ethernet_private), 1); + ethernet_private->port_private = (void *)port_private; + if (!port_private) { + printf ("%s: %s allocation failure, %s\n", + __FUNCTION__, dev->name, + "Port Private Device Structure"); + + free (ethernet_private); + free (dev); + return; + } + + port_private->stats = + calloc (sizeof (struct net_device_stats), 1); + if (!port_private->stats) { + printf ("%s: %s allocation failure, %s\n", + __FUNCTION__, dev->name, + "Net stat Structure"); + + free (port_private); + free (ethernet_private); + free (dev); + return; + } + memset (ethernet_private->port_private, 0, + sizeof (struct mv64460_eth_priv)); + switch (devnum) { + case 0: + ethernet_private->port_num = ETH_0; + break; + case 1: + ethernet_private->port_num = ETH_1; + break; + case 2: + ethernet_private->port_num = ETH_2; + break; + default: + printf ("Invalid device number %d\n", devnum); + break; + }; + + port_private->port_num = devnum; + /* + * Read MIB counter on the GT in order to reset them, + * then zero all the stats fields in memory + */ + mv64460_eth_update_stat (dev); + memset (port_private->stats, 0, + sizeof (struct net_device_stats)); + /* Extract the MAC address from the environment */ + switch (devnum) { + case 0: + s = "ethaddr"; + break; + + case 1: + s = "eth1addr"; + break; + + case 2: + s = "eth2addr"; + break; + + default: /* this should never happen */ + printf ("%s: Invalid device number %d\n", + __FUNCTION__, devnum); + return; + } + + temp = getenv_r (s, buf, sizeof (buf)); + s = (temp > 0) ? buf : NULL; + +#ifdef DEBUG + printf ("Setting MAC %d to %s\n", devnum, s); +#endif + for (x = 0; x < 6; ++x) { + dev->enetaddr[x] = s ? simple_strtoul (s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + + DP (printf ("Allocating descriptor and buffer rings\n")); + + ethernet_private->p_rx_desc_area_base[0] = + (ETH_RX_DESC *) memalign (16, + RX_DESC_ALIGNED_SIZE * + MV64460_RX_QUEUE_SIZE + 1); + ethernet_private->p_tx_desc_area_base[0] = + (ETH_TX_DESC *) memalign (16, + TX_DESC_ALIGNED_SIZE * + MV64460_TX_QUEUE_SIZE + 1); + + ethernet_private->p_rx_buffer_base[0] = + (char *) memalign (16, + MV64460_RX_QUEUE_SIZE * + MV64460_TX_BUFFER_SIZE + 1); + ethernet_private->p_tx_buffer_base[0] = + (char *) memalign (16, + MV64460_RX_QUEUE_SIZE * + MV64460_TX_BUFFER_SIZE + 1); + +#ifdef DEBUG_MV_ETH + /* DEBUG OUTPUT prints adresses of globals */ + print_globals (dev); +#endif + eth_register (dev); + + miiphy_register(dev->name, mv_miiphy_read, mv_miiphy_write); + } + DP (printf ("%s: exit\n", __FUNCTION__)); + +} + +/********************************************************************** + * mv64460_eth_open + * + * This function is called when openning the network device. The function + * should initialize all the hardware, initialize cyclic Rx/Tx + * descriptors chain and buffers and allocate an IRQ to the network + * device. + * + * Input : a pointer to the network device structure + * / / ronen - changed the output to match net/eth.c needs + * Output : nonzero of success , zero if fails. + * under construction + **********************************************************************/ + +int mv64460_eth_open (struct eth_device *dev) +{ + return (mv64460_eth_real_open (dev)); +} + +/* Helper function for mv64460_eth_open */ +static int mv64460_eth_real_open (struct eth_device *dev) +{ + + unsigned int queue; + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + u32 port_status; + ushort reg_short; + int speed; + int duplex; + int i; + int reg; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + /* ronen - when we update the MAC env params we only update dev->enetaddr + see ./net/eth.c eth_set_enetaddr() */ + memcpy (ethernet_private->port_mac_addr, dev->enetaddr, 6); + + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Stop RX Queues */ + MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num), + 0x0000ff00); + + /* Clear the ethernet port interrupts */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_REG (port_num), 0); + MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_EXTEND_REG (port_num), 0); + + /* Unmask RX buffer and TX end interrupt */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_MASK_REG (port_num), + INT_CAUSE_UNMASK_ALL); + + /* Unmask phy and link status changes interrupts */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_EXTEND_MASK_REG (port_num), + INT_CAUSE_UNMASK_ALL_EXT); + + /* Set phy address of the port */ + ethernet_private->port_phy_addr = 0x1 + (port_num << 1); + reg = ethernet_private->port_phy_addr; + + /* Activate the DMA channels etc */ + eth_port_init (ethernet_private); + + /* "Allocate" setup TX rings */ + + for (queue = 0; queue < MV64460_TX_QUEUE_NUM; queue++) { + unsigned int size; + + port_private->tx_ring_size[queue] = MV64460_TX_QUEUE_SIZE; + size = (port_private->tx_ring_size[queue] * TX_DESC_ALIGNED_SIZE); /*size = no of DESCs times DESC-size */ + ethernet_private->tx_desc_area_size[queue] = size; + + /* first clear desc area completely */ + memset ((void *) ethernet_private->p_tx_desc_area_base[queue], + 0, ethernet_private->tx_desc_area_size[queue]); + + /* initialize tx desc ring with low level driver */ + if (ether_init_tx_desc_ring + (ethernet_private, ETH_Q0, + port_private->tx_ring_size[queue], + MV64460_TX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ , + (unsigned int) ethernet_private-> + p_tx_desc_area_base[queue], + (unsigned int) ethernet_private-> + p_tx_buffer_base[queue]) == false) + printf ("### Error initializing TX Ring\n"); + } + + /* "Allocate" setup RX rings */ + for (queue = 0; queue < MV64460_RX_QUEUE_NUM; queue++) { + unsigned int size; + + /* Meantime RX Ring are fixed - but must be configurable by user */ + port_private->rx_ring_size[queue] = MV64460_RX_QUEUE_SIZE; + size = (port_private->rx_ring_size[queue] * + RX_DESC_ALIGNED_SIZE); + ethernet_private->rx_desc_area_size[queue] = size; + + /* first clear desc area completely */ + memset ((void *) ethernet_private->p_rx_desc_area_base[queue], + 0, ethernet_private->rx_desc_area_size[queue]); + if ((ether_init_rx_desc_ring + (ethernet_private, ETH_Q0, + port_private->rx_ring_size[queue], + MV64460_RX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ , + (unsigned int) ethernet_private-> + p_rx_desc_area_base[queue], + (unsigned int) ethernet_private-> + p_rx_buffer_base[queue])) == false) + printf ("### Error initializing RX Ring\n"); + } + + eth_port_start (ethernet_private); + + /* Set maximum receive buffer to 9700 bytes */ + MV_REG_WRITE (MV64460_ETH_PORT_SERIAL_CONTROL_REG (port_num), + (0x5 << 17) | + (MV_REG_READ + (MV64460_ETH_PORT_SERIAL_CONTROL_REG (port_num)) + & 0xfff1ffff)); + + /* + * Set ethernet MTU for leaky bucket mechanism to 0 - this will + * disable the leaky bucket mechanism . + */ + + MV_REG_WRITE (MV64460_ETH_MAXIMUM_TRANSMIT_UNIT (port_num), 0); + port_status = MV_REG_READ (MV64460_ETH_PORT_STATUS_REG (port_num)); + +#if defined(CONFIG_PHY_RESET) + /* + * Reset the phy, only if its the first time through + * otherwise, just check the speeds & feeds + */ + if (port_private->first_init == 0) { + port_private->first_init = 1; + ethernet_phy_reset (port_num); + + /* Start/Restart autonegotiation */ + phy_setup_aneg (dev->name, reg); + udelay (1000); + } +#endif /* defined(CONFIG_PHY_RESET) */ + + miiphy_read (dev->name, reg, PHY_BMSR, ®_short); + + /* + * Wait if PHY is capable of autonegotiation and autonegotiation is not complete + */ + if ((reg_short & PHY_BMSR_AUTN_ABLE) + && !(reg_short & PHY_BMSR_AUTN_COMP)) { + puts ("Waiting for PHY auto negotiation to complete"); + i = 0; + while (!(reg_short & PHY_BMSR_AUTN_COMP)) { + /* + * Timeout reached ? + */ + if (i > PHY_AUTONEGOTIATE_TIMEOUT) { + puts (" TIMEOUT !\n"); + break; + } + + if ((i++ % 1000) == 0) { + putc ('.'); + } + udelay (1000); /* 1 ms */ + miiphy_read (dev->name, reg, PHY_BMSR, ®_short); + + } + puts (" done\n"); + udelay (500000); /* another 500 ms (results in faster booting) */ + } + + speed = miiphy_speed (dev->name, reg); + duplex = miiphy_duplex (dev->name, reg); + + printf ("ENET Speed is %d Mbps - %s duplex connection\n", + (int) speed, (duplex == HALF) ? "HALF" : "FULL"); + + port_private->eth_running = MAGIC_ETH_RUNNING; + return 1; +} + + +static int mv64460_eth_free_tx_rings (struct eth_device *dev) +{ + unsigned int queue; + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + volatile ETH_TX_DESC *p_tx_curr_desc; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Stop Tx Queues */ + MV_REG_WRITE (MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG (port_num), + 0x0000ff00); + + /* Free TX rings */ + DP (printf ("Clearing previously allocated TX queues... ")); + for (queue = 0; queue < MV64460_TX_QUEUE_NUM; queue++) { + /* Free on TX rings */ + for (p_tx_curr_desc = + ethernet_private->p_tx_desc_area_base[queue]; + ((unsigned int) p_tx_curr_desc <= (unsigned int) + ethernet_private->p_tx_desc_area_base[queue] + + ethernet_private->tx_desc_area_size[queue]); + p_tx_curr_desc = + (ETH_TX_DESC *) ((unsigned int) p_tx_curr_desc + + TX_DESC_ALIGNED_SIZE)) { + /* this is inside for loop */ + if (p_tx_curr_desc->return_info != 0) { + p_tx_curr_desc->return_info = 0; + DP (printf ("freed\n")); + } + } + DP (printf ("Done\n")); + } + return 0; +} + +static int mv64460_eth_free_rx_rings (struct eth_device *dev) +{ + unsigned int queue; + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + volatile ETH_RX_DESC *p_rx_curr_desc; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + + /* Stop RX Queues */ + MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num), + 0x0000ff00); + + /* Free RX rings */ + DP (printf ("Clearing previously allocated RX queues... ")); + for (queue = 0; queue < MV64460_RX_QUEUE_NUM; queue++) { + /* Free preallocated skb's on RX rings */ + for (p_rx_curr_desc = + ethernet_private->p_rx_desc_area_base[queue]; + (((unsigned int) p_rx_curr_desc < + ((unsigned int) ethernet_private-> + p_rx_desc_area_base[queue] + + ethernet_private->rx_desc_area_size[queue]))); + p_rx_curr_desc = + (ETH_RX_DESC *) ((unsigned int) p_rx_curr_desc + + RX_DESC_ALIGNED_SIZE)) { + if (p_rx_curr_desc->return_info != 0) { + p_rx_curr_desc->return_info = 0; + DP (printf ("freed\n")); + } + } + DP (printf ("Done\n")); + } + return 0; +} + +/********************************************************************** + * mv64460_eth_stop + * + * This function is used when closing the network device. + * It updates the hardware, + * release all memory that holds buffers and descriptors and release the IRQ. + * Input : a pointer to the device structure + * Output : zero if success , nonzero if fails + *********************************************************************/ + +int mv64460_eth_stop (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Disable all gigE address decoder */ + MV_REG_WRITE (MV64460_ETH_BASE_ADDR_ENABLE_REG, 0x3f); + DP (printf ("%s Ethernet stop called ... \n", __FUNCTION__)); + mv64460_eth_real_stop (dev); + + return 0; +}; + +/* Helper function for mv64460_eth_stop */ + +static int mv64460_eth_real_stop (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + mv64460_eth_free_tx_rings (dev); + mv64460_eth_free_rx_rings (dev); + + eth_port_reset (ethernet_private->port_num); + /* Disable ethernet port interrupts */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_REG (port_num), 0); + MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_EXTEND_REG (port_num), 0); + /* Mask RX buffer and TX end interrupt */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_MASK_REG (port_num), 0); + /* Mask phy and link status changes interrupts */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_EXTEND_MASK_REG (port_num), 0); + MV_RESET_REG_BITS (MV64460_CPU_INTERRUPT0_MASK_HIGH, + BIT0 << port_num); + /* Print Network statistics */ +#ifndef UPDATE_STATS_BY_SOFTWARE + /* + * Print statistics (only if ethernet is running), + * then zero all the stats fields in memory + */ + if (port_private->eth_running == MAGIC_ETH_RUNNING) { + port_private->eth_running = 0; + mv64460_eth_print_stat (dev); + } + memset (port_private->stats, 0, sizeof (struct net_device_stats)); +#endif + DP (printf ("\nEthernet stopped ... \n")); + return 0; +} + + +/********************************************************************** + * mv64460_eth_start_xmit + * + * This function is queues a packet in the Tx descriptor for + * required port. + * + * Input : skb - a pointer to socket buffer + * dev - a pointer to the required port + * + * Output : zero upon success + **********************************************************************/ + +int mv64460_eth_xmit (struct eth_device *dev, volatile void *dataPtr, + int dataSize) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + PKT_INFO pkt_info; + ETH_FUNC_RET_STATUS status; + struct net_device_stats *stats; + ETH_FUNC_RET_STATUS release_result; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + stats = port_private->stats; + + /* Update packet info data structure */ + pkt_info.cmd_sts = ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC; /* DMA owned, first last */ + pkt_info.byte_cnt = dataSize; + pkt_info.buf_ptr = (unsigned int) dataPtr; + pkt_info.return_info = 0; + + status = eth_port_send (ethernet_private, ETH_Q0, &pkt_info); + if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) { + printf ("Error on transmitting packet .."); + if (status == ETH_QUEUE_FULL) + printf ("ETH Queue is full. \n"); + if (status == ETH_QUEUE_LAST_RESOURCE) + printf ("ETH Queue: using last available resource. \n"); + goto error; + } + + /* Update statistics and start of transmittion time */ + stats->tx_bytes += dataSize; + stats->tx_packets++; + + /* Check if packet(s) is(are) transmitted correctly (release everything) */ + do { + release_result = + eth_tx_return_desc (ethernet_private, ETH_Q0, + &pkt_info); + switch (release_result) { + case ETH_OK: + DP (printf ("descriptor released\n")); + if (pkt_info.cmd_sts & BIT0) { + printf ("Error in TX\n"); + stats->tx_errors++; + } + break; + case ETH_RETRY: + DP (printf ("transmission still in process\n")); + break; + + case ETH_ERROR: + printf ("routine can not access Tx desc ring\n"); + break; + + case ETH_END_OF_JOB: + DP (printf ("the routine has nothing to release\n")); + break; + default: /* should not happen */ + break; + } + } while (release_result == ETH_OK); + + return 0; /* success */ + + error: + return 1; /* Failed - higher layers will free the skb */ +} + +/********************************************************************** + * mv64460_eth_receive + * + * This function is forward packets that are received from the port's + * queues toward kernel core or FastRoute them to another interface. + * + * Input : dev - a pointer to the required interface + * max - maximum number to receive (0 means unlimted) + * + * Output : number of served packets + **********************************************************************/ + +int mv64460_eth_receive (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + PKT_INFO pkt_info; + struct net_device_stats *stats; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + stats = port_private->stats; + + while ((eth_port_receive (ethernet_private, ETH_Q0, &pkt_info) == ETH_OK)) { +#ifdef DEBUG_MV_ETH + if (pkt_info.byte_cnt != 0) { + printf ("%s: Received %d byte Packet @ 0x%x\n", + __FUNCTION__, pkt_info.byte_cnt, + pkt_info.buf_ptr); + if(pkt_info.buf_ptr != 0){ + for(i=0; i < pkt_info.byte_cnt; i++){ + if((i % 4) == 0){ + printf("\n0x"); + } + printf("%02x", ((char*)pkt_info.buf_ptr)[i]); + } + printf("\n"); + } + } +#endif + /* Update statistics. Note byte count includes 4 byte CRC count */ + stats->rx_packets++; + stats->rx_bytes += pkt_info.byte_cnt; + + /* + * In case received a packet without first / last bits on OR the error + * summary bit is on, the packets needs to be dropeed. + */ + if (((pkt_info. + cmd_sts & (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) != + (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) + || (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) { + stats->rx_dropped++; + + printf ("Received packet spread on multiple descriptors\n"); + + /* Is this caused by an error ? */ + if (pkt_info.cmd_sts & ETH_ERROR_SUMMARY) { + stats->rx_errors++; + } + + /* free these descriptors again without forwarding them to the higher layers */ + pkt_info.buf_ptr &= ~0x7; /* realign buffer again */ + pkt_info.byte_cnt = 0x0000; /* Reset Byte count */ + + if (eth_rx_return_buff + (ethernet_private, ETH_Q0, &pkt_info) != ETH_OK) { + printf ("Error while returning the RX Desc to Ring\n"); + } else { + DP (printf ("RX Desc returned to Ring\n")); + } + /* /free these descriptors again */ + } else { + +/* !!! call higher layer processing */ +#ifdef DEBUG_MV_ETH + printf ("\nNow send it to upper layer protocols (NetReceive) ...\n"); +#endif + /* let the upper layer handle the packet */ + NetReceive ((uchar *) pkt_info.buf_ptr, + (int) pkt_info.byte_cnt); + +/* **************************************************************** */ +/* free descriptor */ + pkt_info.buf_ptr &= ~0x7; /* realign buffer again */ + pkt_info.byte_cnt = 0x0000; /* Reset Byte count */ + DP (printf ("RX: pkt_info.buf_ptr = %x\n", pkt_info.buf_ptr)); + if (eth_rx_return_buff + (ethernet_private, ETH_Q0, &pkt_info) != ETH_OK) { + printf ("Error while returning the RX Desc to Ring\n"); + } else { + DP (printf ("RX: Desc returned to Ring\n")); + } + +/* **************************************************************** */ + + } + } + mv64460_eth_get_stats (dev); /* update statistics */ + return 1; +} + +/********************************************************************** + * mv64460_eth_get_stats + * + * Returns a pointer to the interface statistics. + * + * Input : dev - a pointer to the required interface + * + * Output : a pointer to the interface's statistics + **********************************************************************/ + +static struct net_device_stats *mv64460_eth_get_stats (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + mv64460_eth_update_stat (dev); + + return port_private->stats; +} + + +/********************************************************************** + * mv64460_eth_update_stat + * + * Update the statistics structure in the private data structure + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + **********************************************************************/ + +static void mv64460_eth_update_stat (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + struct net_device_stats *stats; + unsigned int port_num; + volatile unsigned int dummy; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + stats = port_private->stats; + + /* These are false updates */ + stats->rx_packets += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_FRAMES_RECEIVED); + stats->tx_packets += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_FRAMES_SENT); + stats->rx_bytes += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_RECEIVED_LOW); + /* + * Ideally this should be as follows - + * + * stats->rx_bytes += stats->rx_bytes + + * ((unsigned long) ethReadMibCounter (ethernet_private->port_num , + * ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH) << 32); + * + * But the unsigned long in PowerPC and MIPS are 32bit. So the next read + * is just a dummy read for proper work of the GigE port + */ + dummy = eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH); + stats->tx_bytes += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_SENT_LOW); + dummy = eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_SENT_HIGH); + stats->rx_errors += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_MAC_RECEIVE_ERROR); + + /* Rx dropped is for received packet with CRC error */ + stats->rx_dropped += + (unsigned long) eth_read_mib_counter (ethernet_private-> + port_num, + ETH_MIB_BAD_CRC_EVENT); + stats->multicast += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_MULTICAST_FRAMES_RECEIVED); + stats->collisions += + (unsigned long) eth_read_mib_counter (ethernet_private-> + port_num, + ETH_MIB_COLLISION) + + (unsigned long) eth_read_mib_counter (ethernet_private-> + port_num, + ETH_MIB_LATE_COLLISION); + /* detailed rx errors */ + stats->rx_length_errors += + (unsigned long) eth_read_mib_counter (ethernet_private-> + port_num, + ETH_MIB_UNDERSIZE_RECEIVED) + + + (unsigned long) eth_read_mib_counter (ethernet_private-> + port_num, + ETH_MIB_OVERSIZE_RECEIVED); + /* detailed tx errors */ +} + +#ifndef UPDATE_STATS_BY_SOFTWARE +/********************************************************************** + * mv64460_eth_print_stat + * + * Update the statistics structure in the private data structure + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + **********************************************************************/ + +static void mv64460_eth_print_stat (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + struct net_device_stats *stats; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + stats = port_private->stats; + + /* These are false updates */ + printf ("\n### Network statistics: ###\n"); + printf ("--------------------------\n"); + printf (" Packets received: %ld\n", stats->rx_packets); + printf (" Packets send: %ld\n", stats->tx_packets); + printf (" Received bytes: %ld\n", stats->rx_bytes); + printf (" Send bytes: %ld\n", stats->tx_bytes); + if (stats->rx_errors != 0) + printf (" Rx Errors: %ld\n", + stats->rx_errors); + if (stats->rx_dropped != 0) + printf (" Rx dropped (CRC Errors): %ld\n", + stats->rx_dropped); + if (stats->multicast != 0) + printf (" Rx mulicast frames: %ld\n", + stats->multicast); + if (stats->collisions != 0) + printf (" No. of collisions: %ld\n", + stats->collisions); + if (stats->rx_length_errors != 0) + printf (" Rx length errors: %ld\n", + stats->rx_length_errors); +} +#endif + +/************************************************************************** + *network_start - Network Kick Off Routine UBoot + *Inputs : + *Outputs : + **************************************************************************/ + +bool db64460_eth_start (struct eth_device *dev) +{ + return (mv64460_eth_open (dev)); /* calls real open */ +} + +/************************************************************************* +************************************************************************** +************************************************************************** +* The second part is the low level driver of the gigE ethernet ports. * +************************************************************************** +************************************************************************** +*************************************************************************/ +/* + * based on Linux code + * arch/ppc/galileo/EVB64460/mv64460_eth.c - Driver for MV64460X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + + * 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. + * + */ + +/******************************************************************************** + * Marvell's Gigabit Ethernet controller low level driver + * + * DESCRIPTION: + * This file introduce low level API to Marvell's Gigabit Ethernet + * controller. This Gigabit Ethernet Controller driver API controls + * 1) Operations (i.e. port init, start, reset etc'). + * 2) Data flow (i.e. port send, receive etc'). + * Each Gigabit Ethernet port is controlled via ETH_PORT_INFO + * struct. + * This struct includes user configuration information as well as + * driver internal data needed for its operations. + * + * Supported Features: + * - This low level driver is OS independent. Allocating memory for + * the descriptor rings and buffers are not within the scope of + * this driver. + * - The user is free from Rx/Tx queue managing. + * - This low level driver introduce functionality API that enable + * the to operate Marvell's Gigabit Ethernet Controller in a + * convenient way. + * - Simple Gigabit Ethernet port operation API. + * - Simple Gigabit Ethernet port data flow API. + * - Data flow and operation API support per queue functionality. + * - Support cached descriptors for better performance. + * - Enable access to all four DRAM banks and internal SRAM memory + * spaces. + * - PHY access and control API. + * - Port control register configuration API. + * - Full control over Unicast and Multicast MAC configurations. + * + * Operation flow: + * + * Initialization phase + * This phase complete the initialization of the ETH_PORT_INFO + * struct. + * User information regarding port configuration has to be set + * prior to calling the port initialization routine. For example, + * the user has to assign the port_phy_addr field which is board + * depended parameter. + * In this phase any port Tx/Rx activity is halted, MIB counters + * are cleared, PHY address is set according to user parameter and + * access to DRAM and internal SRAM memory spaces. + * + * Driver ring initialization + * Allocating memory for the descriptor rings and buffers is not + * within the scope of this driver. Thus, the user is required to + * allocate memory for the descriptors ring and buffers. Those + * memory parameters are used by the Rx and Tx ring initialization + * routines in order to curve the descriptor linked list in a form + * of a ring. + * Note: Pay special attention to alignment issues when using + * cached descriptors/buffers. In this phase the driver store + * information in the ETH_PORT_INFO struct regarding each queue + * ring. + * + * Driver start + * This phase prepares the Ethernet port for Rx and Tx activity. + * It uses the information stored in the ETH_PORT_INFO struct to + * initialize the various port registers. + * + * Data flow: + * All packet references to/from the driver are done using PKT_INFO + * struct. + * This struct is a unified struct used with Rx and Tx operations. + * This way the user is not required to be familiar with neither + * Tx nor Rx descriptors structures. + * The driver's descriptors rings are management by indexes. + * Those indexes controls the ring resources and used to indicate + * a SW resource error: + * 'current' + * This index points to the current available resource for use. For + * example in Rx process this index will point to the descriptor + * that will be passed to the user upon calling the receive routine. + * In Tx process, this index will point to the descriptor + * that will be assigned with the user packet info and transmitted. + * 'used' + * This index points to the descriptor that need to restore its + * resources. For example in Rx process, using the Rx buffer return + * API will attach the buffer returned in packet info to the + * descriptor pointed by 'used'. In Tx process, using the Tx + * descriptor return will merely return the user packet info with + * the command status of the transmitted buffer pointed by the + * 'used' index. Nevertheless, it is essential to use this routine + * to update the 'used' index. + * 'first' + * This index supports Tx Scatter-Gather. It points to the first + * descriptor of a packet assembled of multiple buffers. For example + * when in middle of Such packet we have a Tx resource error the + * 'curr' index get the value of 'first' to indicate that the ring + * returned to its state before trying to transmit this packet. + * + * Receive operation: + * The eth_port_receive API set the packet information struct, + * passed by the caller, with received information from the + * 'current' SDMA descriptor. + * It is the user responsibility to return this resource back + * to the Rx descriptor ring to enable the reuse of this source. + * Return Rx resource is done using the eth_rx_return_buff API. + * + * Transmit operation: + * The eth_port_send API supports Scatter-Gather which enables to + * send a packet spanned over multiple buffers. This means that + * for each packet info structure given by the user and put into + * the Tx descriptors ring, will be transmitted only if the 'LAST' + * bit will be set in the packet info command status field. This + * API also consider restriction regarding buffer alignments and + * sizes. + * The user must return a Tx resource after ensuring the buffer + * has been transmitted to enable the Tx ring indexes to update. + * + * BOARD LAYOUT + * This device is on-board. No jumper diagram is necessary. + * + * EXTERNAL INTERFACE + * + * Prior to calling the initialization routine eth_port_init() the user + * must set the following fields under ETH_PORT_INFO struct: + * port_num User Ethernet port number. + * port_phy_addr User PHY address of Ethernet port. + * port_mac_addr[6] User defined port MAC address. + * port_config User port configuration value. + * port_config_extend User port config extend value. + * port_sdma_config User port SDMA config value. + * port_serial_control User port serial control value. + * *port_virt_to_phys () User function to cast virtual addr to CPU bus addr. + * *port_private User scratch pad for user specific data structures. + * + * This driver introduce a set of default values: + * PORT_CONFIG_VALUE Default port configuration value + * PORT_CONFIG_EXTEND_VALUE Default port extend configuration value + * PORT_SDMA_CONFIG_VALUE Default sdma control value + * PORT_SERIAL_CONTROL_VALUE Default port serial control value + * + * This driver data flow is done using the PKT_INFO struct which is + * a unified struct for Rx and Tx operations: + * byte_cnt Tx/Rx descriptor buffer byte count. + * l4i_chk CPU provided TCP Checksum. For Tx operation only. + * cmd_sts Tx/Rx descriptor command status. + * buf_ptr Tx/Rx descriptor buffer pointer. + * return_info Tx/Rx user resource return information. + * + * + * EXTERNAL SUPPORT REQUIREMENTS + * + * This driver requires the following external support: + * + * D_CACHE_FLUSH_LINE (address, address offset) + * + * This macro applies assembly code to flush and invalidate cache + * line. + * address - address base. + * address offset - address offset + * + * + * CPU_PIPE_FLUSH + * + * This macro applies assembly code to flush the CPU pipeline. + * + *******************************************************************************/ +/* includes */ + +/* defines */ +/* SDMA command macros */ +#define ETH_ENABLE_TX_QUEUE(tx_queue, eth_port) \ + MV_REG_WRITE(MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), (1 << tx_queue)) + +#define ETH_DISABLE_TX_QUEUE(tx_queue, eth_port) \ + MV_REG_WRITE(MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port),\ + (1 << (8 + tx_queue))) + +#define ETH_ENABLE_RX_QUEUE(rx_queue, eth_port) \ +MV_REG_WRITE(MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port), (1 << rx_queue)) + +#define ETH_DISABLE_RX_QUEUE(rx_queue, eth_port) \ +MV_REG_WRITE(MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port), (1 << (8 + rx_queue))) + +#define CURR_RFD_GET(p_curr_desc, queue) \ + ((p_curr_desc) = p_eth_port_ctrl->p_rx_curr_desc_q[queue]) + +#define CURR_RFD_SET(p_curr_desc, queue) \ + (p_eth_port_ctrl->p_rx_curr_desc_q[queue] = (p_curr_desc)) + +#define USED_RFD_GET(p_used_desc, queue) \ + ((p_used_desc) = p_eth_port_ctrl->p_rx_used_desc_q[queue]) + +#define USED_RFD_SET(p_used_desc, queue)\ +(p_eth_port_ctrl->p_rx_used_desc_q[queue] = (p_used_desc)) + + +#define CURR_TFD_GET(p_curr_desc, queue) \ + ((p_curr_desc) = p_eth_port_ctrl->p_tx_curr_desc_q[queue]) + +#define CURR_TFD_SET(p_curr_desc, queue) \ + (p_eth_port_ctrl->p_tx_curr_desc_q[queue] = (p_curr_desc)) + +#define USED_TFD_GET(p_used_desc, queue) \ + ((p_used_desc) = p_eth_port_ctrl->p_tx_used_desc_q[queue]) + +#define USED_TFD_SET(p_used_desc, queue) \ + (p_eth_port_ctrl->p_tx_used_desc_q[queue] = (p_used_desc)) + +#define FIRST_TFD_GET(p_first_desc, queue) \ + ((p_first_desc) = p_eth_port_ctrl->p_tx_first_desc_q[queue]) + +#define FIRST_TFD_SET(p_first_desc, queue) \ + (p_eth_port_ctrl->p_tx_first_desc_q[queue] = (p_first_desc)) + + +/* Macros that save access to desc in order to find next desc pointer */ +#define RX_NEXT_DESC_PTR(p_rx_desc, queue) (ETH_RX_DESC*)(((((unsigned int)p_rx_desc - (unsigned int)p_eth_port_ctrl->p_rx_desc_area_base[queue]) + RX_DESC_ALIGNED_SIZE) % p_eth_port_ctrl->rx_desc_area_size[queue]) + (unsigned int)p_eth_port_ctrl->p_rx_desc_area_base[queue]) + +#define TX_NEXT_DESC_PTR(p_tx_desc, queue) (ETH_TX_DESC*)(((((unsigned int)p_tx_desc - (unsigned int)p_eth_port_ctrl->p_tx_desc_area_base[queue]) + TX_DESC_ALIGNED_SIZE) % p_eth_port_ctrl->tx_desc_area_size[queue]) + (unsigned int)p_eth_port_ctrl->p_tx_desc_area_base[queue]) + +#define LINK_UP_TIMEOUT 100000 +#define PHY_BUSY_TIMEOUT 10000000 + +/* locals */ + +/* PHY routines */ +static void ethernet_phy_set (ETH_PORT eth_port_num, int phy_addr); +static int ethernet_phy_get (ETH_PORT eth_port_num); + +/* Ethernet Port routines */ +static void eth_set_access_control (ETH_PORT eth_port_num, + ETH_WIN_PARAM * param); +static bool eth_port_uc_addr (ETH_PORT eth_port_num, unsigned char uc_nibble, + ETH_QUEUE queue, int option); +#if 0 /* FIXME */ +static bool eth_port_smc_addr (ETH_PORT eth_port_num, + unsigned char mc_byte, + ETH_QUEUE queue, int option); +static bool eth_port_omc_addr (ETH_PORT eth_port_num, + unsigned char crc8, + ETH_QUEUE queue, int option); +#endif + +static void eth_b_copy (unsigned int src_addr, unsigned int dst_addr, + int byte_count); + +void eth_dbg (ETH_PORT_INFO * p_eth_port_ctrl); + + +typedef enum _memory_bank { BANK0, BANK1, BANK2, BANK3 } MEMORY_BANK; +u32 mv_get_dram_bank_base_addr (MEMORY_BANK bank) +{ + u32 result = 0; + u32 enable = MV_REG_READ (MV64460_BASE_ADDR_ENABLE); + + if (enable & (1 << bank)) + return 0; + if (bank == BANK0) + result = MV_REG_READ (MV64460_CS_0_BASE_ADDR); + if (bank == BANK1) + result = MV_REG_READ (MV64460_CS_1_BASE_ADDR); + if (bank == BANK2) + result = MV_REG_READ (MV64460_CS_2_BASE_ADDR); + if (bank == BANK3) + result = MV_REG_READ (MV64460_CS_3_BASE_ADDR); + result &= 0x0000ffff; + result = result << 16; + return result; +} + +u32 mv_get_dram_bank_size (MEMORY_BANK bank) +{ + u32 result = 0; + u32 enable = MV_REG_READ (MV64460_BASE_ADDR_ENABLE); + + if (enable & (1 << bank)) + return 0; + if (bank == BANK0) + result = MV_REG_READ (MV64460_CS_0_SIZE); + if (bank == BANK1) + result = MV_REG_READ (MV64460_CS_1_SIZE); + if (bank == BANK2) + result = MV_REG_READ (MV64460_CS_2_SIZE); + if (bank == BANK3) + result = MV_REG_READ (MV64460_CS_3_SIZE); + result += 1; + result &= 0x0000ffff; + result = result << 16; + return result; +} + +u32 mv_get_internal_sram_base (void) +{ + u32 result; + + result = MV_REG_READ (MV64460_INTEGRATED_SRAM_BASE_ADDR); + result &= 0x0000ffff; + result = result << 16; + return result; +} + +/******************************************************************************* +* eth_port_init - Initialize the Ethernet port driver +* +* DESCRIPTION: +* This function prepares the ethernet port to start its activity: +* 1) Completes the ethernet port driver struct initialization toward port +* start routine. +* 2) Resets the device to a quiescent state in case of warm reboot. +* 3) Enable SDMA access to all four DRAM banks as well as internal SRAM. +* 4) Clean MAC tables. The reset status of those tables is unknown. +* 5) Set PHY address. +* Note: Call this routine prior to eth_port_start routine and after setting +* user values in the user fields of Ethernet port control struct (i.e. +* port_phy_addr). +* +* INPUT: +* ETH_PORT_INFO *p_eth_port_ctrl Ethernet port control struct +* +* OUTPUT: +* See description. +* +* RETURN: +* None. +* +*******************************************************************************/ +static void eth_port_init (ETH_PORT_INFO * p_eth_port_ctrl) +{ + int queue; + ETH_WIN_PARAM win_param; + + p_eth_port_ctrl->port_config = PORT_CONFIG_VALUE; + p_eth_port_ctrl->port_config_extend = PORT_CONFIG_EXTEND_VALUE; + p_eth_port_ctrl->port_sdma_config = PORT_SDMA_CONFIG_VALUE; + p_eth_port_ctrl->port_serial_control = PORT_SERIAL_CONTROL_VALUE; + + p_eth_port_ctrl->port_rx_queue_command = 0; + p_eth_port_ctrl->port_tx_queue_command = 0; + + /* Zero out SW structs */ + for (queue = 0; queue < MAX_RX_QUEUE_NUM; queue++) { + CURR_RFD_SET ((ETH_RX_DESC *) 0x00000000, queue); + USED_RFD_SET ((ETH_RX_DESC *) 0x00000000, queue); + p_eth_port_ctrl->rx_resource_err[queue] = false; + } + + for (queue = 0; queue < MAX_TX_QUEUE_NUM; queue++) { + CURR_TFD_SET ((ETH_TX_DESC *) 0x00000000, queue); + USED_TFD_SET ((ETH_TX_DESC *) 0x00000000, queue); + FIRST_TFD_SET ((ETH_TX_DESC *) 0x00000000, queue); + p_eth_port_ctrl->tx_resource_err[queue] = false; + } + + eth_port_reset (p_eth_port_ctrl->port_num); + + /* Set access parameters for DRAM bank 0 */ + win_param.win = ETH_WIN0; /* Use Ethernet window 0 */ + win_param.target = ETH_TARGET_DRAM; /* Window target - DDR */ + win_param.attributes = EBAR_ATTR_DRAM_CS0; /* Enable DRAM bank */ +#ifndef CONFIG_NOT_COHERENT_CACHE + win_param.attributes |= EBAR_ATTR_DRAM_CACHE_COHERENCY_WB; +#endif + win_param.high_addr = 0; + /* Get bank base */ + win_param.base_addr = mv_get_dram_bank_base_addr (BANK0); + win_param.size = mv_get_dram_bank_size (BANK0); /* Get bank size */ + if (win_param.size == 0) + win_param.enable = 0; + else + win_param.enable = 1; /* Enable the access */ + win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */ + + /* Set the access control for address window (EPAPR) READ & WRITE */ + eth_set_access_control (p_eth_port_ctrl->port_num, &win_param); + + /* Set access parameters for DRAM bank 1 */ + win_param.win = ETH_WIN1; /* Use Ethernet window 1 */ + win_param.target = ETH_TARGET_DRAM; /* Window target - DDR */ + win_param.attributes = EBAR_ATTR_DRAM_CS1; /* Enable DRAM bank */ +#ifndef CONFIG_NOT_COHERENT_CACHE + win_param.attributes |= EBAR_ATTR_DRAM_CACHE_COHERENCY_WB; +#endif + win_param.high_addr = 0; + /* Get bank base */ + win_param.base_addr = mv_get_dram_bank_base_addr (BANK1); + win_param.size = mv_get_dram_bank_size (BANK1); /* Get bank size */ + if (win_param.size == 0) + win_param.enable = 0; + else + win_param.enable = 1; /* Enable the access */ + win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */ + + /* Set the access control for address window (EPAPR) READ & WRITE */ + eth_set_access_control (p_eth_port_ctrl->port_num, &win_param); + + /* Set access parameters for DRAM bank 2 */ + win_param.win = ETH_WIN2; /* Use Ethernet window 2 */ + win_param.target = ETH_TARGET_DRAM; /* Window target - DDR */ + win_param.attributes = EBAR_ATTR_DRAM_CS2; /* Enable DRAM bank */ +#ifndef CONFIG_NOT_COHERENT_CACHE + win_param.attributes |= EBAR_ATTR_DRAM_CACHE_COHERENCY_WB; +#endif + win_param.high_addr = 0; + /* Get bank base */ + win_param.base_addr = mv_get_dram_bank_base_addr (BANK2); + win_param.size = mv_get_dram_bank_size (BANK2); /* Get bank size */ + if (win_param.size == 0) + win_param.enable = 0; + else + win_param.enable = 1; /* Enable the access */ + win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */ + + /* Set the access control for address window (EPAPR) READ & WRITE */ + eth_set_access_control (p_eth_port_ctrl->port_num, &win_param); + + /* Set access parameters for DRAM bank 3 */ + win_param.win = ETH_WIN3; /* Use Ethernet window 3 */ + win_param.target = ETH_TARGET_DRAM; /* Window target - DDR */ + win_param.attributes = EBAR_ATTR_DRAM_CS3; /* Enable DRAM bank */ +#ifndef CONFIG_NOT_COHERENT_CACHE + win_param.attributes |= EBAR_ATTR_DRAM_CACHE_COHERENCY_WB; +#endif + win_param.high_addr = 0; + /* Get bank base */ + win_param.base_addr = mv_get_dram_bank_base_addr (BANK3); + win_param.size = mv_get_dram_bank_size (BANK3); /* Get bank size */ + if (win_param.size == 0) + win_param.enable = 0; + else + win_param.enable = 1; /* Enable the access */ + win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */ + + /* Set the access control for address window (EPAPR) READ & WRITE */ + eth_set_access_control (p_eth_port_ctrl->port_num, &win_param); + + /* Set access parameters for Internal SRAM */ + win_param.win = ETH_WIN4; /* Use Ethernet window 0 */ + win_param.target = EBAR_TARGET_CBS; /* Target - Internal SRAM */ + win_param.attributes = EBAR_ATTR_CBS_SRAM | EBAR_ATTR_CBS_SRAM_BLOCK0; + win_param.high_addr = 0; + win_param.base_addr = mv_get_internal_sram_base (); /* Get base addr */ + win_param.size = MV64460_INTERNAL_SRAM_SIZE; /* Get bank size */ + win_param.enable = 1; /* Enable the access */ + win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */ + + /* Set the access control for address window (EPAPR) READ & WRITE */ + eth_set_access_control (p_eth_port_ctrl->port_num, &win_param); + + eth_port_init_mac_tables (p_eth_port_ctrl->port_num); + + ethernet_phy_set (p_eth_port_ctrl->port_num, + p_eth_port_ctrl->port_phy_addr); + + return; + +} + +/******************************************************************************* +* eth_port_start - Start the Ethernet port activity. +* +* DESCRIPTION: +* This routine prepares the Ethernet port for Rx and Tx activity: +* 1. Initialize Tx and Rx Current Descriptor Pointer for each queue that +* has been initialized a descriptor's ring (using ether_init_tx_desc_ring +* for Tx and ether_init_rx_desc_ring for Rx) +* 2. Initialize and enable the Ethernet configuration port by writing to +* the port's configuration and command registers. +* 3. Initialize and enable the SDMA by writing to the SDMA's +* configuration and command registers. +* After completing these steps, the ethernet port SDMA can starts to +* perform Rx and Tx activities. +* +* Note: Each Rx and Tx queue descriptor's list must be initialized prior +* to calling this function (use ether_init_tx_desc_ring for Tx queues and +* ether_init_rx_desc_ring for Rx queues). +* +* INPUT: +* ETH_PORT_INFO *p_eth_port_ctrl Ethernet port control struct +* +* OUTPUT: +* Ethernet port is ready to receive and transmit. +* +* RETURN: +* false if the port PHY is not up. +* true otherwise. +* +*******************************************************************************/ +static bool eth_port_start (ETH_PORT_INFO * p_eth_port_ctrl) +{ + int queue; + volatile ETH_TX_DESC *p_tx_curr_desc; + volatile ETH_RX_DESC *p_rx_curr_desc; + unsigned int phy_reg_data; + ETH_PORT eth_port_num = p_eth_port_ctrl->port_num; + + + /* Assignment of Tx CTRP of given queue */ + for (queue = 0; queue < MAX_TX_QUEUE_NUM; queue++) { + CURR_TFD_GET (p_tx_curr_desc, queue); + MV_REG_WRITE ((MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_0 + (eth_port_num) + + (4 * queue)), + ((unsigned int) p_tx_curr_desc)); + + } + + /* Assignment of Rx CRDP of given queue */ + for (queue = 0; queue < MAX_RX_QUEUE_NUM; queue++) { + CURR_RFD_GET (p_rx_curr_desc, queue); + MV_REG_WRITE ((MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_0 + (eth_port_num) + + (4 * queue)), + ((unsigned int) p_rx_curr_desc)); + + if (p_rx_curr_desc != NULL) + /* Add the assigned Ethernet address to the port's address table */ + eth_port_uc_addr_set (p_eth_port_ctrl->port_num, + p_eth_port_ctrl->port_mac_addr, + queue); + } + + /* Assign port configuration and command. */ + MV_REG_WRITE (MV64460_ETH_PORT_CONFIG_REG (eth_port_num), + p_eth_port_ctrl->port_config); + + MV_REG_WRITE (MV64460_ETH_PORT_CONFIG_EXTEND_REG (eth_port_num), + p_eth_port_ctrl->port_config_extend); + + MV_REG_WRITE (MV64460_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num), + p_eth_port_ctrl->port_serial_control); + + MV_SET_REG_BITS (MV64460_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num), + ETH_SERIAL_PORT_ENABLE); + + /* Assign port SDMA configuration */ + MV_REG_WRITE (MV64460_ETH_SDMA_CONFIG_REG (eth_port_num), + p_eth_port_ctrl->port_sdma_config); + + MV_REG_WRITE (MV64460_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT + (eth_port_num), 0x3fffffff); + MV_REG_WRITE (MV64460_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG + (eth_port_num), 0x03fffcff); + /* Turn off the port/queue bandwidth limitation */ + MV_REG_WRITE (MV64460_ETH_MAXIMUM_TRANSMIT_UNIT (eth_port_num), 0x0); + + /* Enable port Rx. */ + MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (eth_port_num), + p_eth_port_ctrl->port_rx_queue_command); + + /* Check if link is up */ + eth_port_read_smi_reg (eth_port_num, 1, &phy_reg_data); + + if (!(phy_reg_data & 0x20)) + return false; + + return true; +} + +/******************************************************************************* +* eth_port_uc_addr_set - This function Set the port Unicast address. +* +* DESCRIPTION: +* This function Set the port Ethernet MAC address. +* +* INPUT: +* ETH_PORT eth_port_num Port number. +* char * p_addr Address to be set +* ETH_QUEUE queue Rx queue number for this MAC address. +* +* OUTPUT: +* Set MAC address low and high registers. also calls eth_port_uc_addr() +* To set the unicast table with the proper information. +* +* RETURN: +* N/A. +* +*******************************************************************************/ +static void eth_port_uc_addr_set (ETH_PORT eth_port_num, + unsigned char *p_addr, ETH_QUEUE queue) +{ + unsigned int mac_h; + unsigned int mac_l; + + mac_l = (p_addr[4] << 8) | (p_addr[5]); + mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | + (p_addr[2] << 8) | (p_addr[3] << 0); + + MV_REG_WRITE (MV64460_ETH_MAC_ADDR_LOW (eth_port_num), mac_l); + MV_REG_WRITE (MV64460_ETH_MAC_ADDR_HIGH (eth_port_num), mac_h); + + /* Accept frames of this address */ + eth_port_uc_addr (eth_port_num, p_addr[5], queue, ACCEPT_MAC_ADDR); + + return; +} + +/******************************************************************************* +* eth_port_uc_addr - This function Set the port unicast address table +* +* DESCRIPTION: +* This function locates the proper entry in the Unicast table for the +* specified MAC nibble and sets its properties according to function +* parameters. +* +* INPUT: +* ETH_PORT eth_port_num Port number. +* unsigned char uc_nibble Unicast MAC Address last nibble. +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. +* +* OUTPUT: +* This function add/removes MAC addresses from the port unicast address +* table. +* +* RETURN: +* true is output succeeded. +* false if option parameter is invalid. +* +*******************************************************************************/ +static bool eth_port_uc_addr (ETH_PORT eth_port_num, + unsigned char uc_nibble, + ETH_QUEUE queue, int option) +{ + unsigned int unicast_reg; + unsigned int tbl_offset; + unsigned int reg_offset; + + /* Locate the Unicast table entry */ + uc_nibble = (0xf & uc_nibble); + tbl_offset = (uc_nibble / 4) * 4; /* Register offset from unicast table base */ + reg_offset = uc_nibble % 4; /* Entry offset within the above register */ + + switch (option) { + case REJECT_MAC_ADDR: + /* Clear accepts frame bit at specified unicast DA table entry */ + unicast_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset)); + + unicast_reg &= (0x0E << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset), unicast_reg); + break; + + case ACCEPT_MAC_ADDR: + /* Set accepts frame bit at unicast DA filter table entry */ + unicast_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset)); + + unicast_reg |= ((0x01 | queue) << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset), unicast_reg); + + break; + + default: + return false; + } + return true; +} + +#if 0 /* FIXME */ +/******************************************************************************* +* eth_port_mc_addr - Multicast address settings. +* +* DESCRIPTION: +* This API controls the MV device MAC multicast support. +* The MV device supports multicast using two tables: +* 1) Special Multicast Table for MAC addresses of the form +* 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0x_fF). +* The MAC DA[7:0] bits are used as a pointer to the Special Multicast +* Table entries in the DA-Filter table. +* In this case, the function calls eth_port_smc_addr() routine to set the +* Special Multicast Table. +* 2) Other Multicast Table for multicast of another type. A CRC-8bit +* is used as an index to the Other Multicast Table entries in the +* DA-Filter table. +* In this case, the function calculates the CRC-8bit value and calls +* eth_port_omc_addr() routine to set the Other Multicast Table. +* INPUT: +* ETH_PORT eth_port_num Port number. +* unsigned char *p_addr Unicast MAC Address. +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. +* +* OUTPUT: +* See description. +* +* RETURN: +* true is output succeeded. +* false if add_address_table_entry( ) failed. +* +*******************************************************************************/ +static void eth_port_mc_addr (ETH_PORT eth_port_num, + unsigned char *p_addr, + ETH_QUEUE queue, int option) +{ + unsigned int mac_h; + unsigned int mac_l; + unsigned char crc_result = 0; + int mac_array[48]; + int crc[8]; + int i; + + + if ((p_addr[0] == 0x01) && + (p_addr[1] == 0x00) && + (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) + + eth_port_smc_addr (eth_port_num, p_addr[5], queue, option); + else { + /* Calculate CRC-8 out of the given address */ + mac_h = (p_addr[0] << 8) | (p_addr[1]); + mac_l = (p_addr[2] << 24) | (p_addr[3] << 16) | + (p_addr[4] << 8) | (p_addr[5] << 0); + + for (i = 0; i < 32; i++) + mac_array[i] = (mac_l >> i) & 0x1; + for (i = 32; i < 48; i++) + mac_array[i] = (mac_h >> (i - 32)) & 0x1; + + + crc[0] = mac_array[45] ^ mac_array[43] ^ mac_array[40] ^ + mac_array[39] ^ mac_array[35] ^ mac_array[34] ^ + mac_array[31] ^ mac_array[30] ^ mac_array[28] ^ + mac_array[23] ^ mac_array[21] ^ mac_array[19] ^ + mac_array[18] ^ mac_array[16] ^ mac_array[14] ^ + mac_array[12] ^ mac_array[8] ^ mac_array[7] ^ + mac_array[6] ^ mac_array[0]; + + crc[1] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ + mac_array[43] ^ mac_array[41] ^ mac_array[39] ^ + mac_array[36] ^ mac_array[34] ^ mac_array[32] ^ + mac_array[30] ^ mac_array[29] ^ mac_array[28] ^ + mac_array[24] ^ mac_array[23] ^ mac_array[22] ^ + mac_array[21] ^ mac_array[20] ^ mac_array[18] ^ + mac_array[17] ^ mac_array[16] ^ mac_array[15] ^ + mac_array[14] ^ mac_array[13] ^ mac_array[12] ^ + mac_array[9] ^ mac_array[6] ^ mac_array[1] ^ + mac_array[0]; + + crc[2] = mac_array[47] ^ mac_array[46] ^ mac_array[44] ^ + mac_array[43] ^ mac_array[42] ^ mac_array[39] ^ + mac_array[37] ^ mac_array[34] ^ mac_array[33] ^ + mac_array[29] ^ mac_array[28] ^ mac_array[25] ^ + mac_array[24] ^ mac_array[22] ^ mac_array[17] ^ + mac_array[15] ^ mac_array[13] ^ mac_array[12] ^ + mac_array[10] ^ mac_array[8] ^ mac_array[6] ^ + mac_array[2] ^ mac_array[1] ^ mac_array[0]; + + crc[3] = mac_array[47] ^ mac_array[45] ^ mac_array[44] ^ + mac_array[43] ^ mac_array[40] ^ mac_array[38] ^ + mac_array[35] ^ mac_array[34] ^ mac_array[30] ^ + mac_array[29] ^ mac_array[26] ^ mac_array[25] ^ + mac_array[23] ^ mac_array[18] ^ mac_array[16] ^ + mac_array[14] ^ mac_array[13] ^ mac_array[11] ^ + mac_array[9] ^ mac_array[7] ^ mac_array[3] ^ + mac_array[2] ^ mac_array[1]; + + crc[4] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ + mac_array[41] ^ mac_array[39] ^ mac_array[36] ^ + mac_array[35] ^ mac_array[31] ^ mac_array[30] ^ + mac_array[27] ^ mac_array[26] ^ mac_array[24] ^ + mac_array[19] ^ mac_array[17] ^ mac_array[15] ^ + mac_array[14] ^ mac_array[12] ^ mac_array[10] ^ + mac_array[8] ^ mac_array[4] ^ mac_array[3] ^ + mac_array[2]; + + crc[5] = mac_array[47] ^ mac_array[46] ^ mac_array[45] ^ + mac_array[42] ^ mac_array[40] ^ mac_array[37] ^ + mac_array[36] ^ mac_array[32] ^ mac_array[31] ^ + mac_array[28] ^ mac_array[27] ^ mac_array[25] ^ + mac_array[20] ^ mac_array[18] ^ mac_array[16] ^ + mac_array[15] ^ mac_array[13] ^ mac_array[11] ^ + mac_array[9] ^ mac_array[5] ^ mac_array[4] ^ + mac_array[3]; + + crc[6] = mac_array[47] ^ mac_array[46] ^ mac_array[43] ^ + mac_array[41] ^ mac_array[38] ^ mac_array[37] ^ + mac_array[33] ^ mac_array[32] ^ mac_array[29] ^ + mac_array[28] ^ mac_array[26] ^ mac_array[21] ^ + mac_array[19] ^ mac_array[17] ^ mac_array[16] ^ + mac_array[14] ^ mac_array[12] ^ mac_array[10] ^ + mac_array[6] ^ mac_array[5] ^ mac_array[4]; + + crc[7] = mac_array[47] ^ mac_array[44] ^ mac_array[42] ^ + mac_array[39] ^ mac_array[38] ^ mac_array[34] ^ + mac_array[33] ^ mac_array[30] ^ mac_array[29] ^ + mac_array[27] ^ mac_array[22] ^ mac_array[20] ^ + mac_array[18] ^ mac_array[17] ^ mac_array[15] ^ + mac_array[13] ^ mac_array[11] ^ mac_array[7] ^ + mac_array[6] ^ mac_array[5]; + + for (i = 0; i < 8; i++) + crc_result = crc_result | (crc[i] << i); + + eth_port_omc_addr (eth_port_num, crc_result, queue, option); + } + return; +} + +/******************************************************************************* +* eth_port_smc_addr - Special Multicast address settings. +* +* DESCRIPTION: +* This routine controls the MV device special MAC multicast support. +* The Special Multicast Table for MAC addresses supports MAC of the form +* 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0x_fF). +* The MAC DA[7:0] bits are used as a pointer to the Special Multicast +* Table entries in the DA-Filter table. +* This function set the Special Multicast Table appropriate entry +* according to the argument given. +* +* INPUT: +* ETH_PORT eth_port_num Port number. +* unsigned char mc_byte Multicast addr last byte (MAC DA[7:0] bits). +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. +* +* OUTPUT: +* See description. +* +* RETURN: +* true is output succeeded. +* false if option parameter is invalid. +* +*******************************************************************************/ +static bool eth_port_smc_addr (ETH_PORT eth_port_num, + unsigned char mc_byte, + ETH_QUEUE queue, int option) +{ + unsigned int smc_table_reg; + unsigned int tbl_offset; + unsigned int reg_offset; + + /* Locate the SMC table entry */ + tbl_offset = (mc_byte / 4) * 4; /* Register offset from SMC table base */ + reg_offset = mc_byte % 4; /* Entry offset within the above register */ + queue &= 0x7; + + switch (option) { + case REJECT_MAC_ADDR: + /* Clear accepts frame bit at specified Special DA table entry */ + smc_table_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + smc_table_reg &= (0x0E << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset), smc_table_reg); + break; + + case ACCEPT_MAC_ADDR: + /* Set accepts frame bit at specified Special DA table entry */ + smc_table_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + smc_table_reg |= ((0x01 | queue) << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset), smc_table_reg); + break; + + default: + return false; + } + return true; +} + +/******************************************************************************* +* eth_port_omc_addr - Multicast address settings. +* +* DESCRIPTION: +* This routine controls the MV device Other MAC multicast support. +* The Other Multicast Table is used for multicast of another type. +* A CRC-8bit is used as an index to the Other Multicast Table entries +* in the DA-Filter table. +* The function gets the CRC-8bit value from the calling routine and +* set the Other Multicast Table appropriate entry according to the +* CRC-8 argument given. +* +* INPUT: +* ETH_PORT eth_port_num Port number. +* unsigned char crc8 A CRC-8bit (Polynomial: x^8+x^2+x^1+1). +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. +* +* OUTPUT: +* See description. +* +* RETURN: +* true is output succeeded. +* false if option parameter is invalid. +* +*******************************************************************************/ +static bool eth_port_omc_addr (ETH_PORT eth_port_num, + unsigned char crc8, + ETH_QUEUE queue, int option) +{ + unsigned int omc_table_reg; + unsigned int tbl_offset; + unsigned int reg_offset; + + /* Locate the OMC table entry */ + tbl_offset = (crc8 / 4) * 4; /* Register offset from OMC table base */ + reg_offset = crc8 % 4; /* Entry offset within the above register */ + queue &= 0x7; + + switch (option) { + case REJECT_MAC_ADDR: + /* Clear accepts frame bit at specified Other DA table entry */ + omc_table_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + omc_table_reg &= (0x0E << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset), omc_table_reg); + break; + + case ACCEPT_MAC_ADDR: + /* Set accepts frame bit at specified Other DA table entry */ + omc_table_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + omc_table_reg |= ((0x01 | queue) << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset), omc_table_reg); + break; + + default: + return false; + } + return true; +} +#endif + +/******************************************************************************* +* eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables +* +* DESCRIPTION: +* Go through all the DA filter tables (Unicast, Special Multicast & Other +* Multicast) and set each entry to 0. +* +* INPUT: +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* +* OUTPUT: +* Multicast and Unicast packets are rejected. +* +* RETURN: +* None. +* +*******************************************************************************/ +static void eth_port_init_mac_tables (ETH_PORT eth_port_num) +{ + int table_index; + + /* Clear DA filter unicast table (Ex_dFUT) */ + for (table_index = 0; table_index <= 0xC; table_index += 4) + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + table_index), 0); + + for (table_index = 0; table_index <= 0xFC; table_index += 4) { + /* Clear DA filter special multicast table (Ex_dFSMT) */ + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + table_index), 0); + /* Clear DA filter other multicast table (Ex_dFOMT) */ + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + table_index), 0); + } +} + +/******************************************************************************* +* eth_clear_mib_counters - Clear all MIB counters +* +* DESCRIPTION: +* This function clears all MIB counters of a specific ethernet port. +* A read from the MIB counter will reset the counter. +* +* INPUT: +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* +* OUTPUT: +* After reading all MIB counters, the counters resets. +* +* RETURN: +* MIB counter value. +* +*******************************************************************************/ +static void eth_clear_mib_counters (ETH_PORT eth_port_num) +{ + int i; + unsigned int dummy; + + /* Perform dummy reads from MIB counters */ + for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION; + i += 4) + dummy = MV_REG_READ ((MV64460_ETH_MIB_COUNTERS_BASE + (eth_port_num) + i)); + + return; +} + +/******************************************************************************* +* eth_read_mib_counter - Read a MIB counter +* +* DESCRIPTION: +* This function reads a MIB counter of a specific ethernet port. +* NOTE - If read from ETH_MIB_GOOD_OCTETS_RECEIVED_LOW, then the +* following read must be from ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH +* register. The same applies for ETH_MIB_GOOD_OCTETS_SENT_LOW and +* ETH_MIB_GOOD_OCTETS_SENT_HIGH +* +* INPUT: +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* unsigned int mib_offset MIB counter offset (use ETH_MIB_... macros). +* +* OUTPUT: +* After reading the MIB counter, the counter resets. +* +* RETURN: +* MIB counter value. +* +*******************************************************************************/ +unsigned int eth_read_mib_counter (ETH_PORT eth_port_num, + unsigned int mib_offset) +{ + return (MV_REG_READ (MV64460_ETH_MIB_COUNTERS_BASE (eth_port_num) + + mib_offset)); +} + +/******************************************************************************* +* ethernet_phy_set - Set the ethernet port PHY address. +* +* DESCRIPTION: +* This routine set the ethernet port PHY address according to given +* parameter. +* +* INPUT: +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* +* OUTPUT: +* Set PHY Address Register with given PHY address parameter. +* +* RETURN: +* None. +* +*******************************************************************************/ +static void ethernet_phy_set (ETH_PORT eth_port_num, int phy_addr) +{ + unsigned int reg_data; + + reg_data = MV_REG_READ (MV64460_ETH_PHY_ADDR_REG); + + reg_data &= ~(0x1F << (5 * eth_port_num)); + reg_data |= (phy_addr << (5 * eth_port_num)); + + MV_REG_WRITE (MV64460_ETH_PHY_ADDR_REG, reg_data); + + return; +} + +/******************************************************************************* + * ethernet_phy_get - Get the ethernet port PHY address. + * + * DESCRIPTION: + * This routine returns the given ethernet port PHY address. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * + * OUTPUT: + * None. + * + * RETURN: + * PHY address. + * + *******************************************************************************/ +static int ethernet_phy_get (ETH_PORT eth_port_num) +{ + unsigned int reg_data; + + reg_data = MV_REG_READ (MV64460_ETH_PHY_ADDR_REG); + + return ((reg_data >> (5 * eth_port_num)) & 0x1f); +} + +/***********************************************************/ +/* (Re)start autonegotiation */ +/***********************************************************/ +int phy_setup_aneg (char *devname, unsigned char addr) +{ + unsigned short ctl, adv; + + /* Setup standard advertise */ + miiphy_read (devname, addr, PHY_ANAR, &adv); + adv |= (PHY_ANLPAR_ACK | PHY_ANLPAR_RF | PHY_ANLPAR_T4 | + PHY_ANLPAR_TXFD | PHY_ANLPAR_TX | PHY_ANLPAR_10FD | + PHY_ANLPAR_10); + miiphy_write (devname, addr, PHY_ANAR, adv); + + miiphy_read (devname, addr, PHY_1000BTCR, &adv); + adv |= (0x0300); + miiphy_write (devname, addr, PHY_1000BTCR, adv); + + /* Start/Restart aneg */ + miiphy_read (devname, addr, PHY_BMCR, &ctl); + ctl |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG); + miiphy_write (devname, addr, PHY_BMCR, ctl); + + return 0; +} + +/******************************************************************************* + * ethernet_phy_reset - Reset Ethernet port PHY. + * + * DESCRIPTION: + * This routine utilize the SMI interface to reset the ethernet port PHY. + * The routine waits until the link is up again or link up is timeout. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * + * OUTPUT: + * The ethernet port PHY renew its link. + * + * RETURN: + * None. + * + *******************************************************************************/ +static bool ethernet_phy_reset (ETH_PORT eth_port_num) +{ + unsigned int time_out = 50; + unsigned int phy_reg_data; + + eth_port_read_smi_reg (eth_port_num, 20, &phy_reg_data); + phy_reg_data |= 0x0083; /* Set bit 7 to 1 for different RGMII timing */ + eth_port_write_smi_reg (eth_port_num, 20, phy_reg_data); + + /* Reset the PHY */ + eth_port_read_smi_reg (eth_port_num, 0, &phy_reg_data); + phy_reg_data |= 0x8000; /* Set bit 15 to reset the PHY */ + eth_port_write_smi_reg (eth_port_num, 0, phy_reg_data); + + /* Poll on the PHY LINK */ + do { + eth_port_read_smi_reg (eth_port_num, 1, &phy_reg_data); + + if (time_out-- == 0) + return false; + } + while (!(phy_reg_data & 0x20)); + + return true; +} + +/******************************************************************************* + * eth_port_reset - Reset Ethernet port + * + * DESCRIPTION: + * This routine resets the chip by aborting any SDMA engine activity and + * clearing the MIB counters. The Receiver and the Transmit unit are in + * idle state after this command is performed and the port is disabled. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * + * OUTPUT: + * Channel activity is halted. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void eth_port_reset (ETH_PORT eth_port_num) +{ + unsigned int reg_data; + + /* Stop Tx port activity. Check port Tx activity. */ + reg_data = + MV_REG_READ (MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG + (eth_port_num)); + + if (reg_data & 0xFF) { + /* Issue stop command for active channels only */ + MV_REG_WRITE (MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG + (eth_port_num), (reg_data << 8)); + + /* Wait for all Tx activity to terminate. */ + do { + /* Check port cause register that all Tx queues are stopped */ + reg_data = + MV_REG_READ + (MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG + (eth_port_num)); + } + while (reg_data & 0xFF); + } + + /* Stop Rx port activity. Check port Rx activity. */ + reg_data = + MV_REG_READ (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG + (eth_port_num)); + + if (reg_data & 0xFF) { + /* Issue stop command for active channels only */ + MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG + (eth_port_num), (reg_data << 8)); + + /* Wait for all Rx activity to terminate. */ + do { + /* Check port cause register that all Rx queues are stopped */ + reg_data = + MV_REG_READ + (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG + (eth_port_num)); + } + while (reg_data & 0xFF); + } + + /* Clear all MIB counters */ + eth_clear_mib_counters (eth_port_num); + + /* Reset the Enable bit in the Configuration Register */ + reg_data = + MV_REG_READ (MV64460_ETH_PORT_SERIAL_CONTROL_REG + (eth_port_num)); + reg_data &= ~ETH_SERIAL_PORT_ENABLE; + MV_REG_WRITE (MV64460_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num), + reg_data); + + return; +} + +#if 0 /* Not needed here */ +/******************************************************************************* + * ethernet_set_config_reg - Set specified bits in configuration register. + * + * DESCRIPTION: + * This function sets specified bits in the given ethernet + * configuration register. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int value 32 bit value. + * + * OUTPUT: + * The set bits in the value parameter are set in the configuration + * register. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void ethernet_set_config_reg (ETH_PORT eth_port_num, + unsigned int value) +{ + unsigned int eth_config_reg; + + eth_config_reg = + MV_REG_READ (MV64460_ETH_PORT_CONFIG_REG (eth_port_num)); + eth_config_reg |= value; + MV_REG_WRITE (MV64460_ETH_PORT_CONFIG_REG (eth_port_num), + eth_config_reg); + + return; +} +#endif + +#if 0 /* FIXME */ +/******************************************************************************* + * ethernet_reset_config_reg - Reset specified bits in configuration register. + * + * DESCRIPTION: + * This function resets specified bits in the given Ethernet + * configuration register. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int value 32 bit value. + * + * OUTPUT: + * The set bits in the value parameter are reset in the configuration + * register. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void ethernet_reset_config_reg (ETH_PORT eth_port_num, + unsigned int value) +{ + unsigned int eth_config_reg; + + eth_config_reg = MV_REG_READ (MV64460_ETH_PORT_CONFIG_EXTEND_REG + (eth_port_num)); + eth_config_reg &= ~value; + MV_REG_WRITE (MV64460_ETH_PORT_CONFIG_EXTEND_REG (eth_port_num), + eth_config_reg); + + return; +} +#endif + +#if 0 /* Not needed here */ +/******************************************************************************* + * ethernet_get_config_reg - Get the port configuration register + * + * DESCRIPTION: + * This function returns the configuration register value of the given + * ethernet port. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * + * OUTPUT: + * None. + * + * RETURN: + * Port configuration register value. + * + *******************************************************************************/ +static unsigned int ethernet_get_config_reg (ETH_PORT eth_port_num) +{ + unsigned int eth_config_reg; + + eth_config_reg = MV_REG_READ (MV64460_ETH_PORT_CONFIG_EXTEND_REG + (eth_port_num)); + return eth_config_reg; +} + +#endif + +/******************************************************************************* + * eth_port_read_smi_reg - Read PHY registers + * + * DESCRIPTION: + * This routine utilize the SMI interface to interact with the PHY in + * order to perform PHY register read. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int phy_reg PHY register address offset. + * unsigned int *value Register value buffer. + * + * OUTPUT: + * Write the value of a specified PHY register into given buffer. + * + * RETURN: + * false if the PHY is busy or read data is not in valid state. + * true otherwise. + * + *******************************************************************************/ +static bool eth_port_read_smi_reg (ETH_PORT eth_port_num, + unsigned int phy_reg, unsigned int *value) +{ + unsigned int reg_value; + unsigned int time_out = PHY_BUSY_TIMEOUT; + int phy_addr; + + phy_addr = ethernet_phy_get (eth_port_num); + + /* first check that it is not busy */ + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while (reg_value & ETH_SMI_BUSY); + + /* not busy */ + + MV_REG_WRITE (MV64460_ETH_SMI_REG, + (phy_addr << 16) | (phy_reg << 21) | + ETH_SMI_OPCODE_READ); + + time_out = PHY_BUSY_TIMEOUT; /* initialize the time out var again */ + + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while ((reg_value & ETH_SMI_READ_VALID) != ETH_SMI_READ_VALID); /* Bit set equ operation done */ + + /* Wait for the data to update in the SMI register */ +#define PHY_UPDATE_TIMEOUT 10000 + for (time_out = 0; time_out < PHY_UPDATE_TIMEOUT; time_out++); + + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + + *value = reg_value & 0xffff; + + return true; +} + +int mv_miiphy_read(char *devname, unsigned char phy_addr, + unsigned char phy_reg, unsigned short *value) +{ + unsigned int reg_value; + unsigned int time_out = PHY_BUSY_TIMEOUT; + + /* first check that it is not busy */ + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while (reg_value & ETH_SMI_BUSY); + + /* not busy */ + MV_REG_WRITE (MV64460_ETH_SMI_REG, + (phy_addr << 16) | (phy_reg << 21) | + ETH_SMI_OPCODE_READ); + + time_out = PHY_BUSY_TIMEOUT; /* initialize the time out var again */ + + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while ((reg_value & ETH_SMI_READ_VALID) != ETH_SMI_READ_VALID); /* Bit set equ operation done */ + + /* Wait for the data to update in the SMI register */ + for (time_out = 0; time_out < PHY_UPDATE_TIMEOUT; time_out++); + + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + + *value = reg_value & 0xffff; + + return 0; +} + +/******************************************************************************* + * eth_port_write_smi_reg - Write to PHY registers + * + * DESCRIPTION: + * This routine utilize the SMI interface to interact with the PHY in + * order to perform writes to PHY registers. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int phy_reg PHY register address offset. + * unsigned int value Register value. + * + * OUTPUT: + * Write the given value to the specified PHY register. + * + * RETURN: + * false if the PHY is busy. + * true otherwise. + * + *******************************************************************************/ +static bool eth_port_write_smi_reg (ETH_PORT eth_port_num, + unsigned int phy_reg, unsigned int value) +{ + unsigned int reg_value; + unsigned int time_out = PHY_BUSY_TIMEOUT; + int phy_addr; + + phy_addr = ethernet_phy_get (eth_port_num); + + /* first check that it is not busy */ + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while (reg_value & ETH_SMI_BUSY); + + /* not busy */ + MV_REG_WRITE (MV64460_ETH_SMI_REG, + (phy_addr << 16) | (phy_reg << 21) | + ETH_SMI_OPCODE_WRITE | (value & 0xffff)); + return true; +} + +int mv_miiphy_write(char *devname, unsigned char phy_addr, + unsigned char phy_reg, unsigned short value) +{ + unsigned int reg_value; + unsigned int time_out = PHY_BUSY_TIMEOUT; + + /* first check that it is not busy */ + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while (reg_value & ETH_SMI_BUSY); + + /* not busy */ + MV_REG_WRITE (MV64460_ETH_SMI_REG, + (phy_addr << 16) | (phy_reg << 21) | + ETH_SMI_OPCODE_WRITE | (value & 0xffff)); + return 0; +} + +/******************************************************************************* + * eth_set_access_control - Config address decode parameters for Ethernet unit + * + * DESCRIPTION: + * This function configures the address decode parameters for the Gigabit + * Ethernet Controller according the given parameters struct. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * ETH_WIN_PARAM *param Address decode parameter struct. + * + * OUTPUT: + * An access window is opened using the given access parameters. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void eth_set_access_control (ETH_PORT eth_port_num, + ETH_WIN_PARAM * param) +{ + unsigned int access_prot_reg; + + /* Set access control register */ + access_prot_reg = MV_REG_READ (MV64460_ETH_ACCESS_PROTECTION_REG + (eth_port_num)); + access_prot_reg &= (~(3 << (param->win * 2))); /* clear window permission */ + access_prot_reg |= (param->access_ctrl << (param->win * 2)); + MV_REG_WRITE (MV64460_ETH_ACCESS_PROTECTION_REG (eth_port_num), + access_prot_reg); + + /* Set window Size reg (SR) */ + MV_REG_WRITE ((MV64460_ETH_SIZE_REG_0 + + (ETH_SIZE_REG_GAP * param->win)), + (((param->size / 0x10000) - 1) << 16)); + + /* Set window Base address reg (BA) */ + MV_REG_WRITE ((MV64460_ETH_BAR_0 + (ETH_BAR_GAP * param->win)), + (param->target | param->attributes | param->base_addr)); + /* High address remap reg (HARR) */ + if (param->win < 4) + MV_REG_WRITE ((MV64460_ETH_HIGH_ADDR_REMAP_REG_0 + + (ETH_HIGH_ADDR_REMAP_REG_GAP * param->win)), + param->high_addr); + + /* Base address enable reg (BARER) */ + if (param->enable == 1) + MV_RESET_REG_BITS (MV64460_ETH_BASE_ADDR_ENABLE_REG, + (1 << param->win)); + else + MV_SET_REG_BITS (MV64460_ETH_BASE_ADDR_ENABLE_REG, + (1 << param->win)); +} + +/******************************************************************************* + * ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory. + * + * DESCRIPTION: + * This function prepares a Rx chained list of descriptors and packet + * buffers in a form of a ring. The routine must be called after port + * initialization routine and before port start routine. + * The Ethernet SDMA engine uses CPU bus addresses to access the various + * devices in the system (i.e. DRAM). This function uses the ethernet + * struct 'virtual to physical' routine (set by the user) to set the ring + * with physical addresses. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * int rx_desc_num Number of Rx descriptors + * int rx_buff_size Size of Rx buffer + * unsigned int rx_desc_base_addr Rx descriptors memory area base addr. + * unsigned int rx_buff_base_addr Rx buffer memory area base addr. + * + * OUTPUT: + * The routine updates the Ethernet port control struct with information + * regarding the Rx descriptors and buffers. + * + * RETURN: + * false if the given descriptors memory area is not aligned according to + * Ethernet SDMA specifications. + * true otherwise. + * + *******************************************************************************/ +static bool ether_init_rx_desc_ring (ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE rx_queue, + int rx_desc_num, + int rx_buff_size, + unsigned int rx_desc_base_addr, + unsigned int rx_buff_base_addr) +{ + ETH_RX_DESC *p_rx_desc; + ETH_RX_DESC *p_rx_prev_desc; /* pointer to link with the last descriptor */ + unsigned int buffer_addr; + int ix; /* a counter */ + + + p_rx_desc = (ETH_RX_DESC *) rx_desc_base_addr; + p_rx_prev_desc = p_rx_desc; + buffer_addr = rx_buff_base_addr; + + /* Rx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */ + if (rx_buff_base_addr & 0xF) + return false; + + /* Rx buffers are limited to 64K bytes and Minimum size is 8 bytes */ + if ((rx_buff_size < 8) || (rx_buff_size > RX_BUFFER_MAX_SIZE)) + return false; + + /* Rx buffers must be 64-bit aligned. */ + if ((rx_buff_base_addr + rx_buff_size) & 0x7) + return false; + + /* initialize the Rx descriptors ring */ + for (ix = 0; ix < rx_desc_num; ix++) { + p_rx_desc->buf_size = rx_buff_size; + p_rx_desc->byte_cnt = 0x0000; + p_rx_desc->cmd_sts = + ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT; + p_rx_desc->next_desc_ptr = + ((unsigned int) p_rx_desc) + RX_DESC_ALIGNED_SIZE; + p_rx_desc->buf_ptr = buffer_addr; + p_rx_desc->return_info = 0x00000000; + D_CACHE_FLUSH_LINE (p_rx_desc, 0); + buffer_addr += rx_buff_size; + p_rx_prev_desc = p_rx_desc; + p_rx_desc = (ETH_RX_DESC *) + ((unsigned int) p_rx_desc + RX_DESC_ALIGNED_SIZE); + } + + /* Closing Rx descriptors ring */ + p_rx_prev_desc->next_desc_ptr = (rx_desc_base_addr); + D_CACHE_FLUSH_LINE (p_rx_prev_desc, 0); + + /* Save Rx desc pointer to driver struct. */ + CURR_RFD_SET ((ETH_RX_DESC *) rx_desc_base_addr, rx_queue); + USED_RFD_SET ((ETH_RX_DESC *) rx_desc_base_addr, rx_queue); + + p_eth_port_ctrl->p_rx_desc_area_base[rx_queue] = + (ETH_RX_DESC *) rx_desc_base_addr; + p_eth_port_ctrl->rx_desc_area_size[rx_queue] = + rx_desc_num * RX_DESC_ALIGNED_SIZE; + + p_eth_port_ctrl->port_rx_queue_command |= (1 << rx_queue); + + return true; +} + +/******************************************************************************* + * ether_init_tx_desc_ring - Curve a Tx chain desc list and buffer in memory. + * + * DESCRIPTION: + * This function prepares a Tx chained list of descriptors and packet + * buffers in a form of a ring. The routine must be called after port + * initialization routine and before port start routine. + * The Ethernet SDMA engine uses CPU bus addresses to access the various + * devices in the system (i.e. DRAM). This function uses the ethernet + * struct 'virtual to physical' routine (set by the user) to set the ring + * with physical addresses. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * int tx_desc_num Number of Tx descriptors + * int tx_buff_size Size of Tx buffer + * unsigned int tx_desc_base_addr Tx descriptors memory area base addr. + * unsigned int tx_buff_base_addr Tx buffer memory area base addr. + * + * OUTPUT: + * The routine updates the Ethernet port control struct with information + * regarding the Tx descriptors and buffers. + * + * RETURN: + * false if the given descriptors memory area is not aligned according to + * Ethernet SDMA specifications. + * true otherwise. + * + *******************************************************************************/ +static bool ether_init_tx_desc_ring (ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE tx_queue, + int tx_desc_num, + int tx_buff_size, + unsigned int tx_desc_base_addr, + unsigned int tx_buff_base_addr) +{ + + ETH_TX_DESC *p_tx_desc; + ETH_TX_DESC *p_tx_prev_desc; + unsigned int buffer_addr; + int ix; /* a counter */ + + + /* save the first desc pointer to link with the last descriptor */ + p_tx_desc = (ETH_TX_DESC *) tx_desc_base_addr; + p_tx_prev_desc = p_tx_desc; + buffer_addr = tx_buff_base_addr; + + /* Tx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */ + if (tx_buff_base_addr & 0xF) + return false; + + /* Tx buffers are limited to 64K bytes and Minimum size is 8 bytes */ + if ((tx_buff_size > TX_BUFFER_MAX_SIZE) + || (tx_buff_size < TX_BUFFER_MIN_SIZE)) + return false; + + /* Initialize the Tx descriptors ring */ + for (ix = 0; ix < tx_desc_num; ix++) { + p_tx_desc->byte_cnt = 0x0000; + p_tx_desc->l4i_chk = 0x0000; + p_tx_desc->cmd_sts = 0x00000000; + p_tx_desc->next_desc_ptr = + ((unsigned int) p_tx_desc) + TX_DESC_ALIGNED_SIZE; + + p_tx_desc->buf_ptr = buffer_addr; + p_tx_desc->return_info = 0x00000000; + D_CACHE_FLUSH_LINE (p_tx_desc, 0); + buffer_addr += tx_buff_size; + p_tx_prev_desc = p_tx_desc; + p_tx_desc = (ETH_TX_DESC *) + ((unsigned int) p_tx_desc + TX_DESC_ALIGNED_SIZE); + + } + /* Closing Tx descriptors ring */ + p_tx_prev_desc->next_desc_ptr = tx_desc_base_addr; + D_CACHE_FLUSH_LINE (p_tx_prev_desc, 0); + /* Set Tx desc pointer in driver struct. */ + CURR_TFD_SET ((ETH_TX_DESC *) tx_desc_base_addr, tx_queue); + USED_TFD_SET ((ETH_TX_DESC *) tx_desc_base_addr, tx_queue); + + /* Init Tx ring base and size parameters */ + p_eth_port_ctrl->p_tx_desc_area_base[tx_queue] = + (ETH_TX_DESC *) tx_desc_base_addr; + p_eth_port_ctrl->tx_desc_area_size[tx_queue] = + (tx_desc_num * TX_DESC_ALIGNED_SIZE); + + /* Add the queue to the list of Tx queues of this port */ + p_eth_port_ctrl->port_tx_queue_command |= (1 << tx_queue); + + return true; +} + +/******************************************************************************* + * eth_port_send - Send an Ethernet packet + * + * DESCRIPTION: + * This routine send a given packet described by p_pktinfo parameter. It + * supports transmitting of a packet spaned over multiple buffers. The + * routine updates 'curr' and 'first' indexes according to the packet + * segment passed to the routine. In case the packet segment is first, + * the 'first' index is update. In any case, the 'curr' index is updated. + * If the routine get into Tx resource error it assigns 'curr' index as + * 'first'. This way the function can abort Tx process of multiple + * descriptors per packet. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * PKT_INFO *p_pkt_info User packet buffer. + * + * OUTPUT: + * Tx ring 'curr' and 'first' indexes are updated. + * + * RETURN: + * ETH_QUEUE_FULL in case of Tx resource error. + * ETH_ERROR in case the routine can not access Tx desc ring. + * ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_port_send (ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_TX_DESC *p_tx_desc_first; + volatile ETH_TX_DESC *p_tx_desc_curr; + volatile ETH_TX_DESC *p_tx_next_desc_curr; + volatile ETH_TX_DESC *p_tx_desc_used; + unsigned int command_status; + + /* Do not process Tx ring in case of Tx ring resource error */ + if (p_eth_port_ctrl->tx_resource_err[tx_queue] == true) + return ETH_QUEUE_FULL; + + /* Get the Tx Desc ring indexes */ + CURR_TFD_GET (p_tx_desc_curr, tx_queue); + USED_TFD_GET (p_tx_desc_used, tx_queue); + + if (p_tx_desc_curr == NULL) + return ETH_ERROR; + + /* The following parameters are used to save readings from memory */ + p_tx_next_desc_curr = TX_NEXT_DESC_PTR (p_tx_desc_curr, tx_queue); + command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC; + + if (command_status & (ETH_TX_FIRST_DESC)) { + /* Update first desc */ + FIRST_TFD_SET (p_tx_desc_curr, tx_queue); + p_tx_desc_first = p_tx_desc_curr; + } else { + FIRST_TFD_GET (p_tx_desc_first, tx_queue); + command_status |= ETH_BUFFER_OWNED_BY_DMA; + } + + /* Buffers with a payload smaller than 8 bytes must be aligned to 64-bit */ + /* boundary. We use the memory allocated for Tx descriptor. This memory */ + /* located in TX_BUF_OFFSET_IN_DESC offset within the Tx descriptor. */ + if (p_pkt_info->byte_cnt <= 8) { + printf ("You have failed in the < 8 bytes errata - fixme\n"); /* RABEEH - TBD */ + return ETH_ERROR; + + p_tx_desc_curr->buf_ptr = + (unsigned int) p_tx_desc_curr + TX_BUF_OFFSET_IN_DESC; + eth_b_copy (p_pkt_info->buf_ptr, p_tx_desc_curr->buf_ptr, + p_pkt_info->byte_cnt); + } else + p_tx_desc_curr->buf_ptr = p_pkt_info->buf_ptr; + + p_tx_desc_curr->byte_cnt = p_pkt_info->byte_cnt; + p_tx_desc_curr->return_info = p_pkt_info->return_info; + + if (p_pkt_info->cmd_sts & (ETH_TX_LAST_DESC)) { + /* Set last desc with DMA ownership and interrupt enable. */ + p_tx_desc_curr->cmd_sts = command_status | + ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT; + + if (p_tx_desc_curr != p_tx_desc_first) + p_tx_desc_first->cmd_sts |= ETH_BUFFER_OWNED_BY_DMA; + + /* Flush CPU pipe */ + + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_curr, 0); + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_first, 0); + CPU_PIPE_FLUSH; + + /* Apply send command */ + ETH_ENABLE_TX_QUEUE (tx_queue, p_eth_port_ctrl->port_num); + + /* Finish Tx packet. Update first desc in case of Tx resource error */ + p_tx_desc_first = p_tx_next_desc_curr; + FIRST_TFD_SET (p_tx_desc_first, tx_queue); + + } else { + p_tx_desc_curr->cmd_sts = command_status; + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_curr, 0); + } + + /* Check for ring index overlap in the Tx desc ring */ + if (p_tx_next_desc_curr == p_tx_desc_used) { + /* Update the current descriptor */ + CURR_TFD_SET (p_tx_desc_first, tx_queue); + + p_eth_port_ctrl->tx_resource_err[tx_queue] = true; + return ETH_QUEUE_LAST_RESOURCE; + } else { + /* Update the current descriptor */ + CURR_TFD_SET (p_tx_next_desc_curr, tx_queue); + return ETH_OK; + } +} + +/******************************************************************************* + * eth_tx_return_desc - Free all used Tx descriptors + * + * DESCRIPTION: + * This routine returns the transmitted packet information to the caller. + * It uses the 'first' index to support Tx desc return in case a transmit + * of a packet spanned over multiple buffer still in process. + * In case the Tx queue was in "resource error" condition, where there are + * no available Tx resources, the function resets the resource error flag. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * PKT_INFO *p_pkt_info User packet buffer. + * + * OUTPUT: + * Tx ring 'first' and 'used' indexes are updated. + * + * RETURN: + * ETH_ERROR in case the routine can not access Tx desc ring. + * ETH_RETRY in case there is transmission in process. + * ETH_END_OF_JOB if the routine has nothing to release. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_tx_return_desc (ETH_PORT_INFO * + p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_TX_DESC *p_tx_desc_used = NULL; + volatile ETH_TX_DESC *p_tx_desc_first = NULL; + unsigned int command_status; + + + /* Get the Tx Desc ring indexes */ + USED_TFD_GET (p_tx_desc_used, tx_queue); + FIRST_TFD_GET (p_tx_desc_first, tx_queue); + + + /* Sanity check */ + if (p_tx_desc_used == NULL) + return ETH_ERROR; + + command_status = p_tx_desc_used->cmd_sts; + + /* Still transmitting... */ + if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) { + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_used, 0); + return ETH_RETRY; + } + + /* Stop release. About to overlap the current available Tx descriptor */ + if ((p_tx_desc_used == p_tx_desc_first) && + (p_eth_port_ctrl->tx_resource_err[tx_queue] == false)) { + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_used, 0); + return ETH_END_OF_JOB; + } + + /* Pass the packet information to the caller */ + p_pkt_info->cmd_sts = command_status; + p_pkt_info->return_info = p_tx_desc_used->return_info; + p_tx_desc_used->return_info = 0; + + /* Update the next descriptor to release. */ + USED_TFD_SET (TX_NEXT_DESC_PTR (p_tx_desc_used, tx_queue), tx_queue); + + /* Any Tx return cancels the Tx resource error status */ + if (p_eth_port_ctrl->tx_resource_err[tx_queue] == true) + p_eth_port_ctrl->tx_resource_err[tx_queue] = false; + + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_used, 0); + + return ETH_OK; + +} + +/******************************************************************************* + * eth_port_receive - Get received information from Rx ring. + * + * DESCRIPTION: + * This routine returns the received data to the caller. There is no + * data copying during routine operation. All information is returned + * using pointer to packet information struct passed from the caller. + * If the routine exhausts Rx ring resources then the resource error flag + * is set. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * PKT_INFO *p_pkt_info User packet buffer. + * + * OUTPUT: + * Rx ring current and used indexes are updated. + * + * RETURN: + * ETH_ERROR in case the routine can not access Rx desc ring. + * ETH_QUEUE_FULL if Rx ring resources are exhausted. + * ETH_END_OF_JOB if there is no received data. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_port_receive (ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_RX_DESC *p_rx_curr_desc; + volatile ETH_RX_DESC *p_rx_next_curr_desc; + volatile ETH_RX_DESC *p_rx_used_desc; + unsigned int command_status; + + /* Do not process Rx ring in case of Rx ring resource error */ + if (p_eth_port_ctrl->rx_resource_err[rx_queue] == true) { + printf ("\nRx Queue is full ...\n"); + return ETH_QUEUE_FULL; + } + + /* Get the Rx Desc ring 'curr and 'used' indexes */ + CURR_RFD_GET (p_rx_curr_desc, rx_queue); + USED_RFD_GET (p_rx_used_desc, rx_queue); + + /* Sanity check */ + if (p_rx_curr_desc == NULL) + return ETH_ERROR; + + /* The following parameters are used to save readings from memory */ + p_rx_next_curr_desc = RX_NEXT_DESC_PTR (p_rx_curr_desc, rx_queue); + command_status = p_rx_curr_desc->cmd_sts; + + /* Nothing to receive... */ + if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) { +/* DP(printf("Rx: command_status: %08x\n", command_status)); */ + D_CACHE_FLUSH_LINE ((unsigned int) p_rx_curr_desc, 0); +/* DP(printf("\nETH_END_OF_JOB ...\n"));*/ + return ETH_END_OF_JOB; + } + + p_pkt_info->byte_cnt = (p_rx_curr_desc->byte_cnt) - RX_BUF_OFFSET; + p_pkt_info->cmd_sts = command_status; + p_pkt_info->buf_ptr = (p_rx_curr_desc->buf_ptr) + RX_BUF_OFFSET; + p_pkt_info->return_info = p_rx_curr_desc->return_info; + p_pkt_info->l4i_chk = p_rx_curr_desc->buf_size; /* IP fragment indicator */ + + /* Clean the return info field to indicate that the packet has been */ + /* moved to the upper layers */ + p_rx_curr_desc->return_info = 0; + + /* Update 'curr' in data structure */ + CURR_RFD_SET (p_rx_next_curr_desc, rx_queue); + + /* Rx descriptors resource exhausted. Set the Rx ring resource error flag */ + if (p_rx_next_curr_desc == p_rx_used_desc) + p_eth_port_ctrl->rx_resource_err[rx_queue] = true; + + D_CACHE_FLUSH_LINE ((unsigned int) p_rx_curr_desc, 0); + CPU_PIPE_FLUSH; + + return ETH_OK; +} + +/******************************************************************************* + * eth_rx_return_buff - Returns a Rx buffer back to the Rx ring. + * + * DESCRIPTION: + * This routine returns a Rx buffer back to the Rx ring. It retrieves the + * next 'used' descriptor and attached the returned buffer to it. + * In case the Rx ring was in "resource error" condition, where there are + * no available Rx resources, the function resets the resource error flag. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * PKT_INFO *p_pkt_info Information on the returned buffer. + * + * OUTPUT: + * New available Rx resource in Rx descriptor ring. + * + * RETURN: + * ETH_ERROR in case the routine can not access Rx desc ring. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_rx_return_buff (ETH_PORT_INFO * + p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_RX_DESC *p_used_rx_desc; /* Where to return Rx resource */ + + /* Get 'used' Rx descriptor */ + USED_RFD_GET (p_used_rx_desc, rx_queue); + + /* Sanity check */ + if (p_used_rx_desc == NULL) + return ETH_ERROR; + + p_used_rx_desc->buf_ptr = p_pkt_info->buf_ptr; + p_used_rx_desc->return_info = p_pkt_info->return_info; + p_used_rx_desc->byte_cnt = p_pkt_info->byte_cnt; + p_used_rx_desc->buf_size = MV64460_RX_BUFFER_SIZE; /* Reset Buffer size */ + + /* Flush the write pipe */ + CPU_PIPE_FLUSH; + + /* Return the descriptor to DMA ownership */ + p_used_rx_desc->cmd_sts = + ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT; + + /* Flush descriptor and CPU pipe */ + D_CACHE_FLUSH_LINE ((unsigned int) p_used_rx_desc, 0); + CPU_PIPE_FLUSH; + + /* Move the used descriptor pointer to the next descriptor */ + USED_RFD_SET (RX_NEXT_DESC_PTR (p_used_rx_desc, rx_queue), rx_queue); + + /* Any Rx return cancels the Rx resource error status */ + if (p_eth_port_ctrl->rx_resource_err[rx_queue] == true) + p_eth_port_ctrl->rx_resource_err[rx_queue] = false; + + return ETH_OK; +} + +/******************************************************************************* + * eth_port_set_rx_coal - Sets coalescing interrupt mechanism on RX path + * + * DESCRIPTION: + * This routine sets the RX coalescing interrupt mechanism parameter. + * This parameter is a timeout counter, that counts in 64 t_clk + * chunks ; that when timeout event occurs a maskable interrupt + * occurs. + * The parameter is calculated using the tClk of the MV-643xx chip + * , and the required delay of the interrupt in usec. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet port number + * unsigned int t_clk t_clk of the MV-643xx chip in HZ units + * unsigned int delay Delay in usec + * + * OUTPUT: + * Interrupt coalescing mechanism value is set in MV-643xx chip. + * + * RETURN: + * The interrupt coalescing value set in the gigE port. + * + *******************************************************************************/ +#if 0 /* FIXME */ +static unsigned int eth_port_set_rx_coal (ETH_PORT eth_port_num, + unsigned int t_clk, + unsigned int delay) +{ + unsigned int coal; + + coal = ((t_clk / 1000000) * delay) / 64; + /* Set RX Coalescing mechanism */ + MV_REG_WRITE (MV64460_ETH_SDMA_CONFIG_REG (eth_port_num), + ((coal & 0x3fff) << 8) | + (MV_REG_READ + (MV64460_ETH_SDMA_CONFIG_REG (eth_port_num)) + & 0xffc000ff)); + return coal; +} + +#endif +/******************************************************************************* + * eth_port_set_tx_coal - Sets coalescing interrupt mechanism on TX path + * + * DESCRIPTION: + * This routine sets the TX coalescing interrupt mechanism parameter. + * This parameter is a timeout counter, that counts in 64 t_clk + * chunks ; that when timeout event occurs a maskable interrupt + * occurs. + * The parameter is calculated using the t_cLK frequency of the + * MV-643xx chip and the required delay in the interrupt in uSec + * + * INPUT: + * ETH_PORT eth_port_num Ethernet port number + * unsigned int t_clk t_clk of the MV-643xx chip in HZ units + * unsigned int delay Delay in uSeconds + * + * OUTPUT: + * Interrupt coalescing mechanism value is set in MV-643xx chip. + * + * RETURN: + * The interrupt coalescing value set in the gigE port. + * + *******************************************************************************/ +#if 0 /* FIXME */ +static unsigned int eth_port_set_tx_coal (ETH_PORT eth_port_num, + unsigned int t_clk, + unsigned int delay) +{ + unsigned int coal; + + coal = ((t_clk / 1000000) * delay) / 64; + /* Set TX Coalescing mechanism */ + MV_REG_WRITE (MV64460_ETH_TX_FIFO_URGENT_THRESHOLD_REG (eth_port_num), + coal << 4); + return coal; +} +#endif + +/******************************************************************************* + * eth_b_copy - Copy bytes from source to destination + * + * DESCRIPTION: + * This function supports the eight bytes limitation on Tx buffer size. + * The routine will zero eight bytes starting from the destination address + * followed by copying bytes from the source address to the destination. + * + * INPUT: + * unsigned int src_addr 32 bit source address. + * unsigned int dst_addr 32 bit destination address. + * int byte_count Number of bytes to copy. + * + * OUTPUT: + * See description. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void eth_b_copy (unsigned int src_addr, unsigned int dst_addr, + int byte_count) +{ + /* Zero the dst_addr area */ + *(unsigned int *) dst_addr = 0x0; + + while (byte_count != 0) { + *(char *) dst_addr = *(char *) src_addr; + dst_addr++; + src_addr++; + byte_count--; + } +} diff --git a/board/prodrive/p3mx/mv_eth.h b/board/prodrive/p3mx/mv_eth.h new file mode 100644 index 0000000000..334b049ec5 --- /dev/null +++ b/board/prodrive/p3mx/mv_eth.h @@ -0,0 +1,840 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus + * + * based on - Driver for MV64460X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + * + * 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 + */ + +/* + * mv_eth.h - header file for the polled mode GT ethernet driver + */ + +#ifndef __DB64460_ETH_H__ +#define __DB64460_ETH_H__ + +#include +#include +#include +#include +#include +#include "mv_regs.h" +#include "ppc_error_no.h" +#include "../../Marvell/include/core.h" + +/************************************************************************* +************************************************************************** +************************************************************************** +* The first part is the high level driver of the gigE ethernet ports. * +************************************************************************** +************************************************************************** +*************************************************************************/ +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* In case not using SG on Tx, define MAX_SKB_FRAGS as 0 */ +#ifndef MAX_SKB_FRAGS +#define MAX_SKB_FRAGS 0 +#endif + +/* Port attributes */ +/*#define MAX_RX_QUEUE_NUM 8*/ +/*#define MAX_TX_QUEUE_NUM 8*/ +#define MAX_RX_QUEUE_NUM 1 +#define MAX_TX_QUEUE_NUM 1 + + +/* Use one TX queue and one RX queue */ +#define MV64460_TX_QUEUE_NUM 1 +#define MV64460_RX_QUEUE_NUM 1 + +/* + * Number of RX / TX descriptors on RX / TX rings. + * Note that allocating RX descriptors is done by allocating the RX + * ring AND a preallocated RX buffers (skb's) for each descriptor. + * The TX descriptors only allocates the TX descriptors ring, + * with no pre allocated TX buffers (skb's are allocated by higher layers. + */ + +/* Default TX ring size is 10 descriptors */ +#ifdef CONFIG_MV64460_ETH_TXQUEUE_SIZE +#define MV64460_TX_QUEUE_SIZE CONFIG_MV64460_ETH_TXQUEUE_SIZE +#else +#define MV64460_TX_QUEUE_SIZE 4 +#endif + +/* Default RX ring size is 4 descriptors */ +#ifdef CONFIG_MV64460_ETH_RXQUEUE_SIZE +#define MV64460_RX_QUEUE_SIZE CONFIG_MV64460_ETH_RXQUEUE_SIZE +#else +#define MV64460_RX_QUEUE_SIZE 4 +#endif + +#ifdef CONFIG_RX_BUFFER_SIZE +#define MV64460_RX_BUFFER_SIZE CONFIG_RX_BUFFER_SIZE +#else +#define MV64460_RX_BUFFER_SIZE 1600 +#endif + +#ifdef CONFIG_TX_BUFFER_SIZE +#define MV64460_TX_BUFFER_SIZE CONFIG_TX_BUFFER_SIZE +#else +#define MV64460_TX_BUFFER_SIZE 1600 +#endif + +/* + * Network device statistics. Akin to the 2.0 ether stats but + * with byte counters. + */ + +struct net_device_stats +{ + unsigned long rx_packets; /* total packets received */ + unsigned long tx_packets; /* total packets transmitted */ + unsigned long rx_bytes; /* total bytes received */ + unsigned long tx_bytes; /* total bytes transmitted */ + unsigned long rx_errors; /* bad packets received */ + unsigned long tx_errors; /* packet transmit problems */ + unsigned long rx_dropped; /* no space in linux buffers */ + unsigned long tx_dropped; /* no space available in linux */ + unsigned long multicast; /* multicast packets received */ + unsigned long collisions; + + /* detailed rx_errors: */ + unsigned long rx_length_errors; + unsigned long rx_over_errors; /* receiver ring buff overflow */ + unsigned long rx_crc_errors; /* recved pkt with crc error */ + unsigned long rx_frame_errors; /* recv'd frame alignment error */ + unsigned long rx_fifo_errors; /* recv'r fifo overrun */ + unsigned long rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + unsigned long tx_aborted_errors; + unsigned long tx_carrier_errors; + unsigned long tx_fifo_errors; + unsigned long tx_heartbeat_errors; + unsigned long tx_window_errors; + + /* for cslip etc */ + unsigned long rx_compressed; + unsigned long tx_compressed; +}; + + +/* Private data structure used for ethernet device */ +struct mv64460_eth_priv { + unsigned int port_num; + struct net_device_stats *stats; + + /* to buffer area aligned */ + char * p_eth_tx_buffer[MV64460_TX_QUEUE_SIZE+1]; /*pointers to alligned tx buffs in memory space */ + char * p_eth_rx_buffer[MV64460_RX_QUEUE_SIZE+1]; /*pointers to allinged rx buffs in memory space */ + + /* Size of Tx Ring per queue */ + unsigned int tx_ring_size [MAX_TX_QUEUE_NUM]; + + /* Size of Rx Ring per queue */ + unsigned int rx_ring_size [MAX_RX_QUEUE_NUM]; + + /* Magic Number for Ethernet running */ + unsigned int eth_running; + + int first_init; +}; + +int mv64460_eth_init (struct eth_device *dev); +int mv64460_eth_stop (struct eth_device *dev); +int mv64460_eth_start_xmit (struct eth_device*, volatile void* packet, int length); +/* return db64460_eth0_poll(); */ + +int mv64460_eth_open (struct eth_device *dev); + + +/************************************************************************* +************************************************************************** +************************************************************************** +* The second part is the low level driver of the gigE ethernet ports. * +************************************************************************** +************************************************************************** +*************************************************************************/ + + +/******************************************************************************** + * Header File for : MV-643xx network interface header + * + * DESCRIPTION: + * This header file contains macros typedefs and function declaration for + * the Marvell Gig Bit Ethernet Controller. + * + * DEPENDENCIES: + * None. + * + *******************************************************************************/ + + +#ifdef CONFIG_SPECIAL_CONSISTENT_MEMORY +#ifdef CONFIG_MV64460_SRAM_CACHEABLE +/* In case SRAM is cacheable but not cache coherent */ +#define D_CACHE_FLUSH_LINE(addr, offset) \ +{ \ + __asm__ __volatile__ ("dcbf %0,%1" : : "r" (addr), "r" (offset)); \ +} +#else +/* In case SRAM is cache coherent or non-cacheable */ +#define D_CACHE_FLUSH_LINE(addr, offset) ; +#endif +#else +#ifdef CONFIG_NOT_COHERENT_CACHE +/* In case of descriptors on DDR but not cache coherent */ +#define D_CACHE_FLUSH_LINE(addr, offset) \ +{ \ + __asm__ __volatile__ ("dcbf %0,%1" : : "r" (addr), "r" (offset)); \ +} +#else +/* In case of descriptors on DDR and cache coherent */ +#define D_CACHE_FLUSH_LINE(addr, offset) ; +#endif /* CONFIG_NOT_COHERENT_CACHE */ +#endif /* CONFIG_SPECIAL_CONSISTENT_MEMORY */ + + +#define CPU_PIPE_FLUSH \ +{ \ + __asm__ __volatile__ ("eieio"); \ +} + + +/* defines */ + +/* Default port configuration value */ +#define PORT_CONFIG_VALUE \ + ETH_UNICAST_NORMAL_MODE | \ + ETH_DEFAULT_RX_QUEUE_0 | \ + ETH_DEFAULT_RX_ARP_QUEUE_0 | \ + ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \ + ETH_RECEIVE_BC_IF_IP | \ + ETH_RECEIVE_BC_IF_ARP | \ + ETH_CAPTURE_TCP_FRAMES_DIS | \ + ETH_CAPTURE_UDP_FRAMES_DIS | \ + ETH_DEFAULT_RX_TCP_QUEUE_0 | \ + ETH_DEFAULT_RX_UDP_QUEUE_0 | \ + ETH_DEFAULT_RX_BPDU_QUEUE_0 + +/* Default port extend configuration value */ +#define PORT_CONFIG_EXTEND_VALUE \ + ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \ + ETH_PARTITION_DISABLE + + +/* Default sdma control value */ +#ifdef CONFIG_NOT_COHERENT_CACHE +#define PORT_SDMA_CONFIG_VALUE \ + ETH_RX_BURST_SIZE_16_64BIT | \ + GT_ETH_IPG_INT_RX(0) | \ + ETH_TX_BURST_SIZE_16_64BIT; +#else +#define PORT_SDMA_CONFIG_VALUE \ + ETH_RX_BURST_SIZE_4_64BIT | \ + GT_ETH_IPG_INT_RX(0) | \ + ETH_TX_BURST_SIZE_4_64BIT; +#endif + +#define GT_ETH_IPG_INT_RX(value) \ + ((value & 0x3fff) << 8) + +/* Default port serial control value */ +#define PORT_SERIAL_CONTROL_VALUE \ + ETH_FORCE_LINK_PASS | \ + ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \ + ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \ + ETH_ADV_SYMMETRIC_FLOW_CTRL | \ + ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \ + ETH_FORCE_BP_MODE_NO_JAM | \ + BIT9 | \ + ETH_DO_NOT_FORCE_LINK_FAIL | \ + ETH_RETRANSMIT_16_ETTEMPTS | \ + ETH_ENABLE_AUTO_NEG_SPEED_GMII | \ + ETH_DTE_ADV_0 | \ + ETH_DISABLE_AUTO_NEG_BYPASS | \ + ETH_AUTO_NEG_NO_CHANGE | \ + ETH_MAX_RX_PACKET_1552BYTE | \ + ETH_CLR_EXT_LOOPBACK | \ + ETH_SET_FULL_DUPLEX_MODE | \ + ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX; + +#define RX_BUFFER_MAX_SIZE 0xFFFF +#define TX_BUFFER_MAX_SIZE 0xFFFF /* Buffer are limited to 64k */ + +#define RX_BUFFER_MIN_SIZE 0x8 +#define TX_BUFFER_MIN_SIZE 0x8 + +/* Tx WRR confoguration macros */ +#define PORT_MAX_TRAN_UNIT 0x24 /* MTU register (default) 9KByte */ +#define PORT_MAX_TOKEN_BUCKET_SIZE 0x_fFFF /* PMTBS register (default) */ +#define PORT_TOKEN_RATE 1023 /* PTTBRC register (default) */ + +/* MAC accepet/reject macros */ +#define ACCEPT_MAC_ADDR 0 +#define REJECT_MAC_ADDR 1 + +/* Size of a Tx/Rx descriptor used in chain list data structure */ +#define RX_DESC_ALIGNED_SIZE 0x20 +#define TX_DESC_ALIGNED_SIZE 0x20 + +/* An offest in Tx descriptors to store data for buffers less than 8 Bytes */ +#define TX_BUF_OFFSET_IN_DESC 0x18 +/* Buffer offset from buffer pointer */ +#define RX_BUF_OFFSET 0x2 + +/* Gap define */ +#define ETH_BAR_GAP 0x8 +#define ETH_SIZE_REG_GAP 0x8 +#define ETH_HIGH_ADDR_REMAP_REG_GAP 0x4 +#define ETH_PORT_ACCESS_CTRL_GAP 0x4 + +/* Gigabit Ethernet Unit Global Registers */ + +/* MIB Counters register definitions */ +#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW 0x0 +#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH 0x4 +#define ETH_MIB_BAD_OCTETS_RECEIVED 0x8 +#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR 0xc +#define ETH_MIB_GOOD_FRAMES_RECEIVED 0x10 +#define ETH_MIB_BAD_FRAMES_RECEIVED 0x14 +#define ETH_MIB_BROADCAST_FRAMES_RECEIVED 0x18 +#define ETH_MIB_MULTICAST_FRAMES_RECEIVED 0x1c +#define ETH_MIB_FRAMES_64_OCTETS 0x20 +#define ETH_MIB_FRAMES_65_TO_127_OCTETS 0x24 +#define ETH_MIB_FRAMES_128_TO_255_OCTETS 0x28 +#define ETH_MIB_FRAMES_256_TO_511_OCTETS 0x2c +#define ETH_MIB_FRAMES_512_TO_1023_OCTETS 0x30 +#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS 0x34 +#define ETH_MIB_GOOD_OCTETS_SENT_LOW 0x38 +#define ETH_MIB_GOOD_OCTETS_SENT_HIGH 0x3c +#define ETH_MIB_GOOD_FRAMES_SENT 0x40 +#define ETH_MIB_EXCESSIVE_COLLISION 0x44 +#define ETH_MIB_MULTICAST_FRAMES_SENT 0x48 +#define ETH_MIB_BROADCAST_FRAMES_SENT 0x4c +#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50 +#define ETH_MIB_FC_SENT 0x54 +#define ETH_MIB_GOOD_FC_RECEIVED 0x58 +#define ETH_MIB_BAD_FC_RECEIVED 0x5c +#define ETH_MIB_UNDERSIZE_RECEIVED 0x60 +#define ETH_MIB_FRAGMENTS_RECEIVED 0x64 +#define ETH_MIB_OVERSIZE_RECEIVED 0x68 +#define ETH_MIB_JABBER_RECEIVED 0x6c +#define ETH_MIB_MAC_RECEIVE_ERROR 0x70 +#define ETH_MIB_BAD_CRC_EVENT 0x74 +#define ETH_MIB_COLLISION 0x78 +#define ETH_MIB_LATE_COLLISION 0x7c + +/* Port serial status reg (PSR) */ +#define ETH_INTERFACE_GMII_MII 0 +#define ETH_INTERFACE_PCM BIT0 +#define ETH_LINK_IS_DOWN 0 +#define ETH_LINK_IS_UP BIT1 +#define ETH_PORT_AT_HALF_DUPLEX 0 +#define ETH_PORT_AT_FULL_DUPLEX BIT2 +#define ETH_RX_FLOW_CTRL_DISABLED 0 +#define ETH_RX_FLOW_CTRL_ENBALED BIT3 +#define ETH_GMII_SPEED_100_10 0 +#define ETH_GMII_SPEED_1000 BIT4 +#define ETH_MII_SPEED_10 0 +#define ETH_MII_SPEED_100 BIT5 +#define ETH_NO_TX 0 +#define ETH_TX_IN_PROGRESS BIT7 +#define ETH_BYPASS_NO_ACTIVE 0 +#define ETH_BYPASS_ACTIVE BIT8 +#define ETH_PORT_NOT_AT_PARTITION_STATE 0 +#define ETH_PORT_AT_PARTITION_STATE BIT9 +#define ETH_PORT_TX_FIFO_NOT_EMPTY 0 +#define ETH_PORT_TX_FIFO_EMPTY BIT10 + + +/* These macros describes the Port configuration reg (Px_cR) bits */ +#define ETH_UNICAST_NORMAL_MODE 0 +#define ETH_UNICAST_PROMISCUOUS_MODE BIT0 +#define ETH_DEFAULT_RX_QUEUE_0 0 +#define ETH_DEFAULT_RX_QUEUE_1 BIT1 +#define ETH_DEFAULT_RX_QUEUE_2 BIT2 +#define ETH_DEFAULT_RX_QUEUE_3 (BIT2 | BIT1) +#define ETH_DEFAULT_RX_QUEUE_4 BIT3 +#define ETH_DEFAULT_RX_QUEUE_5 (BIT3 | BIT1) +#define ETH_DEFAULT_RX_QUEUE_6 (BIT3 | BIT2) +#define ETH_DEFAULT_RX_QUEUE_7 (BIT3 | BIT2 | BIT1) +#define ETH_DEFAULT_RX_ARP_QUEUE_0 0 +#define ETH_DEFAULT_RX_ARP_QUEUE_1 BIT4 +#define ETH_DEFAULT_RX_ARP_QUEUE_2 BIT5 +#define ETH_DEFAULT_RX_ARP_QUEUE_3 (BIT5 | BIT4) +#define ETH_DEFAULT_RX_ARP_QUEUE_4 BIT6 +#define ETH_DEFAULT_RX_ARP_QUEUE_5 (BIT6 | BIT4) +#define ETH_DEFAULT_RX_ARP_QUEUE_6 (BIT6 | BIT5) +#define ETH_DEFAULT_RX_ARP_QUEUE_7 (BIT6 | BIT5 | BIT4) +#define ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP 0 +#define ETH_REJECT_BC_IF_NOT_IP_OR_ARP BIT7 +#define ETH_RECEIVE_BC_IF_IP 0 +#define ETH_REJECT_BC_IF_IP BIT8 +#define ETH_RECEIVE_BC_IF_ARP 0 +#define ETH_REJECT_BC_IF_ARP BIT9 +#define ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY BIT12 +#define ETH_CAPTURE_TCP_FRAMES_DIS 0 +#define ETH_CAPTURE_TCP_FRAMES_EN BIT14 +#define ETH_CAPTURE_UDP_FRAMES_DIS 0 +#define ETH_CAPTURE_UDP_FRAMES_EN BIT15 +#define ETH_DEFAULT_RX_TCP_QUEUE_0 0 +#define ETH_DEFAULT_RX_TCP_QUEUE_1 BIT16 +#define ETH_DEFAULT_RX_TCP_QUEUE_2 BIT17 +#define ETH_DEFAULT_RX_TCP_QUEUE_3 (BIT17 | BIT16) +#define ETH_DEFAULT_RX_TCP_QUEUE_4 BIT18 +#define ETH_DEFAULT_RX_TCP_QUEUE_5 (BIT18 | BIT16) +#define ETH_DEFAULT_RX_TCP_QUEUE_6 (BIT18 | BIT17) +#define ETH_DEFAULT_RX_TCP_QUEUE_7 (BIT18 | BIT17 | BIT16) +#define ETH_DEFAULT_RX_UDP_QUEUE_0 0 +#define ETH_DEFAULT_RX_UDP_QUEUE_1 BIT19 +#define ETH_DEFAULT_RX_UDP_QUEUE_2 BIT20 +#define ETH_DEFAULT_RX_UDP_QUEUE_3 (BIT20 | BIT19) +#define ETH_DEFAULT_RX_UDP_QUEUE_4 (BIT21 +#define ETH_DEFAULT_RX_UDP_QUEUE_5 (BIT21 | BIT19) +#define ETH_DEFAULT_RX_UDP_QUEUE_6 (BIT21 | BIT20) +#define ETH_DEFAULT_RX_UDP_QUEUE_7 (BIT21 | BIT20 | BIT19) +#define ETH_DEFAULT_RX_BPDU_QUEUE_0 0 +#define ETH_DEFAULT_RX_BPDU_QUEUE_1 BIT22 +#define ETH_DEFAULT_RX_BPDU_QUEUE_2 BIT23 +#define ETH_DEFAULT_RX_BPDU_QUEUE_3 (BIT23 | BIT22) +#define ETH_DEFAULT_RX_BPDU_QUEUE_4 BIT24 +#define ETH_DEFAULT_RX_BPDU_QUEUE_5 (BIT24 | BIT22) +#define ETH_DEFAULT_RX_BPDU_QUEUE_6 (BIT24 | BIT23) +#define ETH_DEFAULT_RX_BPDU_QUEUE_7 (BIT24 | BIT23 | BIT22) + + +/* These macros describes the Port configuration extend reg (Px_cXR) bits*/ +#define ETH_CLASSIFY_EN BIT0 +#define ETH_SPAN_BPDU_PACKETS_AS_NORMAL 0 +#define ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7 BIT1 +#define ETH_PARTITION_DISABLE 0 +#define ETH_PARTITION_ENABLE BIT2 + + +/* Tx/Rx queue command reg (RQCR/TQCR)*/ +#define ETH_QUEUE_0_ENABLE BIT0 +#define ETH_QUEUE_1_ENABLE BIT1 +#define ETH_QUEUE_2_ENABLE BIT2 +#define ETH_QUEUE_3_ENABLE BIT3 +#define ETH_QUEUE_4_ENABLE BIT4 +#define ETH_QUEUE_5_ENABLE BIT5 +#define ETH_QUEUE_6_ENABLE BIT6 +#define ETH_QUEUE_7_ENABLE BIT7 +#define ETH_QUEUE_0_DISABLE BIT8 +#define ETH_QUEUE_1_DISABLE BIT9 +#define ETH_QUEUE_2_DISABLE BIT10 +#define ETH_QUEUE_3_DISABLE BIT11 +#define ETH_QUEUE_4_DISABLE BIT12 +#define ETH_QUEUE_5_DISABLE BIT13 +#define ETH_QUEUE_6_DISABLE BIT14 +#define ETH_QUEUE_7_DISABLE BIT15 + +/* These macros describes the Port Sdma configuration reg (SDCR) bits */ +#define ETH_RIFB BIT0 +#define ETH_RX_BURST_SIZE_1_64BIT 0 +#define ETH_RX_BURST_SIZE_2_64BIT BIT1 +#define ETH_RX_BURST_SIZE_4_64BIT BIT2 +#define ETH_RX_BURST_SIZE_8_64BIT (BIT2 | BIT1) +#define ETH_RX_BURST_SIZE_16_64BIT BIT3 +#define ETH_BLM_RX_NO_SWAP BIT4 +#define ETH_BLM_RX_BYTE_SWAP 0 +#define ETH_BLM_TX_NO_SWAP BIT5 +#define ETH_BLM_TX_BYTE_SWAP 0 +#define ETH_DESCRIPTORS_BYTE_SWAP BIT6 +#define ETH_DESCRIPTORS_NO_SWAP 0 +#define ETH_TX_BURST_SIZE_1_64BIT 0 +#define ETH_TX_BURST_SIZE_2_64BIT BIT22 +#define ETH_TX_BURST_SIZE_4_64BIT BIT23 +#define ETH_TX_BURST_SIZE_8_64BIT (BIT23 | BIT22) +#define ETH_TX_BURST_SIZE_16_64BIT BIT24 + +/* These macros describes the Port serial control reg (PSCR) bits */ +#define ETH_SERIAL_PORT_DISABLE 0 +#define ETH_SERIAL_PORT_ENABLE BIT0 +#define ETH_FORCE_LINK_PASS BIT1 +#define ETH_DO_NOT_FORCE_LINK_PASS 0 +#define ETH_ENABLE_AUTO_NEG_FOR_DUPLX 0 +#define ETH_DISABLE_AUTO_NEG_FOR_DUPLX BIT2 +#define ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL 0 +#define ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL BIT3 +#define ETH_ADV_NO_FLOW_CTRL 0 +#define ETH_ADV_SYMMETRIC_FLOW_CTRL BIT4 +#define ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX 0 +#define ETH_FORCE_FC_MODE_TX_PAUSE_DIS BIT5 +#define ETH_FORCE_BP_MODE_NO_JAM 0 +#define ETH_FORCE_BP_MODE_JAM_TX BIT7 +#define ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR BIT8 +#define ETH_FORCE_LINK_FAIL 0 +#define ETH_DO_NOT_FORCE_LINK_FAIL BIT10 +#define ETH_RETRANSMIT_16_ETTEMPTS 0 +#define ETH_RETRANSMIT_FOREVER BIT11 +#define ETH_DISABLE_AUTO_NEG_SPEED_GMII BIT13 +#define ETH_ENABLE_AUTO_NEG_SPEED_GMII 0 +#define ETH_DTE_ADV_0 0 +#define ETH_DTE_ADV_1 BIT14 +#define ETH_DISABLE_AUTO_NEG_BYPASS 0 +#define ETH_ENABLE_AUTO_NEG_BYPASS BIT15 +#define ETH_AUTO_NEG_NO_CHANGE 0 +#define ETH_RESTART_AUTO_NEG BIT16 +#define ETH_MAX_RX_PACKET_1518BYTE 0 +#define ETH_MAX_RX_PACKET_1522BYTE BIT17 +#define ETH_MAX_RX_PACKET_1552BYTE BIT18 +#define ETH_MAX_RX_PACKET_9022BYTE (BIT18 | BIT17) +#define ETH_MAX_RX_PACKET_9192BYTE BIT19 +#define ETH_MAX_RX_PACKET_9700BYTE (BIT19 | BIT17) +#define ETH_SET_EXT_LOOPBACK BIT20 +#define ETH_CLR_EXT_LOOPBACK 0 +#define ETH_SET_FULL_DUPLEX_MODE BIT21 +#define ETH_SET_HALF_DUPLEX_MODE 0 +#define ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX BIT22 +#define ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX 0 +#define ETH_SET_GMII_SPEED_TO_10_100 0 +#define ETH_SET_GMII_SPEED_TO_1000 BIT23 +#define ETH_SET_MII_SPEED_TO_10 0 +#define ETH_SET_MII_SPEED_TO_100 BIT24 + + +/* SMI reg */ +#define ETH_SMI_BUSY BIT28 /* 0 - Write, 1 - Read */ +#define ETH_SMI_READ_VALID BIT27 /* 0 - Write, 1 - Read */ +#define ETH_SMI_OPCODE_WRITE 0 /* Completion of Read operation */ +#define ETH_SMI_OPCODE_READ BIT26 /* Operation is in progress */ + +/* SDMA command status fields macros */ + +/* Tx & Rx descriptors status */ +#define ETH_ERROR_SUMMARY (BIT0) + +/* Tx & Rx descriptors command */ +#define ETH_BUFFER_OWNED_BY_DMA (BIT31) + +/* Tx descriptors status */ +#define ETH_LC_ERROR (0 ) +#define ETH_UR_ERROR (BIT1 ) +#define ETH_RL_ERROR (BIT2 ) +#define ETH_LLC_SNAP_FORMAT (BIT9 ) + +/* Rx descriptors status */ +#define ETH_CRC_ERROR (0 ) +#define ETH_OVERRUN_ERROR (BIT1 ) +#define ETH_MAX_FRAME_LENGTH_ERROR (BIT2 ) +#define ETH_RESOURCE_ERROR ((BIT2 | BIT1)) +#define ETH_VLAN_TAGGED (BIT19) +#define ETH_BPDU_FRAME (BIT20) +#define ETH_TCP_FRAME_OVER_IP_V_4 (0 ) +#define ETH_UDP_FRAME_OVER_IP_V_4 (BIT21) +#define ETH_OTHER_FRAME_TYPE (BIT22) +#define ETH_LAYER_2_IS_ETH_V_2 (BIT23) +#define ETH_FRAME_TYPE_IP_V_4 (BIT24) +#define ETH_FRAME_HEADER_OK (BIT25) +#define ETH_RX_LAST_DESC (BIT26) +#define ETH_RX_FIRST_DESC (BIT27) +#define ETH_UNKNOWN_DESTINATION_ADDR (BIT28) +#define ETH_RX_ENABLE_INTERRUPT (BIT29) +#define ETH_LAYER_4_CHECKSUM_OK (BIT30) + +/* Rx descriptors byte count */ +#define ETH_FRAME_FRAGMENTED (BIT2) + +/* Tx descriptors command */ +#define ETH_LAYER_4_CHECKSUM_FIRST_DESC (BIT10) +#define ETH_FRAME_SET_TO_VLAN (BIT15) +#define ETH_TCP_FRAME (0 ) +#define ETH_UDP_FRAME (BIT16) +#define ETH_GEN_TCP_UDP_CHECKSUM (BIT17) +#define ETH_GEN_IP_V_4_CHECKSUM (BIT18) +#define ETH_ZERO_PADDING (BIT19) +#define ETH_TX_LAST_DESC (BIT20) +#define ETH_TX_FIRST_DESC (BIT21) +#define ETH_GEN_CRC (BIT22) +#define ETH_TX_ENABLE_INTERRUPT (BIT23) +#define ETH_AUTO_MODE (BIT30) + +/* Address decode parameters */ +/* Ethernet Base Address Register bits */ +#define EBAR_TARGET_DRAM 0x00000000 +#define EBAR_TARGET_DEVICE 0x00000001 +#define EBAR_TARGET_CBS 0x00000002 +#define EBAR_TARGET_PCI0 0x00000003 +#define EBAR_TARGET_PCI1 0x00000004 +#define EBAR_TARGET_CUNIT 0x00000005 +#define EBAR_TARGET_AUNIT 0x00000006 +#define EBAR_TARGET_GUNIT 0x00000007 + +/* Window attributes */ +#define EBAR_ATTR_DRAM_CS0 0x00000E00 +#define EBAR_ATTR_DRAM_CS1 0x00000D00 +#define EBAR_ATTR_DRAM_CS2 0x00000B00 +#define EBAR_ATTR_DRAM_CS3 0x00000700 + +/* DRAM Target interface */ +#define EBAR_ATTR_DRAM_NO_CACHE_COHERENCY 0x00000000 +#define EBAR_ATTR_DRAM_CACHE_COHERENCY_WT 0x00001000 +#define EBAR_ATTR_DRAM_CACHE_COHERENCY_WB 0x00002000 + +/* Device Bus Target interface */ +#define EBAR_ATTR_DEVICE_DEVCS0 0x00001E00 +#define EBAR_ATTR_DEVICE_DEVCS1 0x00001D00 +#define EBAR_ATTR_DEVICE_DEVCS2 0x00001B00 +#define EBAR_ATTR_DEVICE_DEVCS3 0x00001700 +#define EBAR_ATTR_DEVICE_BOOTCS3 0x00000F00 + +/* PCI Target interface */ +#define EBAR_ATTR_PCI_BYTE_SWAP 0x00000000 +#define EBAR_ATTR_PCI_NO_SWAP 0x00000100 +#define EBAR_ATTR_PCI_BYTE_WORD_SWAP 0x00000200 +#define EBAR_ATTR_PCI_WORD_SWAP 0x00000300 +#define EBAR_ATTR_PCI_NO_SNOOP_NOT_ASSERT 0x00000000 +#define EBAR_ATTR_PCI_NO_SNOOP_ASSERT 0x00000400 +#define EBAR_ATTR_PCI_IO_SPACE 0x00000000 +#define EBAR_ATTR_PCI_MEMORY_SPACE 0x00000800 +#define EBAR_ATTR_PCI_REQ64_FORCE 0x00000000 +#define EBAR_ATTR_PCI_REQ64_SIZE 0x00001000 + +/* CPU 60x bus or internal SRAM interface */ +#define EBAR_ATTR_CBS_SRAM_BLOCK0 0x00000000 +#define EBAR_ATTR_CBS_SRAM_BLOCK1 0x00000100 +#define EBAR_ATTR_CBS_SRAM 0x00000000 +#define EBAR_ATTR_CBS_CPU_BUS 0x00000800 + +/* Window access control */ +#define EWIN_ACCESS_NOT_ALLOWED 0 +#define EWIN_ACCESS_READ_ONLY BIT0 +#define EWIN_ACCESS_FULL (BIT1 | BIT0) +#define EWIN0_ACCESS_MASK 0x0003 +#define EWIN1_ACCESS_MASK 0x000C +#define EWIN2_ACCESS_MASK 0x0030 +#define EWIN3_ACCESS_MASK 0x00C0 + +/* typedefs */ + +typedef enum _eth_port +{ + ETH_0 = 0, + ETH_1 = 1, + ETH_2 = 2 +}ETH_PORT; + +typedef enum _eth_func_ret_status +{ + ETH_OK, /* Returned as expected. */ + ETH_ERROR, /* Fundamental error. */ + ETH_RETRY, /* Could not process request. Try later. */ + ETH_END_OF_JOB, /* Ring has nothing to process. */ + ETH_QUEUE_FULL, /* Ring resource error. */ + ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */ +}ETH_FUNC_RET_STATUS; + +typedef enum _eth_queue +{ + ETH_Q0 = 0, + ETH_Q1 = 1, + ETH_Q2 = 2, + ETH_Q3 = 3, + ETH_Q4 = 4, + ETH_Q5 = 5, + ETH_Q6 = 6, + ETH_Q7 = 7 +} ETH_QUEUE; + +typedef enum _addr_win +{ + ETH_WIN0, + ETH_WIN1, + ETH_WIN2, + ETH_WIN3, + ETH_WIN4, + ETH_WIN5 +} ETH_ADDR_WIN; + +typedef enum _eth_target +{ + ETH_TARGET_DRAM , + ETH_TARGET_DEVICE, + ETH_TARGET_CBS , + ETH_TARGET_PCI0 , + ETH_TARGET_PCI1 +}ETH_TARGET; + +typedef struct _eth_rx_desc +{ + unsigned short byte_cnt ; /* Descriptor buffer byte count */ + unsigned short buf_size ; /* Buffer size */ + unsigned int cmd_sts ; /* Descriptor command status */ + unsigned int next_desc_ptr; /* Next descriptor pointer */ + unsigned int buf_ptr ; /* Descriptor buffer pointer */ + unsigned int return_info ; /* User resource return information */ +} ETH_RX_DESC; + + +typedef struct _eth_tx_desc +{ + unsigned short byte_cnt ; /* Descriptor buffer byte count */ + unsigned short l4i_chk ; /* CPU provided TCP Checksum */ + unsigned int cmd_sts ; /* Descriptor command status */ + unsigned int next_desc_ptr; /* Next descriptor pointer */ + unsigned int buf_ptr ; /* Descriptor buffer pointer */ + unsigned int return_info ; /* User resource return information */ +} ETH_TX_DESC; + +/* Unified struct for Rx and Tx operations. The user is not required to */ +/* be familier with neither Tx nor Rx descriptors. */ +typedef struct _pkt_info +{ + unsigned short byte_cnt ; /* Descriptor buffer byte count */ + unsigned short l4i_chk ; /* Tx CPU provided TCP Checksum */ + unsigned int cmd_sts ; /* Descriptor command status */ + unsigned int buf_ptr ; /* Descriptor buffer pointer */ + unsigned int return_info ; /* User resource return information */ +} PKT_INFO; + + +typedef struct _eth_win_param +{ + ETH_ADDR_WIN win; /* Window number. See ETH_ADDR_WIN enum */ + ETH_TARGET target; /* System targets. See ETH_TARGET enum */ + unsigned short attributes; /* BAR attributes. See above macros. */ + unsigned int base_addr; /* Window base address in unsigned int form */ + unsigned int high_addr; /* Window high address in unsigned int form */ + unsigned int size; /* Size in MBytes. Must be % 64Kbyte. */ + bool enable; /* Enable/disable access to the window. */ + unsigned short access_ctrl; /* Access ctrl register. see above macros */ +} ETH_WIN_PARAM; + + +/* Ethernet port specific infomation */ + +typedef struct _eth_port_ctrl +{ + ETH_PORT port_num; /* User Ethernet port number */ + int port_phy_addr; /* User phy address of Ethrnet port */ + unsigned char port_mac_addr[6]; /* User defined port MAC address. */ + unsigned int port_config; /* User port configuration value */ + unsigned int port_config_extend; /* User port config extend value */ + unsigned int port_sdma_config; /* User port SDMA config value */ + unsigned int port_serial_control; /* User port serial control value */ + unsigned int port_tx_queue_command; /* Port active Tx queues summary */ + unsigned int port_rx_queue_command; /* Port active Rx queues summary */ + + /* User function to cast virtual address to CPU bus address */ + unsigned int (*port_virt_to_phys)(unsigned int addr); + /* User scratch pad for user specific data structures */ + void *port_private; + + bool rx_resource_err[MAX_RX_QUEUE_NUM]; /* Rx ring resource error flag */ + bool tx_resource_err[MAX_TX_QUEUE_NUM]; /* Tx ring resource error flag */ + + /* Tx/Rx rings managment indexes fields. For driver use */ + + /* Next available Rx resource */ + volatile ETH_RX_DESC *p_rx_curr_desc_q[MAX_RX_QUEUE_NUM]; + /* Returning Rx resource */ + volatile ETH_RX_DESC *p_rx_used_desc_q[MAX_RX_QUEUE_NUM]; + + /* Next available Tx resource */ + volatile ETH_TX_DESC *p_tx_curr_desc_q[MAX_TX_QUEUE_NUM]; + /* Returning Tx resource */ + volatile ETH_TX_DESC *p_tx_used_desc_q[MAX_TX_QUEUE_NUM]; + /* An extra Tx index to support transmit of multiple buffers per packet */ + volatile ETH_TX_DESC *p_tx_first_desc_q[MAX_TX_QUEUE_NUM]; + + /* Tx/Rx rings size and base variables fields. For driver use */ + + volatile ETH_RX_DESC *p_rx_desc_area_base[MAX_RX_QUEUE_NUM]; + unsigned int rx_desc_area_size[MAX_RX_QUEUE_NUM]; + char *p_rx_buffer_base[MAX_RX_QUEUE_NUM]; + + volatile ETH_TX_DESC *p_tx_desc_area_base[MAX_TX_QUEUE_NUM]; + unsigned int tx_desc_area_size[MAX_TX_QUEUE_NUM]; + char *p_tx_buffer_base[MAX_TX_QUEUE_NUM]; + +} ETH_PORT_INFO; + + +/* ethernet.h API list */ + +/* Port operation control routines */ +static void eth_port_init (ETH_PORT_INFO *p_eth_port_ctrl); +static void eth_port_reset(ETH_PORT eth_port_num); +static bool eth_port_start(ETH_PORT_INFO *p_eth_port_ctrl); + + +/* Port MAC address routines */ +static void eth_port_uc_addr_set (ETH_PORT eth_port_num, + unsigned char *p_addr, + ETH_QUEUE queue); +#if 0 /* FIXME */ +static void eth_port_mc_addr (ETH_PORT eth_port_num, + unsigned char *p_addr, + ETH_QUEUE queue, + int option); +#endif + +/* PHY and MIB routines */ +static bool ethernet_phy_reset(ETH_PORT eth_port_num); + +static bool eth_port_write_smi_reg(ETH_PORT eth_port_num, + unsigned int phy_reg, + unsigned int value); + +static bool eth_port_read_smi_reg(ETH_PORT eth_port_num, + unsigned int phy_reg, + unsigned int* value); + +static void eth_clear_mib_counters(ETH_PORT eth_port_num); + +/* Port data flow control routines */ +static ETH_FUNC_RET_STATUS eth_port_send (ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO *p_pkt_info); +static ETH_FUNC_RET_STATUS eth_tx_return_desc(ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO *p_pkt_info); +static ETH_FUNC_RET_STATUS eth_port_receive (ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO *p_pkt_info); +static ETH_FUNC_RET_STATUS eth_rx_return_buff(ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO *p_pkt_info); + + +static bool ether_init_tx_desc_ring(ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE tx_queue, + int tx_desc_num, + int tx_buff_size, + unsigned int tx_desc_base_addr, + unsigned int tx_buff_base_addr); + +static bool ether_init_rx_desc_ring(ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE rx_queue, + int rx_desc_num, + int rx_buff_size, + unsigned int rx_desc_base_addr, + unsigned int rx_buff_base_addr); + +#endif /* MV64460_ETH_ */ diff --git a/board/prodrive/p3mx/mv_regs.h b/board/prodrive/p3mx/mv_regs.h new file mode 100644 index 0000000000..068590f9d3 --- /dev/null +++ b/board/prodrive/p3mx/mv_regs.h @@ -0,0 +1,1125 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus + * + * based on - Driver for MV64460X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + * + * 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 + */ + +/******************************************************************************** +* gt64460r.h - GT-64460 Internal registers definition file. +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv_regsh +#define __INCmv_regsh + +#define MV64460 + +/* Supported by the Atlantis */ +#define MV64460_INCLUDE_PCI_1 +#define MV64460_INCLUDE_PCI_0_ARBITER +#define MV64460_INCLUDE_PCI_1_ARBITER +#define MV64460_INCLUDE_SNOOP_SUPPORT +#define MV64460_INCLUDE_P2P +#define MV64460_INCLUDE_ETH_PORT_2 +#define MV64460_INCLUDE_CPU_MAPPING +#define MV64460_INCLUDE_MPSC + +/* Not supported features */ +#undef INCLUDE_CNTMR_4_7 +#undef INCLUDE_DMA_4_7 + +/****************************************/ +/* Processor Address Space */ +/****************************************/ + +/* DDR SDRAM BAR and size registers */ + +#define MV64460_CS_0_BASE_ADDR 0x008 +#define MV64460_CS_0_SIZE 0x010 +#define MV64460_CS_1_BASE_ADDR 0x208 +#define MV64460_CS_1_SIZE 0x210 +#define MV64460_CS_2_BASE_ADDR 0x018 +#define MV64460_CS_2_SIZE 0x020 +#define MV64460_CS_3_BASE_ADDR 0x218 +#define MV64460_CS_3_SIZE 0x220 + +/* Devices BAR and size registers */ + +#define MV64460_DEV_CS0_BASE_ADDR 0x028 +#define MV64460_DEV_CS0_SIZE 0x030 +#define MV64460_DEV_CS1_BASE_ADDR 0x228 +#define MV64460_DEV_CS1_SIZE 0x230 +#define MV64460_DEV_CS2_BASE_ADDR 0x248 +#define MV64460_DEV_CS2_SIZE 0x250 +#define MV64460_DEV_CS3_BASE_ADDR 0x038 +#define MV64460_DEV_CS3_SIZE 0x040 +#define MV64460_BOOTCS_BASE_ADDR 0x238 +#define MV64460_BOOTCS_SIZE 0x240 + +/* PCI 0 BAR and size registers */ + +#define MV64460_PCI_0_IO_BASE_ADDR 0x048 +#define MV64460_PCI_0_IO_SIZE 0x050 +#define MV64460_PCI_0_MEMORY0_BASE_ADDR 0x058 +#define MV64460_PCI_0_MEMORY0_SIZE 0x060 +#define MV64460_PCI_0_MEMORY1_BASE_ADDR 0x080 +#define MV64460_PCI_0_MEMORY1_SIZE 0x088 +#define MV64460_PCI_0_MEMORY2_BASE_ADDR 0x258 +#define MV64460_PCI_0_MEMORY2_SIZE 0x260 +#define MV64460_PCI_0_MEMORY3_BASE_ADDR 0x280 +#define MV64460_PCI_0_MEMORY3_SIZE 0x288 + +/* PCI 1 BAR and size registers */ +#define MV64460_PCI_1_IO_BASE_ADDR 0x090 +#define MV64460_PCI_1_IO_SIZE 0x098 +#define MV64460_PCI_1_MEMORY0_BASE_ADDR 0x0a0 +#define MV64460_PCI_1_MEMORY0_SIZE 0x0a8 +#define MV64460_PCI_1_MEMORY1_BASE_ADDR 0x0b0 +#define MV64460_PCI_1_MEMORY1_SIZE 0x0b8 +#define MV64460_PCI_1_MEMORY2_BASE_ADDR 0x2a0 +#define MV64460_PCI_1_MEMORY2_SIZE 0x2a8 +#define MV64460_PCI_1_MEMORY3_BASE_ADDR 0x2b0 +#define MV64460_PCI_1_MEMORY3_SIZE 0x2b8 + +/* SRAM base address */ +#define MV64460_INTEGRATED_SRAM_BASE_ADDR 0x268 + +/* internal registers space base address */ +#define MV64460_INTERNAL_SPACE_BASE_ADDR 0x068 + +/* Enables the CS , DEV_CS , PCI 0 and PCI 1 + windows above */ +#define MV64460_BASE_ADDR_ENABLE 0x278 + +/****************************************/ +/* PCI remap registers */ +/****************************************/ + /* PCI 0 */ +#define MV64460_PCI_0_IO_ADDR_REMAP 0x0f0 +#define MV64460_PCI_0_MEMORY0_LOW_ADDR_REMAP 0x0f8 +#define MV64460_PCI_0_MEMORY0_HIGH_ADDR_REMAP 0x320 +#define MV64460_PCI_0_MEMORY1_LOW_ADDR_REMAP 0x100 +#define MV64460_PCI_0_MEMORY1_HIGH_ADDR_REMAP 0x328 +#define MV64460_PCI_0_MEMORY2_LOW_ADDR_REMAP 0x2f8 +#define MV64460_PCI_0_MEMORY2_HIGH_ADDR_REMAP 0x330 +#define MV64460_PCI_0_MEMORY3_LOW_ADDR_REMAP 0x300 +#define MV64460_PCI_0_MEMORY3_HIGH_ADDR_REMAP 0x338 + /* PCI 1 */ +#define MV64460_PCI_1_IO_ADDR_REMAP 0x108 +#define MV64460_PCI_1_MEMORY0_LOW_ADDR_REMAP 0x110 +#define MV64460_PCI_1_MEMORY0_HIGH_ADDR_REMAP 0x340 +#define MV64460_PCI_1_MEMORY1_LOW_ADDR_REMAP 0x118 +#define MV64460_PCI_1_MEMORY1_HIGH_ADDR_REMAP 0x348 +#define MV64460_PCI_1_MEMORY2_LOW_ADDR_REMAP 0x310 +#define MV64460_PCI_1_MEMORY2_HIGH_ADDR_REMAP 0x350 +#define MV64460_PCI_1_MEMORY3_LOW_ADDR_REMAP 0x318 +#define MV64460_PCI_1_MEMORY3_HIGH_ADDR_REMAP 0x358 + +#define MV64460_CPU_PCI_0_HEADERS_RETARGET_CONTROL 0x3b0 +#define MV64460_CPU_PCI_0_HEADERS_RETARGET_BASE 0x3b8 +#define MV64460_CPU_PCI_1_HEADERS_RETARGET_CONTROL 0x3c0 +#define MV64460_CPU_PCI_1_HEADERS_RETARGET_BASE 0x3c8 +#define MV64460_CPU_GE_HEADERS_RETARGET_CONTROL 0x3d0 +#define MV64460_CPU_GE_HEADERS_RETARGET_BASE 0x3d8 +#define MV64460_CPU_IDMA_HEADERS_RETARGET_CONTROL 0x3e0 +#define MV64460_CPU_IDMA_HEADERS_RETARGET_BASE 0x3e8 + +/****************************************/ +/* CPU Control Registers */ +/****************************************/ + +#define MV64460_CPU_CONFIG 0x000 +#define MV64460_CPU_MODE 0x120 +#define MV64460_CPU_MASTER_CONTROL 0x160 +#define MV64460_CPU_CROSS_BAR_CONTROL_LOW 0x150 +#define MV64460_CPU_CROSS_BAR_CONTROL_HIGH 0x158 +#define MV64460_CPU_CROSS_BAR_TIMEOUT 0x168 + +/****************************************/ +/* SMP RegisterS */ +/****************************************/ + +#define MV64460_SMP_WHO_AM_I 0x200 +#define MV64460_SMP_CPU0_DOORBELL 0x214 +#define MV64460_SMP_CPU0_DOORBELL_CLEAR 0x21C +#define MV64460_SMP_CPU1_DOORBELL 0x224 +#define MV64460_SMP_CPU1_DOORBELL_CLEAR 0x22C +#define MV64460_SMP_CPU0_DOORBELL_MASK 0x234 +#define MV64460_SMP_CPU1_DOORBELL_MASK 0x23C +#define MV64460_SMP_SEMAPHOR0 0x244 +#define MV64460_SMP_SEMAPHOR1 0x24c +#define MV64460_SMP_SEMAPHOR2 0x254 +#define MV64460_SMP_SEMAPHOR3 0x25c +#define MV64460_SMP_SEMAPHOR4 0x264 +#define MV64460_SMP_SEMAPHOR5 0x26c +#define MV64460_SMP_SEMAPHOR6 0x274 +#define MV64460_SMP_SEMAPHOR7 0x27c + +/****************************************/ +/* CPU Sync Barrier Register */ +/****************************************/ + +#define MV64460_CPU_0_SYNC_BARRIER_TRIGGER 0x0c0 +#define MV64460_CPU_0_SYNC_BARRIER_VIRTUAL 0x0c8 +#define MV64460_CPU_1_SYNC_BARRIER_TRIGGER 0x0d0 +#define MV64460_CPU_1_SYNC_BARRIER_VIRTUAL 0x0d8 + +/****************************************/ +/* CPU Access Protect */ +/****************************************/ + +#define MV64460_CPU_PROTECT_WINDOW_0_BASE_ADDR 0x180 +#define MV64460_CPU_PROTECT_WINDOW_0_SIZE 0x188 +#define MV64460_CPU_PROTECT_WINDOW_1_BASE_ADDR 0x190 +#define MV64460_CPU_PROTECT_WINDOW_1_SIZE 0x198 +#define MV64460_CPU_PROTECT_WINDOW_2_BASE_ADDR 0x1a0 +#define MV64460_CPU_PROTECT_WINDOW_2_SIZE 0x1a8 +#define MV64460_CPU_PROTECT_WINDOW_3_BASE_ADDR 0x1b0 +#define MV64460_CPU_PROTECT_WINDOW_3_SIZE 0x1b8 + + +/****************************************/ +/* CPU Error Report */ +/****************************************/ + +#define MV64460_CPU_ERROR_ADDR_LOW 0x070 +#define MV64460_CPU_ERROR_ADDR_HIGH 0x078 +#define MV64460_CPU_ERROR_DATA_LOW 0x128 +#define MV64460_CPU_ERROR_DATA_HIGH 0x130 +#define MV64460_CPU_ERROR_PARITY 0x138 +#define MV64460_CPU_ERROR_CAUSE 0x140 +#define MV64460_CPU_ERROR_MASK 0x148 + +/****************************************/ +/* CPU Interface Debug Registers */ +/****************************************/ + +#define MV64460_PUNIT_SLAVE_DEBUG_LOW 0x360 +#define MV64460_PUNIT_SLAVE_DEBUG_HIGH 0x368 +#define MV64460_PUNIT_MASTER_DEBUG_LOW 0x370 +#define MV64460_PUNIT_MASTER_DEBUG_HIGH 0x378 +#define MV64460_PUNIT_MMASK 0x3e4 + +/****************************************/ +/* Integrated SRAM Registers */ +/****************************************/ + +#define MV64460_SRAM_CONFIG 0x380 +#define MV64460_SRAM_TEST_MODE 0X3F4 +#define MV64460_SRAM_ERROR_CAUSE 0x388 +#define MV64460_SRAM_ERROR_ADDR 0x390 +#define MV64460_SRAM_ERROR_ADDR_HIGH 0X3F8 +#define MV64460_SRAM_ERROR_DATA_LOW 0x398 +#define MV64460_SRAM_ERROR_DATA_HIGH 0x3a0 +#define MV64460_SRAM_ERROR_DATA_PARITY 0x3a8 + +/****************************************/ +/* SDRAM Configuration */ +/****************************************/ + +#define MV64460_SDRAM_CONFIG 0x1400 +#define MV64460_D_UNIT_CONTROL_LOW 0x1404 +#define MV64460_D_UNIT_CONTROL_HIGH 0x1424 +#define MV64460_D_UNIT_MMASK 0x14B0 +#define MV64460_SDRAM_TIMING_CONTROL_LOW 0x1408 +#define MV64460_SDRAM_TIMING_CONTROL_HIGH 0x140c +#define MV64460_SDRAM_ADDR_CONTROL 0x1410 +#define MV64460_SDRAM_OPEN_PAGES_CONTROL 0x1414 +#define MV64460_SDRAM_OPERATION 0x1418 +#define MV64460_SDRAM_MODE 0x141c +#define MV64460_EXTENDED_DRAM_MODE 0x1420 +#define MV64460_SDRAM_CROSS_BAR_CONTROL_LOW 0x1430 +#define MV64460_SDRAM_CROSS_BAR_CONTROL_HIGH 0x1434 +#define MV64460_SDRAM_CROSS_BAR_TIMEOUT 0x1438 +#define MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION 0x14c0 +#define MV64460_SDRAM_DATA_PADS_CALIBRATION 0x14c4 + +/****************************************/ +/* SDRAM Error Report */ +/****************************************/ + +#define MV64460_SDRAM_ERROR_DATA_LOW 0x1444 +#define MV64460_SDRAM_ERROR_DATA_HIGH 0x1440 +#define MV64460_SDRAM_ERROR_ADDR 0x1450 +#define MV64460_SDRAM_RECEIVED_ECC 0x1448 +#define MV64460_SDRAM_CALCULATED_ECC 0x144c +#define MV64460_SDRAM_ECC_CONTROL 0x1454 +#define MV64460_SDRAM_ECC_ERROR_COUNTER 0x1458 + +/******************************************/ +/* Controlled Delay Line (CDL) Registers */ +/******************************************/ + +#define MV64460_DFCDL_CONFIG0 0x1480 +#define MV64460_DFCDL_CONFIG1 0x1484 +#define MV64460_DLL_WRITE 0x1488 +#define MV64460_DLL_READ 0x148c +#define MV64460_SRAM_ADDR 0x1490 +#define MV64460_SRAM_DATA0 0x1494 +#define MV64460_SRAM_DATA1 0x1498 +#define MV64460_SRAM_DATA2 0x149c +#define MV64460_DFCL_PROBE 0x14a0 + +/******************************************/ +/* Debug Registers */ +/******************************************/ + +#define MV64460_DUNIT_DEBUG_LOW 0x1460 +#define MV64460_DUNIT_DEBUG_HIGH 0x1464 +#define MV64460_DUNIT_MMASK 0X1b40 + +/****************************************/ +/* Device Parameters */ +/****************************************/ + +#define MV64460_DEVICE_BANK0_PARAMETERS 0x45c +#define MV64460_DEVICE_BANK1_PARAMETERS 0x460 +#define MV64460_DEVICE_BANK2_PARAMETERS 0x464 +#define MV64460_DEVICE_BANK3_PARAMETERS 0x468 +#define MV64460_DEVICE_BOOT_BANK_PARAMETERS 0x46c +#define MV64460_DEVICE_INTERFACE_CONTROL 0x4c0 +#define MV64460_DEVICE_INTERFACE_CROSS_BAR_CONTROL_LOW 0x4c8 +#define MV64460_DEVICE_INTERFACE_CROSS_BAR_CONTROL_HIGH 0x4cc +#define MV64460_DEVICE_INTERFACE_CROSS_BAR_TIMEOUT 0x4c4 + +/****************************************/ +/* Device interrupt registers */ +/****************************************/ + +#define MV64460_DEVICE_INTERRUPT_CAUSE 0x4d0 +#define MV64460_DEVICE_INTERRUPT_MASK 0x4d4 +#define MV64460_DEVICE_ERROR_ADDR 0x4d8 +#define MV64460_DEVICE_ERROR_DATA 0x4dc +#define MV64460_DEVICE_ERROR_PARITY 0x4e0 + +/****************************************/ +/* Device debug registers */ +/****************************************/ + +#define MV64460_DEVICE_DEBUG_LOW 0x4e4 +#define MV64460_DEVICE_DEBUG_HIGH 0x4e8 +#define MV64460_RUNIT_MMASK 0x4f0 + +/****************************************/ +/* PCI Slave Address Decoding registers */ +/****************************************/ + +#define MV64460_PCI_0_CS_0_BANK_SIZE 0xc08 +#define MV64460_PCI_1_CS_0_BANK_SIZE 0xc88 +#define MV64460_PCI_0_CS_1_BANK_SIZE 0xd08 +#define MV64460_PCI_1_CS_1_BANK_SIZE 0xd88 +#define MV64460_PCI_0_CS_2_BANK_SIZE 0xc0c +#define MV64460_PCI_1_CS_2_BANK_SIZE 0xc8c +#define MV64460_PCI_0_CS_3_BANK_SIZE 0xd0c +#define MV64460_PCI_1_CS_3_BANK_SIZE 0xd8c +#define MV64460_PCI_0_DEVCS_0_BANK_SIZE 0xc10 +#define MV64460_PCI_1_DEVCS_0_BANK_SIZE 0xc90 +#define MV64460_PCI_0_DEVCS_1_BANK_SIZE 0xd10 +#define MV64460_PCI_1_DEVCS_1_BANK_SIZE 0xd90 +#define MV64460_PCI_0_DEVCS_2_BANK_SIZE 0xd18 +#define MV64460_PCI_1_DEVCS_2_BANK_SIZE 0xd98 +#define MV64460_PCI_0_DEVCS_3_BANK_SIZE 0xc14 +#define MV64460_PCI_1_DEVCS_3_BANK_SIZE 0xc94 +#define MV64460_PCI_0_DEVCS_BOOT_BANK_SIZE 0xd14 +#define MV64460_PCI_1_DEVCS_BOOT_BANK_SIZE 0xd94 +#define MV64460_PCI_0_P2P_MEM0_BAR_SIZE 0xd1c +#define MV64460_PCI_1_P2P_MEM0_BAR_SIZE 0xd9c +#define MV64460_PCI_0_P2P_MEM1_BAR_SIZE 0xd20 +#define MV64460_PCI_1_P2P_MEM1_BAR_SIZE 0xda0 +#define MV64460_PCI_0_P2P_I_O_BAR_SIZE 0xd24 +#define MV64460_PCI_1_P2P_I_O_BAR_SIZE 0xda4 +#define MV64460_PCI_0_CPU_BAR_SIZE 0xd28 +#define MV64460_PCI_1_CPU_BAR_SIZE 0xda8 +#define MV64460_PCI_0_INTERNAL_SRAM_BAR_SIZE 0xe00 +#define MV64460_PCI_1_INTERNAL_SRAM_BAR_SIZE 0xe80 +#define MV64460_PCI_0_EXPANSION_ROM_BAR_SIZE 0xd2c +#define MV64460_PCI_1_EXPANSION_ROM_BAR_SIZE 0xd9c +#define MV64460_PCI_0_BASE_ADDR_REG_ENABLE 0xc3c +#define MV64460_PCI_1_BASE_ADDR_REG_ENABLE 0xcbc +#define MV64460_PCI_0_CS_0_BASE_ADDR_REMAP 0xc48 +#define MV64460_PCI_1_CS_0_BASE_ADDR_REMAP 0xcc8 +#define MV64460_PCI_0_CS_1_BASE_ADDR_REMAP 0xd48 +#define MV64460_PCI_1_CS_1_BASE_ADDR_REMAP 0xdc8 +#define MV64460_PCI_0_CS_2_BASE_ADDR_REMAP 0xc4c +#define MV64460_PCI_1_CS_2_BASE_ADDR_REMAP 0xccc +#define MV64460_PCI_0_CS_3_BASE_ADDR_REMAP 0xd4c +#define MV64460_PCI_1_CS_3_BASE_ADDR_REMAP 0xdcc +#define MV64460_PCI_0_CS_0_BASE_HIGH_ADDR_REMAP 0xF04 +#define MV64460_PCI_1_CS_0_BASE_HIGH_ADDR_REMAP 0xF84 +#define MV64460_PCI_0_CS_1_BASE_HIGH_ADDR_REMAP 0xF08 +#define MV64460_PCI_1_CS_1_BASE_HIGH_ADDR_REMAP 0xF88 +#define MV64460_PCI_0_CS_2_BASE_HIGH_ADDR_REMAP 0xF0C +#define MV64460_PCI_1_CS_2_BASE_HIGH_ADDR_REMAP 0xF8C +#define MV64460_PCI_0_CS_3_BASE_HIGH_ADDR_REMAP 0xF10 +#define MV64460_PCI_1_CS_3_BASE_HIGH_ADDR_REMAP 0xF90 +#define MV64460_PCI_0_DEVCS_0_BASE_ADDR_REMAP 0xc50 +#define MV64460_PCI_1_DEVCS_0_BASE_ADDR_REMAP 0xcd0 +#define MV64460_PCI_0_DEVCS_1_BASE_ADDR_REMAP 0xd50 +#define MV64460_PCI_1_DEVCS_1_BASE_ADDR_REMAP 0xdd0 +#define MV64460_PCI_0_DEVCS_2_BASE_ADDR_REMAP 0xd58 +#define MV64460_PCI_1_DEVCS_2_BASE_ADDR_REMAP 0xdd8 +#define MV64460_PCI_0_DEVCS_3_BASE_ADDR_REMAP 0xc54 +#define MV64460_PCI_1_DEVCS_3_BASE_ADDR_REMAP 0xcd4 +#define MV64460_PCI_0_DEVCS_BOOTCS_BASE_ADDR_REMAP 0xd54 +#define MV64460_PCI_1_DEVCS_BOOTCS_BASE_ADDR_REMAP 0xdd4 +#define MV64460_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_LOW 0xd5c +#define MV64460_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_LOW 0xddc +#define MV64460_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_HIGH 0xd60 +#define MV64460_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_HIGH 0xde0 +#define MV64460_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_LOW 0xd64 +#define MV64460_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_LOW 0xde4 +#define MV64460_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_HIGH 0xd68 +#define MV64460_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_HIGH 0xde8 +#define MV64460_PCI_0_P2P_I_O_BASE_ADDR_REMAP 0xd6c +#define MV64460_PCI_1_P2P_I_O_BASE_ADDR_REMAP 0xdec +#define MV64460_PCI_0_CPU_BASE_ADDR_REMAP_LOW 0xd70 +#define MV64460_PCI_1_CPU_BASE_ADDR_REMAP_LOW 0xdf0 +#define MV64460_PCI_0_CPU_BASE_ADDR_REMAP_HIGH 0xd74 +#define MV64460_PCI_1_CPU_BASE_ADDR_REMAP_HIGH 0xdf4 +#define MV64460_PCI_0_INTEGRATED_SRAM_BASE_ADDR_REMAP 0xf00 +#define MV64460_PCI_1_INTEGRATED_SRAM_BASE_ADDR_REMAP 0xf80 +#define MV64460_PCI_0_EXPANSION_ROM_BASE_ADDR_REMAP 0xf38 +#define MV64460_PCI_1_EXPANSION_ROM_BASE_ADDR_REMAP 0xfb8 +#define MV64460_PCI_0_ADDR_DECODE_CONTROL 0xd3c +#define MV64460_PCI_1_ADDR_DECODE_CONTROL 0xdbc +#define MV64460_PCI_0_HEADERS_RETARGET_CONTROL 0xF40 +#define MV64460_PCI_1_HEADERS_RETARGET_CONTROL 0xFc0 +#define MV64460_PCI_0_HEADERS_RETARGET_BASE 0xF44 +#define MV64460_PCI_1_HEADERS_RETARGET_BASE 0xFc4 +#define MV64460_PCI_0_HEADERS_RETARGET_HIGH 0xF48 +#define MV64460_PCI_1_HEADERS_RETARGET_HIGH 0xFc8 + +/***********************************/ +/* PCI Control Register Map */ +/***********************************/ + +#define MV64460_PCI_0_DLL_STATUS_AND_COMMAND 0x1d20 +#define MV64460_PCI_1_DLL_STATUS_AND_COMMAND 0x1da0 +#define MV64460_PCI_0_MPP_PADS_DRIVE_CONTROL 0x1d1C +#define MV64460_PCI_1_MPP_PADS_DRIVE_CONTROL 0x1d9C +#define MV64460_PCI_0_COMMAND 0xc00 +#define MV64460_PCI_1_COMMAND 0xc80 +#define MV64460_PCI_0_MODE 0xd00 +#define MV64460_PCI_1_MODE 0xd80 +#define MV64460_PCI_0_RETRY 0xc04 +#define MV64460_PCI_1_RETRY 0xc84 +#define MV64460_PCI_0_READ_BUFFER_DISCARD_TIMER 0xd04 +#define MV64460_PCI_1_READ_BUFFER_DISCARD_TIMER 0xd84 +#define MV64460_PCI_0_MSI_TRIGGER_TIMER 0xc38 +#define MV64460_PCI_1_MSI_TRIGGER_TIMER 0xcb8 +#define MV64460_PCI_0_ARBITER_CONTROL 0x1d00 +#define MV64460_PCI_1_ARBITER_CONTROL 0x1d80 +#define MV64460_PCI_0_CROSS_BAR_CONTROL_LOW 0x1d08 +#define MV64460_PCI_1_CROSS_BAR_CONTROL_LOW 0x1d88 +#define MV64460_PCI_0_CROSS_BAR_CONTROL_HIGH 0x1d0c +#define MV64460_PCI_1_CROSS_BAR_CONTROL_HIGH 0x1d8c +#define MV64460_PCI_0_CROSS_BAR_TIMEOUT 0x1d04 +#define MV64460_PCI_1_CROSS_BAR_TIMEOUT 0x1d84 +#define MV64460_PCI_0_SYNC_BARRIER_TRIGGER_REG 0x1D18 +#define MV64460_PCI_1_SYNC_BARRIER_TRIGGER_REG 0x1D98 +#define MV64460_PCI_0_SYNC_BARRIER_VIRTUAL_REG 0x1d10 +#define MV64460_PCI_1_SYNC_BARRIER_VIRTUAL_REG 0x1d90 +#define MV64460_PCI_0_P2P_CONFIG 0x1d14 +#define MV64460_PCI_1_P2P_CONFIG 0x1d94 + +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_0_LOW 0x1e00 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_0_HIGH 0x1e04 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_0 0x1e08 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_1_LOW 0x1e10 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_1_HIGH 0x1e14 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_1 0x1e18 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_2_LOW 0x1e20 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_2_HIGH 0x1e24 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_2 0x1e28 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_3_LOW 0x1e30 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_3_HIGH 0x1e34 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_3 0x1e38 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_4_LOW 0x1e40 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_4_HIGH 0x1e44 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_4 0x1e48 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_5_LOW 0x1e50 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_5_HIGH 0x1e54 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_5 0x1e58 + +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_0_LOW 0x1e80 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_0_HIGH 0x1e84 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_0 0x1e88 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_1_LOW 0x1e90 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_1_HIGH 0x1e94 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_1 0x1e98 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_2_LOW 0x1ea0 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_2_HIGH 0x1ea4 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_2 0x1ea8 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_3_LOW 0x1eb0 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_3_HIGH 0x1eb4 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_3 0x1eb8 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_4_LOW 0x1ec0 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_4_HIGH 0x1ec4 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_4 0x1ec8 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_5_LOW 0x1ed0 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_5_HIGH 0x1ed4 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_5 0x1ed8 + +/****************************************/ +/* PCI Configuration Access Registers */ +/****************************************/ + +#define MV64460_PCI_0_CONFIG_ADDR 0xcf8 +#define MV64460_PCI_0_CONFIG_DATA_VIRTUAL_REG 0xcfc +#define MV64460_PCI_1_CONFIG_ADDR 0xc78 +#define MV64460_PCI_1_CONFIG_DATA_VIRTUAL_REG 0xc7c +#define MV64460_PCI_0_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG 0xc34 +#define MV64460_PCI_1_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG 0xcb4 + +/****************************************/ +/* PCI Error Report Registers */ +/****************************************/ + +#define MV64460_PCI_0_SERR_MASK 0xc28 +#define MV64460_PCI_1_SERR_MASK 0xca8 +#define MV64460_PCI_0_ERROR_ADDR_LOW 0x1d40 +#define MV64460_PCI_1_ERROR_ADDR_LOW 0x1dc0 +#define MV64460_PCI_0_ERROR_ADDR_HIGH 0x1d44 +#define MV64460_PCI_1_ERROR_ADDR_HIGH 0x1dc4 +#define MV64460_PCI_0_ERROR_ATTRIBUTE 0x1d48 +#define MV64460_PCI_1_ERROR_ATTRIBUTE 0x1dc8 +#define MV64460_PCI_0_ERROR_COMMAND 0x1d50 +#define MV64460_PCI_1_ERROR_COMMAND 0x1dd0 +#define MV64460_PCI_0_ERROR_CAUSE 0x1d58 +#define MV64460_PCI_1_ERROR_CAUSE 0x1dd8 +#define MV64460_PCI_0_ERROR_MASK 0x1d5c +#define MV64460_PCI_1_ERROR_MASK 0x1ddc + +/****************************************/ +/* PCI Debug Registers */ +/****************************************/ + +#define MV64460_PCI_0_MMASK 0X1D24 +#define MV64460_PCI_1_MMASK 0X1DA4 + +/*********************************************/ +/* PCI Configuration, Function 0, Registers */ +/*********************************************/ + +#define MV64460_PCI_DEVICE_AND_VENDOR_ID 0x000 +#define MV64460_PCI_STATUS_AND_COMMAND 0x004 +#define MV64460_PCI_CLASS_CODE_AND_REVISION_ID 0x008 +#define MV64460_PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE 0x00C + +#define MV64460_PCI_SCS_0_BASE_ADDR_LOW 0x010 +#define MV64460_PCI_SCS_0_BASE_ADDR_HIGH 0x014 +#define MV64460_PCI_SCS_1_BASE_ADDR_LOW 0x018 +#define MV64460_PCI_SCS_1_BASE_ADDR_HIGH 0x01C +#define MV64460_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_LOW 0x020 +#define MV64460_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_HIGH 0x024 +#define MV64460_PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID 0x02c +#define MV64460_PCI_EXPANSION_ROM_BASE_ADDR_REG 0x030 +#define MV64460_PCI_CAPABILTY_LIST_POINTER 0x034 +#define MV64460_PCI_INTERRUPT_PIN_AND_LINE 0x03C + /* capability list */ +#define MV64460_PCI_POWER_MANAGEMENT_CAPABILITY 0x040 +#define MV64460_PCI_POWER_MANAGEMENT_STATUS_AND_CONTROL 0x044 +#define MV64460_PCI_VPD_ADDR 0x048 +#define MV64460_PCI_VPD_DATA 0x04c +#define MV64460_PCI_MSI_MESSAGE_CONTROL 0x050 +#define MV64460_PCI_MSI_MESSAGE_ADDR 0x054 +#define MV64460_PCI_MSI_MESSAGE_UPPER_ADDR 0x058 +#define MV64460_PCI_MSI_MESSAGE_DATA 0x05c +#define MV64460_PCI_X_COMMAND 0x060 +#define MV64460_PCI_X_STATUS 0x064 +#define MV64460_PCI_COMPACT_PCI_HOT_SWAP 0x068 + +/***********************************************/ +/* PCI Configuration, Function 1, Registers */ +/***********************************************/ + +#define MV64460_PCI_SCS_2_BASE_ADDR_LOW 0x110 +#define MV64460_PCI_SCS_2_BASE_ADDR_HIGH 0x114 +#define MV64460_PCI_SCS_3_BASE_ADDR_LOW 0x118 +#define MV64460_PCI_SCS_3_BASE_ADDR_HIGH 0x11c +#define MV64460_PCI_INTERNAL_SRAM_BASE_ADDR_LOW 0x120 +#define MV64460_PCI_INTERNAL_SRAM_BASE_ADDR_HIGH 0x124 + +/***********************************************/ +/* PCI Configuration, Function 2, Registers */ +/***********************************************/ + +#define MV64460_PCI_DEVCS_0_BASE_ADDR_LOW 0x210 +#define MV64460_PCI_DEVCS_0_BASE_ADDR_HIGH 0x214 +#define MV64460_PCI_DEVCS_1_BASE_ADDR_LOW 0x218 +#define MV64460_PCI_DEVCS_1_BASE_ADDR_HIGH 0x21c +#define MV64460_PCI_DEVCS_2_BASE_ADDR_LOW 0x220 +#define MV64460_PCI_DEVCS_2_BASE_ADDR_HIGH 0x224 + +/***********************************************/ +/* PCI Configuration, Function 3, Registers */ +/***********************************************/ + +#define MV64460_PCI_DEVCS_3_BASE_ADDR_LOW 0x310 +#define MV64460_PCI_DEVCS_3_BASE_ADDR_HIGH 0x314 +#define MV64460_PCI_BOOT_CS_BASE_ADDR_LOW 0x318 +#define MV64460_PCI_BOOT_CS_BASE_ADDR_HIGH 0x31c +#define MV64460_PCI_CPU_BASE_ADDR_LOW 0x220 +#define MV64460_PCI_CPU_BASE_ADDR_HIGH 0x224 + +/***********************************************/ +/* PCI Configuration, Function 4, Registers */ +/***********************************************/ + +#define MV64460_PCI_P2P_MEM0_BASE_ADDR_LOW 0x410 +#define MV64460_PCI_P2P_MEM0_BASE_ADDR_HIGH 0x414 +#define MV64460_PCI_P2P_MEM1_BASE_ADDR_LOW 0x418 +#define MV64460_PCI_P2P_MEM1_BASE_ADDR_HIGH 0x41c +#define MV64460_PCI_P2P_I_O_BASE_ADDR 0x420 +#define MV64460_PCI_INTERNAL_REGS_I_O_MAPPED_BASE_ADDR 0x424 + +/****************************************/ +/* Messaging Unit Registers (I20) */ +/****************************************/ + +#define MV64460_I2O_INBOUND_MESSAGE_REG0_PCI_0_SIDE 0x010 +#define MV64460_I2O_INBOUND_MESSAGE_REG1_PCI_0_SIDE 0x014 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG0_PCI_0_SIDE 0x018 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG1_PCI_0_SIDE 0x01C +#define MV64460_I2O_INBOUND_DOORBELL_REG_PCI_0_SIDE 0x020 +#define MV64460_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE 0x024 +#define MV64460_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE 0x028 +#define MV64460_I2O_OUTBOUND_DOORBELL_REG_PCI_0_SIDE 0x02C +#define MV64460_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE 0x030 +#define MV64460_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE 0x034 +#define MV64460_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE 0x040 +#define MV64460_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE 0x044 +#define MV64460_I2O_QUEUE_CONTROL_REG_PCI_0_SIDE 0x050 +#define MV64460_I2O_QUEUE_BASE_ADDR_REG_PCI_0_SIDE 0x054 +#define MV64460_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE 0x060 +#define MV64460_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE 0x064 +#define MV64460_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE 0x068 +#define MV64460_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE 0x06C +#define MV64460_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE 0x070 +#define MV64460_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE 0x074 +#define MV64460_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE 0x0F8 +#define MV64460_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE 0x0FC + +#define MV64460_I2O_INBOUND_MESSAGE_REG0_PCI_1_SIDE 0x090 +#define MV64460_I2O_INBOUND_MESSAGE_REG1_PCI_1_SIDE 0x094 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG0_PCI_1_SIDE 0x098 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG1_PCI_1_SIDE 0x09C +#define MV64460_I2O_INBOUND_DOORBELL_REG_PCI_1_SIDE 0x0A0 +#define MV64460_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE 0x0A4 +#define MV64460_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE 0x0A8 +#define MV64460_I2O_OUTBOUND_DOORBELL_REG_PCI_1_SIDE 0x0AC +#define MV64460_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE 0x0B0 +#define MV64460_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE 0x0B4 +#define MV64460_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE 0x0C0 +#define MV64460_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE 0x0C4 +#define MV64460_I2O_QUEUE_CONTROL_REG_PCI_1_SIDE 0x0D0 +#define MV64460_I2O_QUEUE_BASE_ADDR_REG_PCI_1_SIDE 0x0D4 +#define MV64460_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE 0x0E0 +#define MV64460_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE 0x0E4 +#define MV64460_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE 0x0E8 +#define MV64460_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE 0x0EC +#define MV64460_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE 0x0F0 +#define MV64460_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE 0x0F4 +#define MV64460_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE 0x078 +#define MV64460_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE 0x07C + +#define MV64460_I2O_INBOUND_MESSAGE_REG0_CPU0_SIDE 0x1C10 +#define MV64460_I2O_INBOUND_MESSAGE_REG1_CPU0_SIDE 0x1C14 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG0_CPU0_SIDE 0x1C18 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG1_CPU0_SIDE 0x1C1C +#define MV64460_I2O_INBOUND_DOORBELL_REG_CPU0_SIDE 0x1C20 +#define MV64460_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE 0x1C24 +#define MV64460_I2O_INBOUND_INTERRUPT_MASK_REG_CPU0_SIDE 0x1C28 +#define MV64460_I2O_OUTBOUND_DOORBELL_REG_CPU0_SIDE 0x1C2C +#define MV64460_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE 0x1C30 +#define MV64460_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU0_SIDE 0x1C34 +#define MV64460_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE 0x1C40 +#define MV64460_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE 0x1C44 +#define MV64460_I2O_QUEUE_CONTROL_REG_CPU0_SIDE 0x1C50 +#define MV64460_I2O_QUEUE_BASE_ADDR_REG_CPU0_SIDE 0x1C54 +#define MV64460_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE 0x1C60 +#define MV64460_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE 0x1C64 +#define MV64460_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE 0x1C68 +#define MV64460_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE 0x1C6C +#define MV64460_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE 0x1C70 +#define MV64460_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE 0x1C74 +#define MV64460_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE 0x1CF8 +#define MV64460_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE 0x1CFC +#define MV64460_I2O_INBOUND_MESSAGE_REG0_CPU1_SIDE 0x1C90 +#define MV64460_I2O_INBOUND_MESSAGE_REG1_CPU1_SIDE 0x1C94 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG0_CPU1_SIDE 0x1C98 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG1_CPU1_SIDE 0x1C9C +#define MV64460_I2O_INBOUND_DOORBELL_REG_CPU1_SIDE 0x1CA0 +#define MV64460_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE 0x1CA4 +#define MV64460_I2O_INBOUND_INTERRUPT_MASK_REG_CPU1_SIDE 0x1CA8 +#define MV64460_I2O_OUTBOUND_DOORBELL_REG_CPU1_SIDE 0x1CAC +#define MV64460_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE 0x1CB0 +#define MV64460_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU1_SIDE 0x1CB4 +#define MV64460_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE 0x1CC0 +#define MV64460_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE 0x1CC4 +#define MV64460_I2O_QUEUE_CONTROL_REG_CPU1_SIDE 0x1CD0 +#define MV64460_I2O_QUEUE_BASE_ADDR_REG_CPU1_SIDE 0x1CD4 +#define MV64460_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE 0x1CE0 +#define MV64460_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE 0x1CE4 +#define MV64460_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE 0x1CE8 +#define MV64460_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE 0x1CEC +#define MV64460_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE 0x1CF0 +#define MV64460_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE 0x1CF4 +#define MV64460_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE 0x1C78 +#define MV64460_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE 0x1C7C + +/****************************************/ +/* Ethernet Unit Registers */ +/****************************************/ + +#define MV64460_ETH_PHY_ADDR_REG 0x2000 +#define MV64460_ETH_SMI_REG 0x2004 +#define MV64460_ETH_UNIT_DEFAULT_ADDR_REG 0x2008 +#define MV64460_ETH_UNIT_DEFAULTID_REG 0x200c +#define MV64460_ETH_UNIT_INTERRUPT_CAUSE_REG 0x2080 +#define MV64460_ETH_UNIT_INTERRUPT_MASK_REG 0x2084 +#define MV64460_ETH_UNIT_INTERNAL_USE_REG 0x24fc +#define MV64460_ETH_UNIT_ERROR_ADDR_REG 0x2094 +#define MV64460_ETH_BAR_0 0x2200 +#define MV64460_ETH_BAR_1 0x2208 +#define MV64460_ETH_BAR_2 0x2210 +#define MV64460_ETH_BAR_3 0x2218 +#define MV64460_ETH_BAR_4 0x2220 +#define MV64460_ETH_BAR_5 0x2228 +#define MV64460_ETH_SIZE_REG_0 0x2204 +#define MV64460_ETH_SIZE_REG_1 0x220c +#define MV64460_ETH_SIZE_REG_2 0x2214 +#define MV64460_ETH_SIZE_REG_3 0x221c +#define MV64460_ETH_SIZE_REG_4 0x2224 +#define MV64460_ETH_SIZE_REG_5 0x222c +#define MV64460_ETH_HEADERS_RETARGET_BASE_REG 0x2230 +#define MV64460_ETH_HEADERS_RETARGET_CONTROL_REG 0x2234 +#define MV64460_ETH_HIGH_ADDR_REMAP_REG_0 0x2280 +#define MV64460_ETH_HIGH_ADDR_REMAP_REG_1 0x2284 +#define MV64460_ETH_HIGH_ADDR_REMAP_REG_2 0x2288 +#define MV64460_ETH_HIGH_ADDR_REMAP_REG_3 0x228c +#define MV64460_ETH_BASE_ADDR_ENABLE_REG 0x2290 +#define MV64460_ETH_ACCESS_PROTECTION_REG(port) (0x2294 + (port<<2)) +#define MV64460_ETH_MIB_COUNTERS_BASE(port) (0x3000 + (port<<7)) +#define MV64460_ETH_PORT_CONFIG_REG(port) (0x2400 + (port<<10)) +#define MV64460_ETH_PORT_CONFIG_EXTEND_REG(port) (0x2404 + (port<<10)) +#define MV64460_ETH_MII_SERIAL_PARAMETRS_REG(port) (0x2408 + (port<<10)) +#define MV64460_ETH_GMII_SERIAL_PARAMETRS_REG(port) (0x240c + (port<<10)) +#define MV64460_ETH_VLAN_ETHERTYPE_REG(port) (0x2410 + (port<<10)) +#define MV64460_ETH_MAC_ADDR_LOW(port) (0x2414 + (port<<10)) +#define MV64460_ETH_MAC_ADDR_HIGH(port) (0x2418 + (port<<10)) +#define MV64460_ETH_SDMA_CONFIG_REG(port) (0x241c + (port<<10)) +#define MV64460_ETH_DSCP_0(port) (0x2420 + (port<<10)) +#define MV64460_ETH_DSCP_1(port) (0x2424 + (port<<10)) +#define MV64460_ETH_DSCP_2(port) (0x2428 + (port<<10)) +#define MV64460_ETH_DSCP_3(port) (0x242c + (port<<10)) +#define MV64460_ETH_DSCP_4(port) (0x2430 + (port<<10)) +#define MV64460_ETH_DSCP_5(port) (0x2434 + (port<<10)) +#define MV64460_ETH_DSCP_6(port) (0x2438 + (port<<10)) +#define MV64460_ETH_PORT_SERIAL_CONTROL_REG(port) (0x243c + (port<<10)) +#define MV64460_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port) (0x2440 + (port<<10)) +#define MV64460_ETH_PORT_STATUS_REG(port) (0x2444 + (port<<10)) +#define MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG(port) (0x2448 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_FIXED_PRIORITY(port) (0x244c + (port<<10)) +#define MV64460_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port) (0x2450 + (port<<10)) +#define MV64460_ETH_MAXIMUM_TRANSMIT_UNIT(port) (0x2458 + (port<<10)) +#define MV64460_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port) (0x245c + (port<<10)) +#define MV64460_ETH_INTERRUPT_CAUSE_REG(port) (0x2460 + (port<<10)) +#define MV64460_ETH_INTERRUPT_CAUSE_EXTEND_REG(port) (0x2464 + (port<<10)) +#define MV64460_ETH_INTERRUPT_MASK_REG(port) (0x2468 + (port<<10)) +#define MV64460_ETH_INTERRUPT_EXTEND_MASK_REG(port) (0x246c + (port<<10)) +#define MV64460_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port) (0x2470 + (port<<10)) +#define MV64460_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port) (0x2474 + (port<<10)) +#define MV64460_ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (0x247c + (port<<10)) +#define MV64460_ETH_RX_DISCARDED_FRAMES_COUNTER(port) (0x2484 + (port<<10) +#define MV64460_ETH_PORT_DEBUG_0_REG(port) (0x248c + (port<<10)) +#define MV64460_ETH_PORT_DEBUG_1_REG(port) (0x2490 + (port<<10)) +#define MV64460_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port) (0x2494 + (port<<10)) +#define MV64460_ETH_INTERNAL_USE_REG(port) (0x24fc + (port<<10)) +#define MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG(port) (0x2680 + (port<<10)) +#define MV64460_ETH_CURRENT_SERVED_TX_DESC_PTR(port) (0x2684 + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port) (0x260c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port) (0x261c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port) (0x262c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port) (0x263c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port) (0x264c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port) (0x265c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port) (0x266c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port) (0x267c + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port) (0x26c0 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port) (0x26c4 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port) (0x26c8 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port) (0x26cc + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port) (0x26d0 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port) (0x26d4 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port) (0x26d8 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port) (0x26dc + (port<<10)) +#define MV64460_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port) (0x2700 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port) (0x2710 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port) (0x2720 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port) (0x2730 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port) (0x2740 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port) (0x2750 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port) (0x2760 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port) (0x2770 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port) (0x2704 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port) (0x2714 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port) (0x2724 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port) (0x2734 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port) (0x2744 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port) (0x2754 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port) (0x2764 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port) (0x2774 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_0_ARBITER_CONFIG(port) (0x2708 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_1_ARBITER_CONFIG(port) (0x2718 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_2_ARBITER_CONFIG(port) (0x2728 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_3_ARBITER_CONFIG(port) (0x2738 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_4_ARBITER_CONFIG(port) (0x2748 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_5_ARBITER_CONFIG(port) (0x2758 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_6_ARBITER_CONFIG(port) (0x2768 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_7_ARBITER_CONFIG(port) (0x2778 + (port<<10)) +#define MV64460_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port) (0x2780 + (port<<10)) +#define MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port) (0x3400 + (port<<10)) +#define MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port) (0x3500 + (port<<10)) +#define MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE(port) (0x3600 + (port<<10)) + +/*******************************************/ +/* CUNIT Registers */ +/*******************************************/ + + /* Address Decoding Register Map */ + +#define MV64460_CUNIT_BASE_ADDR_REG0 0xf200 +#define MV64460_CUNIT_BASE_ADDR_REG1 0xf208 +#define MV64460_CUNIT_BASE_ADDR_REG2 0xf210 +#define MV64460_CUNIT_BASE_ADDR_REG3 0xf218 +#define MV64460_CUNIT_SIZE0 0xf204 +#define MV64460_CUNIT_SIZE1 0xf20c +#define MV64460_CUNIT_SIZE2 0xf214 +#define MV64460_CUNIT_SIZE3 0xf21c +#define MV64460_CUNIT_HIGH_ADDR_REMAP_REG0 0xf240 +#define MV64460_CUNIT_HIGH_ADDR_REMAP_REG1 0xf244 +#define MV64460_CUNIT_BASE_ADDR_ENABLE_REG 0xf250 +#define MV64460_MPSC0_ACCESS_PROTECTION_REG 0xf254 +#define MV64460_MPSC1_ACCESS_PROTECTION_REG 0xf258 +#define MV64460_CUNIT_INTERNAL_SPACE_BASE_ADDR_REG 0xf25C + + /* Error Report Registers */ + +#define MV64460_CUNIT_INTERRUPT_CAUSE_REG 0xf310 +#define MV64460_CUNIT_INTERRUPT_MASK_REG 0xf314 +#define MV64460_CUNIT_ERROR_ADDR 0xf318 + + /* Cunit Control Registers */ + +#define MV64460_CUNIT_ARBITER_CONTROL_REG 0xf300 +#define MV64460_CUNIT_CONFIG_REG 0xb40c +#define MV64460_CUNIT_CRROSBAR_TIMEOUT_REG 0xf304 + + /* Cunit Debug Registers */ + +#define MV64460_CUNIT_DEBUG_LOW 0xf340 +#define MV64460_CUNIT_DEBUG_HIGH 0xf344 +#define MV64460_CUNIT_MMASK 0xf380 + + /* Cunit Base Address Enable Window Bits*/ +#define MV64460_CUNIT_BASE_ADDR_WIN_0_BIT 0x0 +#define MV64460_CUNIT_BASE_ADDR_WIN_1_BIT 0x1 +#define MV64460_CUNIT_BASE_ADDR_WIN_2_BIT 0x2 +#define MV64460_CUNIT_BASE_ADDR_WIN_3_BIT 0x3 + + /* MPSCs Clocks Routing Registers */ + +#define MV64460_MPSC_ROUTING_REG 0xb400 +#define MV64460_MPSC_RX_CLOCK_ROUTING_REG 0xb404 +#define MV64460_MPSC_TX_CLOCK_ROUTING_REG 0xb408 + + /* MPSCs Interrupts Registers */ + +#define MV64460_MPSC_CAUSE_REG(port) (0xb804 + (port<<3)) +#define MV64460_MPSC_MASK_REG(port) (0xb884 + (port<<3)) + +#define MV64460_MPSC_MAIN_CONFIG_LOW(port) (0x8000 + (port<<12)) +#define MV64460_MPSC_MAIN_CONFIG_HIGH(port) (0x8004 + (port<<12)) +#define MV64460_MPSC_PROTOCOL_CONFIG(port) (0x8008 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG1(port) (0x800c + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG2(port) (0x8010 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG3(port) (0x8014 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG4(port) (0x8018 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG5(port) (0x801c + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG6(port) (0x8020 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG7(port) (0x8024 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG8(port) (0x8028 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG9(port) (0x802c + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG10(port) (0x8030 + (port<<12)) + + /* MPSC0 Registers */ + + +/***************************************/ +/* SDMA Registers */ +/***************************************/ + +#define MV64460_SDMA_CONFIG_REG(channel) (0x4000 + (channel<<13)) +#define MV64460_SDMA_COMMAND_REG(channel) (0x4008 + (channel<<13)) +#define MV64460_SDMA_CURRENT_RX_DESCRIPTOR_POINTER(channel) (0x4810 + (channel<<13)) +#define MV64460_SDMA_CURRENT_TX_DESCRIPTOR_POINTER(channel) (0x4c10 + (channel<<13)) +#define MV64460_SDMA_FIRST_TX_DESCRIPTOR_POINTER(channel) (0x4c14 + (channel<<13)) + +#define MV64460_SDMA_CAUSE_REG 0xb800 +#define MV64460_SDMA_MASK_REG 0xb880 + + +/****************************************/ +/* SDMA Address Space Targets */ +/****************************************/ + +#define MV64460_SDMA_DRAM_CS_0_TARGET 0x0e00 +#define MV64460_SDMA_DRAM_CS_1_TARGET 0x0d00 +#define MV64460_SDMA_DRAM_CS_2_TARGET 0x0b00 +#define MV64460_SDMA_DRAM_CS_3_TARGET 0x0700 + +#define MV64460_SDMA_DEV_CS_0_TARGET 0x1e01 +#define MV64460_SDMA_DEV_CS_1_TARGET 0x1d01 +#define MV64460_SDMA_DEV_CS_2_TARGET 0x1b01 +#define MV64460_SDMA_DEV_CS_3_TARGET 0x1701 + +#define MV64460_SDMA_BOOT_CS_TARGET 0x0f00 + +#define MV64460_SDMA_SRAM_TARGET 0x0003 +#define MV64460_SDMA_60X_BUS_TARGET 0x4003 + +#define MV64460_PCI_0_TARGET 0x0003 +#define MV64460_PCI_1_TARGET 0x0004 + + +/* Devices BAR and size registers */ + +#define MV64460_DEV_CS0_BASE_ADDR 0x028 +#define MV64460_DEV_CS0_SIZE 0x030 +#define MV64460_DEV_CS1_BASE_ADDR 0x228 +#define MV64460_DEV_CS1_SIZE 0x230 +#define MV64460_DEV_CS2_BASE_ADDR 0x248 +#define MV64460_DEV_CS2_SIZE 0x250 +#define MV64460_DEV_CS3_BASE_ADDR 0x038 +#define MV64460_DEV_CS3_SIZE 0x040 +#define MV64460_BOOTCS_BASE_ADDR 0x238 +#define MV64460_BOOTCS_SIZE 0x240 + +/* SDMA Window access protection */ +#define MV64460_SDMA_WIN_ACCESS_NOT_ALLOWED 0 +#define MV64460_SDMA_WIN_ACCESS_READ_ONLY 1 +#define MV64460_SDMA_WIN_ACCESS_FULL 2 + +/* BRG Interrupts */ + +#define MV64460_BRG_CONFIG_REG(brg) (0xb200 + (brg<<3)) +#define MV64460_BRG_BAUDE_TUNING_REG(brg) (0xb204 + (brg<<3)) +#define MV64460_BRG_CAUSE_REG 0xb834 +#define MV64460_BRG_MASK_REG 0xb8b4 + +/****************************************/ +/* DMA Channel Control */ +/****************************************/ + +#define MV64460_DMA_CHANNEL0_CONTROL 0x840 +#define MV64460_DMA_CHANNEL0_CONTROL_HIGH 0x880 +#define MV64460_DMA_CHANNEL1_CONTROL 0x844 +#define MV64460_DMA_CHANNEL1_CONTROL_HIGH 0x884 +#define MV64460_DMA_CHANNEL2_CONTROL 0x848 +#define MV64460_DMA_CHANNEL2_CONTROL_HIGH 0x888 +#define MV64460_DMA_CHANNEL3_CONTROL 0x84C +#define MV64460_DMA_CHANNEL3_CONTROL_HIGH 0x88C + + +/****************************************/ +/* IDMA Registers */ +/****************************************/ + +#define MV64460_DMA_CHANNEL0_BYTE_COUNT 0x800 +#define MV64460_DMA_CHANNEL1_BYTE_COUNT 0x804 +#define MV64460_DMA_CHANNEL2_BYTE_COUNT 0x808 +#define MV64460_DMA_CHANNEL3_BYTE_COUNT 0x80C +#define MV64460_DMA_CHANNEL0_SOURCE_ADDR 0x810 +#define MV64460_DMA_CHANNEL1_SOURCE_ADDR 0x814 +#define MV64460_DMA_CHANNEL2_SOURCE_ADDR 0x818 +#define MV64460_DMA_CHANNEL3_SOURCE_ADDR 0x81c +#define MV64460_DMA_CHANNEL0_DESTINATION_ADDR 0x820 +#define MV64460_DMA_CHANNEL1_DESTINATION_ADDR 0x824 +#define MV64460_DMA_CHANNEL2_DESTINATION_ADDR 0x828 +#define MV64460_DMA_CHANNEL3_DESTINATION_ADDR 0x82C +#define MV64460_DMA_CHANNEL0_NEXT_DESCRIPTOR_POINTER 0x830 +#define MV64460_DMA_CHANNEL1_NEXT_DESCRIPTOR_POINTER 0x834 +#define MV64460_DMA_CHANNEL2_NEXT_DESCRIPTOR_POINTER 0x838 +#define MV64460_DMA_CHANNEL3_NEXT_DESCRIPTOR_POINTER 0x83C +#define MV64460_DMA_CHANNEL0_CURRENT_DESCRIPTOR_POINTER 0x870 +#define MV64460_DMA_CHANNEL1_CURRENT_DESCRIPTOR_POINTER 0x874 +#define MV64460_DMA_CHANNEL2_CURRENT_DESCRIPTOR_POINTER 0x878 +#define MV64460_DMA_CHANNEL3_CURRENT_DESCRIPTOR_POINTER 0x87C + + /* IDMA Address Decoding Base Address Registers */ + +#define MV64460_DMA_BASE_ADDR_REG0 0xa00 +#define MV64460_DMA_BASE_ADDR_REG1 0xa08 +#define MV64460_DMA_BASE_ADDR_REG2 0xa10 +#define MV64460_DMA_BASE_ADDR_REG3 0xa18 +#define MV64460_DMA_BASE_ADDR_REG4 0xa20 +#define MV64460_DMA_BASE_ADDR_REG5 0xa28 +#define MV64460_DMA_BASE_ADDR_REG6 0xa30 +#define MV64460_DMA_BASE_ADDR_REG7 0xa38 + + /* IDMA Address Decoding Size Address Register */ + +#define MV64460_DMA_SIZE_REG0 0xa04 +#define MV64460_DMA_SIZE_REG1 0xa0c +#define MV64460_DMA_SIZE_REG2 0xa14 +#define MV64460_DMA_SIZE_REG3 0xa1c +#define MV64460_DMA_SIZE_REG4 0xa24 +#define MV64460_DMA_SIZE_REG5 0xa2c +#define MV64460_DMA_SIZE_REG6 0xa34 +#define MV64460_DMA_SIZE_REG7 0xa3C + + /* IDMA Address Decoding High Address Remap and Access + Protection Registers */ + +#define MV64460_DMA_HIGH_ADDR_REMAP_REG0 0xa60 +#define MV64460_DMA_HIGH_ADDR_REMAP_REG1 0xa64 +#define MV64460_DMA_HIGH_ADDR_REMAP_REG2 0xa68 +#define MV64460_DMA_HIGH_ADDR_REMAP_REG3 0xa6C +#define MV64460_DMA_BASE_ADDR_ENABLE_REG 0xa80 +#define MV64460_DMA_CHANNEL0_ACCESS_PROTECTION_REG 0xa70 +#define MV64460_DMA_CHANNEL1_ACCESS_PROTECTION_REG 0xa74 +#define MV64460_DMA_CHANNEL2_ACCESS_PROTECTION_REG 0xa78 +#define MV64460_DMA_CHANNEL3_ACCESS_PROTECTION_REG 0xa7c +#define MV64460_DMA_ARBITER_CONTROL 0x860 +#define MV64460_DMA_CROSS_BAR_TIMEOUT 0x8d0 + + /* IDMA Headers Retarget Registers */ + +#define MV64460_DMA_HEADERS_RETARGET_CONTROL 0xa84 +#define MV64460_DMA_HEADERS_RETARGET_BASE 0xa88 + + /* IDMA Interrupt Register */ + +#define MV64460_DMA_INTERRUPT_CAUSE_REG 0x8c0 +#define MV64460_DMA_INTERRUPT_CAUSE_MASK 0x8c4 +#define MV64460_DMA_ERROR_ADDR 0x8c8 +#define MV64460_DMA_ERROR_SELECT 0x8cc + + /* IDMA Debug Register ( for internal use ) */ + +#define MV64460_DMA_DEBUG_LOW 0x8e0 +#define MV64460_DMA_DEBUG_HIGH 0x8e4 +#define MV64460_DMA_SPARE 0xA8C + +/****************************************/ +/* Timer_Counter */ +/****************************************/ + +#define MV64460_TIMER_COUNTER0 0x850 +#define MV64460_TIMER_COUNTER1 0x854 +#define MV64460_TIMER_COUNTER2 0x858 +#define MV64460_TIMER_COUNTER3 0x85C +#define MV64460_TIMER_COUNTER_0_3_CONTROL 0x864 +#define MV64460_TIMER_COUNTER_0_3_INTERRUPT_CAUSE 0x868 +#define MV64460_TIMER_COUNTER_0_3_INTERRUPT_MASK 0x86c + +/****************************************/ +/* Watchdog registers */ +/****************************************/ + +#define MV64460_WATCHDOG_CONFIG_REG 0xb410 +#define MV64460_WATCHDOG_VALUE_REG 0xb414 + +/****************************************/ +/* I2C Registers */ +/****************************************/ + +#define MV64460_I2C_SLAVE_ADDR 0xc000 +#define MV64460_I2C_EXTENDED_SLAVE_ADDR 0xc010 +#define MV64460_I2C_DATA 0xc004 +#define MV64460_I2C_CONTROL 0xc008 +#define MV64460_I2C_STATUS_BAUDE_RATE 0xc00C +#define MV64460_I2C_SOFT_RESET 0xc01c + +/****************************************/ +/* GPP Interface Registers */ +/****************************************/ + +#define MV64460_GPP_IO_CONTROL 0xf100 +#define MV64460_GPP_LEVEL_CONTROL 0xf110 +#define MV64460_GPP_VALUE 0xf104 +#define MV64460_GPP_INTERRUPT_CAUSE 0xf108 +#define MV64460_GPP_INTERRUPT_MASK0 0xf10c +#define MV64460_GPP_INTERRUPT_MASK1 0xf114 +#define MV64460_GPP_VALUE_SET 0xf118 +#define MV64460_GPP_VALUE_CLEAR 0xf11c + +/****************************************/ +/* Interrupt Controller Registers */ +/****************************************/ + +/****************************************/ +/* Interrupts */ +/****************************************/ + +#define MV64460_MAIN_INTERRUPT_CAUSE_LOW 0x004 +#define MV64460_MAIN_INTERRUPT_CAUSE_HIGH 0x00c +#define MV64460_CPU_INTERRUPT0_MASK_LOW 0x014 +#define MV64460_CPU_INTERRUPT0_MASK_HIGH 0x01c +#define MV64460_CPU_INTERRUPT0_SELECT_CAUSE 0x024 +#define MV64460_CPU_INTERRUPT1_MASK_LOW 0x034 +#define MV64460_CPU_INTERRUPT1_MASK_HIGH 0x03c +#define MV64460_CPU_INTERRUPT1_SELECT_CAUSE 0x044 +#define MV64460_INTERRUPT0_MASK_0_LOW 0x054 +#define MV64460_INTERRUPT0_MASK_0_HIGH 0x05c +#define MV64460_INTERRUPT0_SELECT_CAUSE 0x064 +#define MV64460_INTERRUPT1_MASK_0_LOW 0x074 +#define MV64460_INTERRUPT1_MASK_0_HIGH 0x07c +#define MV64460_INTERRUPT1_SELECT_CAUSE 0x084 + +/****************************************/ +/* MPP Interface Registers */ +/****************************************/ + +#define MV64460_MPP_CONTROL0 0xf000 +#define MV64460_MPP_CONTROL1 0xf004 +#define MV64460_MPP_CONTROL2 0xf008 +#define MV64460_MPP_CONTROL3 0xf00c + +/****************************************/ +/* Serial Initialization registers */ +/****************************************/ + +#define MV64460_SERIAL_INIT_LAST_DATA 0xf324 +#define MV64460_SERIAL_INIT_CONTROL 0xf328 +#define MV64460_SERIAL_INIT_STATUS 0xf32c + + +#endif /* __INCgt64460rh */ diff --git a/board/prodrive/p3mx/p3mx.c b/board/prodrive/p3mx/p3mx.c new file mode 100644 index 0000000000..6cebd1aeb6 --- /dev/null +++ b/board/prodrive/p3mx/p3mx.c @@ -0,0 +1,809 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * Based on original work by + * Roel Loeffen, (C) Copyright 2006 Prodrive B.V. + * Josh Huber, (C) Copyright 2001 Mission Critical Linux, 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 + * + * modifications for the DB64360 eval board based by Ingo.Assmus@keymile.com + * modifications for the cpci750 by reinhard.arlt@esd-electronics.com + * modifications for the P3M750 by roel.loeffen@prodrive.nl + */ + +/* + * p3m750.c - main board support/init for the Prodrive p3m750/p3m7448. + */ + +#include +#include <74xx_7xx.h> +#include "../../Marvell/include/memory.h" +#include "../../Marvell/include/pci.h" +#include "../../Marvell/include/mv_gen_reg.h" +#include +#include + +#include "eth.h" +#include "mpsc.h" +#include "64460.h" +#include "mv_regs.h" + +DECLARE_GLOBAL_DATA_PTR; + +#undef DEBUG +/*#define DEBUG */ + +#ifdef CONFIG_PCI +#define MAP_PCI +#endif /* of CONFIG_PCI */ + +#ifdef DEBUG +#define DP(x) x +#else +#define DP(x) +#endif + +extern void flush_data_cache (void); +extern void invalidate_l1_instruction_cache (void); +extern flash_info_t flash_info[]; + +/* ------------------------------------------------------------------------- */ + +/* this is the current GT register space location */ +/* it starts at CFG_DFL_GT_REGS but moves later to CFG_GT_REGS */ + +/* Unfortunately, we cant change it while we are in flash, so we initialize it + * to the "final" value. This means that any debug_led calls before + * board_early_init_f wont work right (like in cpu_init_f). + * See also my_remap_gt_regs below. (NTL) + */ + +void board_prebootm_init (void); +unsigned int INTERNAL_REG_BASE_ADDR = CFG_GT_REGS; +int display_mem_map (void); + +/* ------------------------------------------------------------------------- */ + +/* + * This is a version of the GT register space remapping function that + * doesn't touch globals (meaning, it's ok to run from flash.) + * + * Unfortunately, this has the side effect that a writable + * INTERNAL_REG_BASE_ADDR is impossible. Oh well. + */ + +void my_remap_gt_regs (u32 cur_loc, u32 new_loc) +{ + u32 temp; + + /* check and see if it's already moved */ + temp = in_le32 ((u32 *) (new_loc + INTERNAL_SPACE_DECODE)); + if ((temp & 0xffff) == new_loc >> 16) + return; + + temp = (in_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE)) & + 0xffff0000) | (new_loc >> 16); + + out_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE), temp); + + while (GTREGREAD (INTERNAL_SPACE_DECODE) != temp); +} + +#ifdef CONFIG_PCI + +static void gt_pci_config (void) +{ + unsigned int stat; + unsigned int val = 0x00fff864; /* DINK32: BusNum 23:16, DevNum 15:11, */ + /* FuncNum 10:8, RegNum 7:2 */ + + /* + * In PCIX mode devices provide their own bus and device numbers. + * We query the Discovery II's + * config registers by writing ones to the bus and device. + * We then update the Virtual register with the correct value for the + * bus and device. + */ + if ((GTREGREAD (PCI_0_MODE) & (BIT4 | BIT5)) != 0) { /* if PCI-X */ + GT_REG_WRITE (PCI_0_CONFIG_ADDR, BIT31 | val); + + GT_REG_READ (PCI_0_CONFIG_DATA_VIRTUAL_REG, &stat); + + GT_REG_WRITE (PCI_0_CONFIG_ADDR, BIT31 | val); + GT_REG_WRITE (PCI_0_CONFIG_DATA_VIRTUAL_REG, + (stat & 0xffff0000) | CFG_PCI_IDSEL); + + } + if ((GTREGREAD (PCI_1_MODE) & (BIT4 | BIT5)) != 0) { /* if PCI-X */ + GT_REG_WRITE (PCI_1_CONFIG_ADDR, BIT31 | val); + GT_REG_READ (PCI_1_CONFIG_DATA_VIRTUAL_REG, &stat); + + GT_REG_WRITE (PCI_1_CONFIG_ADDR, BIT31 | val); + GT_REG_WRITE (PCI_1_CONFIG_DATA_VIRTUAL_REG, + (stat & 0xffff0000) | CFG_PCI_IDSEL); + } + + /* Enable master */ + PCI_MASTER_ENABLE (0, SELF); + PCI_MASTER_ENABLE (1, SELF); + + /* Enable PCI0/1 Mem0 and IO 0 disable all others */ + GT_REG_READ (BASE_ADDR_ENABLE, &stat); + stat |= (1 << 11) | (1 << 12) | (1 << 13) | (1 << 16) | (1 << 17) | + (1 << 18); + stat &= ~((1 << 9) | (1 << 10) | (1 << 14) | (1 << 15)); + GT_REG_WRITE (BASE_ADDR_ENABLE, stat); + + /* ronen: + * add write to pci remap registers for 64460. + * in 64360 when writing to pci base go and overide remap automaticaly, + * in 64460 it doesn't + */ + GT_REG_WRITE (PCI_0_IO_BASE_ADDR, CFG_PCI0_IO_SPACE >> 16); + GT_REG_WRITE (PCI_0I_O_ADDRESS_REMAP, CFG_PCI0_IO_SPACE_PCI >> 16); + GT_REG_WRITE (PCI_0_IO_SIZE, (CFG_PCI0_IO_SIZE - 1) >> 16); + + GT_REG_WRITE (PCI_0_MEMORY0_BASE_ADDR, CFG_PCI0_MEM_BASE >> 16); + GT_REG_WRITE (PCI_0MEMORY0_ADDRESS_REMAP, CFG_PCI0_MEM_BASE >> 16); + GT_REG_WRITE (PCI_0_MEMORY0_SIZE, (CFG_PCI0_MEM_SIZE - 1) >> 16); + + GT_REG_WRITE (PCI_1_IO_BASE_ADDR, CFG_PCI1_IO_SPACE >> 16); + GT_REG_WRITE (PCI_1I_O_ADDRESS_REMAP, CFG_PCI1_IO_SPACE_PCI >> 16); + GT_REG_WRITE (PCI_1_IO_SIZE, (CFG_PCI1_IO_SIZE - 1) >> 16); + + GT_REG_WRITE (PCI_1_MEMORY0_BASE_ADDR, CFG_PCI1_MEM_BASE >> 16); + GT_REG_WRITE (PCI_1MEMORY0_ADDRESS_REMAP, CFG_PCI1_MEM_BASE >> 16); + GT_REG_WRITE (PCI_1_MEMORY0_SIZE, (CFG_PCI1_MEM_SIZE - 1) >> 16); + + /* PCI interface settings */ + /* Timeout set to retry forever */ + GT_REG_WRITE (PCI_0TIMEOUT_RETRY, 0x0); + GT_REG_WRITE (PCI_1TIMEOUT_RETRY, 0x0); + + /* ronen - enable only CS0 and Internal reg!! */ + GT_REG_WRITE (PCI_0BASE_ADDRESS_REGISTERS_ENABLE, 0xfffffdfe); + GT_REG_WRITE (PCI_1BASE_ADDRESS_REGISTERS_ENABLE, 0xfffffdfe); + + /* ronen: + * update the pci internal registers base address. + */ +#ifdef MAP_PCI + for (stat = 0; stat <= PCI_HOST1; stat++) + pciWriteConfigReg (stat, + PCI_INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS, + SELF, CFG_GT_REGS); +#endif + +} +#endif + +/* Setup CPU interface paramaters */ +static void gt_cpu_config (void) +{ + cpu_t cpu = get_cpu_type (); + ulong tmp; + + /* cpu configuration register */ + tmp = GTREGREAD (CPU_CONFIGURATION); + /* set the SINGLE_CPU bit see MV64460 */ +#ifndef CFG_GT_DUAL_CPU /* SINGLE_CPU seems to cause JTAG problems */ + tmp |= CPU_CONF_SINGLE_CPU; +#endif + tmp &= ~CPU_CONF_AACK_DELAY_2; + tmp |= CPU_CONF_DP_VALID; + tmp |= CPU_CONF_AP_VALID; + tmp |= CPU_CONF_PIPELINE; + GT_REG_WRITE (CPU_CONFIGURATION, tmp); /* Marvell (VXWorks) writes 0x20220FF */ + + /* CPU master control register */ + tmp = GTREGREAD (CPU_MASTER_CONTROL); + tmp |= CPU_MAST_CTL_ARB_EN; + + if ((cpu == CPU_7400) || + (cpu == CPU_7410) || (cpu == CPU_7455) || (cpu == CPU_7450)) { + + tmp |= CPU_MAST_CTL_CLEAN_BLK; + tmp |= CPU_MAST_CTL_FLUSH_BLK; + + } else { + /* cleanblock must be cleared for CPUs + * that do not support this command (603e, 750) + * see Res#1 */ + tmp &= ~CPU_MAST_CTL_CLEAN_BLK; + tmp &= ~CPU_MAST_CTL_FLUSH_BLK; + } + GT_REG_WRITE (CPU_MASTER_CONTROL, tmp); +} + +/* + * board_early_init_f. + * + * set up gal. device mappings, etc. + */ +int board_early_init_f (void) +{ + /* set up the GT the way the kernel wants it + * the call to move the GT register space will obviously + * fail if it has already been done, but we're going to assume + * that if it's not at the power-on location, it's where we put + * it last time. (huber) + */ + + my_remap_gt_regs (CFG_DFL_GT_REGS, CFG_GT_REGS); + +#ifdef CONFIG_PCI + gt_pci_config (); +#endif + /* mask all external interrupt sources */ + GT_REG_WRITE (CPU_INTERRUPT_MASK_REGISTER_LOW, 0); + GT_REG_WRITE (CPU_INTERRUPT_MASK_REGISTER_HIGH, 0); + /* new in >MV6436x */ + GT_REG_WRITE (CPU_INTERRUPT_1_MASK_REGISTER_LOW, 0); + GT_REG_WRITE (CPU_INTERRUPT_1_MASK_REGISTER_HIGH, 0); + /* --------------------- */ + GT_REG_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0); + GT_REG_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_HIGH, 0); + GT_REG_WRITE (PCI_1INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0); + GT_REG_WRITE (PCI_1INTERRUPT_CAUSE_MASK_REGISTER_HIGH, 0); + + /* Device and Boot bus settings + */ + memoryMapDeviceSpace(DEVICE0, 0, 0); + GT_REG_WRITE(DEVICE_BANK0PARAMETERS, 0); + memoryMapDeviceSpace(DEVICE1, 0, 0); + GT_REG_WRITE(DEVICE_BANK1PARAMETERS, 0); + memoryMapDeviceSpace(DEVICE2, 0, 0); + GT_REG_WRITE(DEVICE_BANK2PARAMETERS, 0); + memoryMapDeviceSpace(DEVICE3, 0, 0); + GT_REG_WRITE(DEVICE_BANK3PARAMETERS, 0); + + GT_REG_WRITE(DEVICE_BOOT_BANK_PARAMETERS, CFG_BOOT_PAR); + + gt_cpu_config(); + + /* MPP setup */ + GT_REG_WRITE (MPP_CONTROL0, CFG_MPP_CONTROL_0); + GT_REG_WRITE (MPP_CONTROL1, CFG_MPP_CONTROL_1); + GT_REG_WRITE (MPP_CONTROL2, CFG_MPP_CONTROL_2); + GT_REG_WRITE (MPP_CONTROL3, CFG_MPP_CONTROL_3); + + GT_REG_WRITE (GPP_LEVEL_CONTROL, CFG_GPP_LEVEL_CONTROL); + + return 0; +} + +/* various things to do after relocation */ + +int misc_init_r () +{ + u8 val; + + icache_enable (); +#ifdef CFG_L2 + l2cache_enable (); +#endif +#ifdef CONFIG_MPSC + mpsc_sdma_init (); + mpsc_init2 (); +#endif + + /* + * Enable trickle changing in RTC upon powerup + * No diode, 250 ohm series resistor + */ + val = 0xa5; + i2c_write(CFG_I2C_RTC_ADDR, 8, 1, &val, 1); + + return 0; +} + +int board_early_init_r(void) +{ + /* now relocate the debug serial driver */ + mpsc_putchar += gd->reloc_off; + mpsc_getchar += gd->reloc_off; + mpsc_test_char += gd->reloc_off; + + return 0; +} + +void after_reloc (ulong dest_addr, gd_t * gd) +{ + memoryMapDeviceSpace (BOOT_DEVICE, CFG_BOOT_SPACE, CFG_BOOT_SIZE); + +/* display_mem_map(); */ + + /* now, jump to the main U-Boot board init code */ + board_init_r (gd, dest_addr); + /* NOTREACHED */ +} + +/* + * Check Board Identity: + * right now, assume borad type. (there is just one...after all) + */ + +int checkboard (void) +{ + char *s = getenv("serial#"); + + printf("Board: %s", CFG_BOARD_NAME); + + if (s != NULL) { + puts(", serial# "); + puts(s); + } + putc('\n'); + + return (0); +} + +/* utility functions */ +void debug_led (int led, int mode) +{ +} + +int display_mem_map (void) +{ + int i, j; + unsigned int base, size, width; + + /* SDRAM */ + printf ("SD (DDR) RAM\n"); + for (i = 0; i <= BANK3; i++) { + base = memoryGetBankBaseAddress (i); + size = memoryGetBankSize (i); + if (size != 0) + printf ("BANK%d: base - 0x%08x\tsize - %dM bytes\n", + i, base, size >> 20); + } +#ifdef CONFIG_PCI + /* CPU's PCI windows */ + for (i = 0; i <= PCI_HOST1; i++) { + printf ("\nCPU's PCI %d windows\n", i); + base = pciGetSpaceBase (i, PCI_IO); + size = pciGetSpaceSize (i, PCI_IO); + printf (" IO: base - 0x%08x\tsize - %dM bytes\n", base, + size >> 20); + /* ronen currently only first PCI MEM is used 3 */ + for (j = 0; j <= PCI_REGION0; j++) { + base = pciGetSpaceBase (i, j); + size = pciGetSpaceSize (i, j); + printf ("MEMORY %d: base - 0x%08x\tsize - %dM bytes\n", + j, base, size >> 20); + } + } +#endif /* of CONFIG_PCI */ + + /* Bootrom */ + base = memoryGetDeviceBaseAddress (BOOT_DEVICE); /* Boot */ + size = memoryGetDeviceSize (BOOT_DEVICE); + width = memoryGetDeviceWidth (BOOT_DEVICE) * 8; + printf (" BOOT: base - 0x%08x size - %dM bytes\twidth - %d bits\t- FLASH\n", + base, size >> 20, width); + + return (0); +} + +/* DRAM check routines copied from gw8260 */ + +#if defined (CFG_DRAM_TEST) + +/*********************************************************************/ +/* NAME: move64() - moves a double word (64-bit) */ +/* */ +/* DESCRIPTION: */ +/* this function performs a double word move from the data at */ +/* the source pointer to the location at the destination pointer. */ +/* */ +/* INPUTS: */ +/* unsigned long long *src - pointer to data to move */ +/* */ +/* OUTPUTS: */ +/* unsigned long long *dest - pointer to locate to move data */ +/* */ +/* RETURNS: */ +/* None */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* May cloober fr0. */ +/* */ +/*********************************************************************/ +static void move64 (unsigned long long *src, unsigned long long *dest) +{ + asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ + "stfd 0, 0(4)" /* *dest = fpr0 */ + : : : "fr0"); /* Clobbers fr0 */ + return; +} + + +#if defined (CFG_DRAM_TEST_DATA) + +unsigned long long pattern[] = { + 0xaaaaaaaaaaaaaaaaULL, + 0xccccccccccccccccULL, + 0xf0f0f0f0f0f0f0f0ULL, + 0xff00ff00ff00ff00ULL, + 0xffff0000ffff0000ULL, + 0xffffffff00000000ULL, + 0x00000000ffffffffULL, + 0x0000ffff0000ffffULL, + 0x00ff00ff00ff00ffULL, + 0x0f0f0f0f0f0f0f0fULL, + 0x3333333333333333ULL, + 0x5555555555555555ULL +}; + +/*********************************************************************/ +/* NAME: mem_test_data() - test data lines for shorts and opens */ +/* */ +/* DESCRIPTION: */ +/* Tests data lines for shorts and opens by forcing adjacent data */ +/* to opposite states. Because the data lines could be routed in */ +/* an arbitrary manner the must ensure test patterns ensure that */ +/* every case is tested. By using the following series of binary */ +/* patterns every combination of adjacent bits is test regardless */ +/* of routing. */ +/* */ +/* ...101010101010101010101010 */ +/* ...110011001100110011001100 */ +/* ...111100001111000011110000 */ +/* ...111111110000000011111111 */ +/* */ +/* Carrying this out, gives us six hex patterns as follows: */ +/* */ +/* 0xaaaaaaaaaaaaaaaa */ +/* 0xcccccccccccccccc */ +/* 0xf0f0f0f0f0f0f0f0 */ +/* 0xff00ff00ff00ff00 */ +/* 0xffff0000ffff0000 */ +/* 0xffffffff00000000 */ +/* */ +/* The number test patterns will always be given by: */ +/* */ +/* log(base 2)(number data bits) = log2 (64) = 6 */ +/* */ +/* To test for short and opens to other signals on our boards. we */ +/* simply */ +/* test with the 1's complemnt of the paterns as well. */ +/* */ +/* OUTPUTS: */ +/* Displays failing test pattern */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* Assumes only one one SDRAM bank */ +/* */ +/*********************************************************************/ +int mem_test_data (void) +{ + unsigned long long *pmem = (unsigned long long *) CFG_MEMTEST_START; + unsigned long long temp64 = 0; + int num_patterns = sizeof (pattern) / sizeof (pattern[0]); + int i; + unsigned int hi, lo; + + for (i = 0; i < num_patterns; i++) { + move64 (&(pattern[i]), pmem); + move64 (pmem, &temp64); + + /* hi = (temp64>>32) & 0xffffffff; */ + /* lo = temp64 & 0xffffffff; */ + /* printf("\ntemp64 = 0x%08x%08x", hi, lo); */ + + hi = (pattern[i] >> 32) & 0xffffffff; + lo = pattern[i] & 0xffffffff; + /* printf("\npattern[%d] = 0x%08x%08x", i, hi, lo); */ + + if (temp64 != pattern[i]) { + printf ("\n Data Test Failed, pattern 0x%08x%08x", + hi, lo); + return 1; + } + } + + return 0; +} +#endif /* CFG_DRAM_TEST_DATA */ + +#if defined (CFG_DRAM_TEST_ADDRESS) +/*********************************************************************/ +/* NAME: mem_test_address() - test address lines */ +/* */ +/* DESCRIPTION: */ +/* This function performs a test to verify that each word im */ +/* memory is uniquly addressable. The test sequence is as follows: */ +/* */ +/* 1) write the address of each word to each word. */ +/* 2) verify that each location equals its address */ +/* */ +/* OUTPUTS: */ +/* Displays failing test pattern and address */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int mem_test_address (void) +{ + volatile unsigned int *pmem = + (volatile unsigned int *) CFG_MEMTEST_START; + const unsigned int size = (CFG_MEMTEST_END - CFG_MEMTEST_START) / 4; + unsigned int i; + + /* write address to each location */ + for (i = 0; i < size; i++) + pmem[i] = i; + + /* verify each loaction */ + for (i = 0; i < size; i++) { + if (pmem[i] != i) { + printf ("\n Address Test Failed at 0x%x", i); + return 1; + } + } + return 0; +} +#endif /* CFG_DRAM_TEST_ADDRESS */ + +#if defined (CFG_DRAM_TEST_WALK) +/*********************************************************************/ +/* NAME: mem_march() - memory march */ +/* */ +/* DESCRIPTION: */ +/* Marches up through memory. At each location verifies rmask if */ +/* read = 1. At each location write wmask if write = 1. Displays */ +/* failing address and pattern. */ +/* */ +/* INPUTS: */ +/* volatile unsigned long long * base - start address of test */ +/* unsigned int size - number of dwords(64-bit) to test */ +/* unsigned long long rmask - read verify mask */ +/* unsigned long long wmask - wrtie verify mask */ +/* short read - verifies rmask if read = 1 */ +/* short write - writes wmask if write = 1 */ +/* */ +/* OUTPUTS: */ +/* Displays failing test pattern and address */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int mem_march (volatile unsigned long long *base, + unsigned int size, + unsigned long long rmask, + unsigned long long wmask, short read, short write) +{ + unsigned int i; + unsigned long long temp = 0; + unsigned int hitemp, lotemp, himask, lomask; + + for (i = 0; i < size; i++) { + if (read != 0) { + /* temp = base[i]; */ + move64 ((unsigned long long *) &(base[i]), &temp); + if (rmask != temp) { + hitemp = (temp >> 32) & 0xffffffff; + lotemp = temp & 0xffffffff; + himask = (rmask >> 32) & 0xffffffff; + lomask = rmask & 0xffffffff; + + printf ("\n Walking one's test failed: address = 0x%08x," "\n\texpected 0x%08x%08x, found 0x%08x%08x", i << 3, himask, lomask, hitemp, lotemp); + return 1; + } + } + if (write != 0) { + /* base[i] = wmask; */ + move64 (&wmask, (unsigned long long *) &(base[i])); + } + } + return 0; +} +#endif /* CFG_DRAM_TEST_WALK */ + +/*********************************************************************/ +/* NAME: mem_test_walk() - a simple walking ones test */ +/* */ +/* DESCRIPTION: */ +/* Performs a walking ones through entire physical memory. The */ +/* test uses as series of memory marches, mem_march(), to verify */ +/* and write the test patterns to memory. The test sequence is as */ +/* follows: */ +/* 1) march writing 0000...0001 */ +/* 2) march verifying 0000...0001 , writing 0000...0010 */ +/* 3) repeat step 2 shifting masks left 1 bit each time unitl */ +/* the write mask equals 1000...0000 */ +/* 4) march verifying 1000...0000 */ +/* The test fails if any of the memory marches return a failure. */ +/* */ +/* OUTPUTS: */ +/* Displays which pass on the memory test is executing */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int mem_test_walk (void) +{ + unsigned long long mask; + volatile unsigned long long *pmem = + (volatile unsigned long long *) CFG_MEMTEST_START; + const unsigned long size = (CFG_MEMTEST_END - CFG_MEMTEST_START) / 8; + + unsigned int i; + + mask = 0x01; + + printf ("Initial Pass"); + mem_march (pmem, size, 0x0, 0x1, 0, 1); + + printf ("\b\b\b\b\b\b\b\b\b\b\b\b"); + printf (" "); + printf (" "); + printf ("\b\b\b\b\b\b\b\b\b\b\b\b"); + + for (i = 0; i < 63; i++) { + printf ("Pass %2d", i + 2); + if (mem_march (pmem, size, mask, mask << 1, 1, 1) != 0) { + /*printf("mask: 0x%x, pass: %d, ", mask, i); */ + return 1; + } + mask = mask << 1; + printf ("\b\b\b\b\b\b\b"); + } + + printf ("Last Pass"); + if (mem_march (pmem, size, 0, mask, 0, 1) != 0) { + /* printf("mask: 0x%x", mask); */ + return 1; + } + printf ("\b\b\b\b\b\b\b\b\b"); + printf (" "); + printf ("\b\b\b\b\b\b\b\b\b"); + + return 0; +} + +/*********************************************************************/ +/* NAME: testdram() - calls any enabled memory tests */ +/* */ +/* DESCRIPTION: */ +/* Runs memory tests if the environment test variables are set to */ +/* 'y'. */ +/* */ +/* INPUTS: */ +/* testdramdata - If set to 'y', data test is run. */ +/* testdramaddress - If set to 'y', address test is run. */ +/* testdramwalk - If set to 'y', walking ones test is run */ +/* */ +/* OUTPUTS: */ +/* None */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int testdram (void) +{ + char *s; + int rundata = 0; + int runaddress = 0; + int runwalk = 0; + +#ifdef CFG_DRAM_TEST_DATA + s = getenv ("testdramdata"); + rundata = (s && (*s == 'y')) ? 1 : 0; +#endif +#ifdef CFG_DRAM_TEST_ADDRESS + s = getenv ("testdramaddress"); + runaddress = (s && (*s == 'y')) ? 1 : 0; +#endif +#ifdef CFG_DRAM_TEST_WALK + s = getenv ("testdramwalk"); + runwalk = (s && (*s == 'y')) ? 1 : 0; +#endif + + if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) + printf ("Testing RAM from 0x%08x to 0x%08x ... " + "(don't panic... that will take a moment !!!!)\n", + CFG_MEMTEST_START, CFG_MEMTEST_END); +#ifdef CFG_DRAM_TEST_DATA + if (rundata == 1) { + printf ("Test DATA ... "); + if (mem_test_data () == 1) { + printf ("failed \n"); + return 1; + } else + printf ("ok \n"); + } +#endif +#ifdef CFG_DRAM_TEST_ADDRESS + if (runaddress == 1) { + printf ("Test ADDRESS ... "); + if (mem_test_address () == 1) { + printf ("failed \n"); + return 1; + } else + printf ("ok \n"); + } +#endif +#ifdef CFG_DRAM_TEST_WALK + if (runwalk == 1) { + printf ("Test WALKING ONEs ... "); + if (mem_test_walk () == 1) { + printf ("failed \n"); + return 1; + } else + printf ("ok \n"); + } +#endif + if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) + printf ("passed\n"); + return 0; + +} +#endif /* CFG_DRAM_TEST */ + +/* ronen - the below functions are used by the bootm function */ +/* - we map the base register to fbe00000 (same mapping as in the LSP) */ +/* - we turn off the RX gig dmas - to prevent the dma from overunning */ +/* the kernel data areas. */ +/* - we diable and invalidate the icache and dcache. */ +void my_remap_gt_regs_bootm (u32 cur_loc, u32 new_loc) +{ + u32 temp; + + temp = in_le32 ((u32 *) (new_loc + INTERNAL_SPACE_DECODE)); + if ((temp & 0xffff) == new_loc >> 16) + return; + + temp = (in_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE)) & + 0xffff0000) | (new_loc >> 16); + + out_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE), temp); + + while ((WORD_SWAP (*((volatile unsigned int *) (NONE_CACHEABLE | + new_loc | + (INTERNAL_SPACE_DECODE))))) + != temp); + +} diff --git a/board/prodrive/p3mx/pci.c b/board/prodrive/p3mx/pci.c new file mode 100644 index 0000000000..137739bede --- /dev/null +++ b/board/prodrive/p3mx/pci.c @@ -0,0 +1,1025 @@ +/* + * (C) Copyright 2000 + * 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 + * + */ +/* PCI.c - PCI functions */ + + +#include +#ifdef CONFIG_PCI +#include + +#ifdef CONFIG_PCI_PNP +void pciauto_config_init(struct pci_controller *hose); +int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar); +#endif + +#include "../../Marvell/include/pci.h" + +#undef DEBUG +#undef IDE_SET_NATIVE_MODE +static unsigned int local_buses[] = { 0, 0 }; + +static const unsigned char pci_irq_swizzle[2][PCI_MAX_DEVICES] = { + {0, 0, 0, 0, 0, 0, 0, 27, 27, [9 ... PCI_MAX_DEVICES - 1] = 0 }, + {0, 0, 0, 0, 0, 0, 0, 29, 29, [9 ... PCI_MAX_DEVICES - 1] = 0 }, +}; + +#ifdef CONFIG_USE_CPCIDVI +typedef struct { + unsigned int base; + unsigned int init; +} GT_CPCIDVI_ROM_T; + +static GT_CPCIDVI_ROM_T gt_cpcidvi_rom = {0, 0}; +#endif + +#ifdef DEBUG +static const unsigned int pci_bus_list[] = { PCI_0_MODE, PCI_1_MODE }; +static void gt_pci_bus_mode_display (PCI_HOST host) +{ + unsigned int mode; + + + mode = (GTREGREAD (pci_bus_list[host]) & (BIT4 | BIT5)) >> 4; + switch (mode) { + case 0: + printf ("PCI %d bus mode: Conventional PCI\n", host); + break; + case 1: + printf ("PCI %d bus mode: 66 Mhz PCIX\n", host); + break; + case 2: + printf ("PCI %d bus mode: 100 Mhz PCIX\n", host); + break; + case 3: + printf ("PCI %d bus mode: 133 Mhz PCIX\n", host); + break; + default: + printf ("Unknown BUS %d\n", mode); + } +} +#endif + +static const unsigned int pci_p2p_configuration_reg[] = { + PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION +}; + +static const unsigned int pci_configuration_address[] = { + PCI_0CONFIGURATION_ADDRESS, PCI_1CONFIGURATION_ADDRESS +}; + +static const unsigned int pci_configuration_data[] = { + PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, + PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER +}; + +static const unsigned int pci_error_cause_reg[] = { + PCI_0ERROR_CAUSE, PCI_1ERROR_CAUSE +}; + +static const unsigned int pci_arbiter_control[] = { + PCI_0ARBITER_CONTROL, PCI_1ARBITER_CONTROL +}; + +static const unsigned int pci_address_space_en[] = { + PCI_0_BASE_ADDR_REG_ENABLE, PCI_1_BASE_ADDR_REG_ENABLE +}; + +static const unsigned int pci_snoop_control_base_0_low[] = { + PCI_0SNOOP_CONTROL_BASE_0_LOW, PCI_1SNOOP_CONTROL_BASE_0_LOW +}; +static const unsigned int pci_snoop_control_top_0[] = { + PCI_0SNOOP_CONTROL_TOP_0, PCI_1SNOOP_CONTROL_TOP_0 +}; + +static const unsigned int pci_access_control_base_0_low[] = { + PCI_0ACCESS_CONTROL_BASE_0_LOW, PCI_1ACCESS_CONTROL_BASE_0_LOW +}; +static const unsigned int pci_access_control_top_0[] = { + PCI_0ACCESS_CONTROL_TOP_0, PCI_1ACCESS_CONTROL_TOP_0 +}; + +static const unsigned int pci_scs_bank_size[2][4] = { + {PCI_0SCS_0_BANK_SIZE, PCI_0SCS_1_BANK_SIZE, + PCI_0SCS_2_BANK_SIZE, PCI_0SCS_3_BANK_SIZE}, + {PCI_1SCS_0_BANK_SIZE, PCI_1SCS_1_BANK_SIZE, + PCI_1SCS_2_BANK_SIZE, PCI_1SCS_3_BANK_SIZE} +}; + +static const unsigned int pci_p2p_configuration[] = { + PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION +}; + + +/******************************************************************** +* pciWriteConfigReg - Write to a PCI configuration register +* - Make sure the GT is configured as a master before writing +* to another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* +* +* Inputs: unsigned int regOffset: The register offset as it apears in the GT spec +* (or any other PCI device spec) +* pciDevNum: The device number needs to be addressed. +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ +void pciWriteConfigReg (PCI_HOST host, unsigned int regOffset, + unsigned int pciDevNum, unsigned int data) +{ + volatile unsigned int DataForAddrReg; + unsigned int functionNum; + unsigned int busNum = 0; + unsigned int addr; + + if (pciDevNum > 32) /* illegal device Number */ + return; + if (pciDevNum == SELF) { /* configure our configuration space. */ + pciDevNum = + (GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) & + 0x1f; + busNum = GTREGREAD (pci_p2p_configuration_reg[host]) & + 0xff0000; + } + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xfc; + DataForAddrReg = + (regOffset | pciDevNum | functionNum | busNum) | BIT31; + GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg); + GT_REG_READ (pci_configuration_address[host], &addr); + if (addr != DataForAddrReg) + return; + GT_REG_WRITE (pci_configuration_data[host], data); +} + +/******************************************************************** +* pciReadConfigReg - Read from a PCI0 configuration register +* - Make sure the GT is configured as a master before reading +* from another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI +* spec) +* pciDevNum: The device number needs to be addressed. +* RETURNS: data , if the data == 0xffffffff check the master abort bit in the +* cause register to make sure the data is valid +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ +unsigned int pciReadConfigReg (PCI_HOST host, unsigned int regOffset, + unsigned int pciDevNum) +{ + volatile unsigned int DataForAddrReg; + unsigned int data; + unsigned int functionNum; + unsigned int busNum = 0; + + if (pciDevNum > 32) /* illegal device Number */ + return 0xffffffff; + if (pciDevNum == SELF) { /* configure our configuration space. */ + pciDevNum = + (GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) & + 0x1f; + busNum = GTREGREAD (pci_p2p_configuration_reg[host]) & + 0xff0000; + } + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xfc; + DataForAddrReg = + (regOffset | pciDevNum | functionNum | busNum) | BIT31; + GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg); + GT_REG_READ (pci_configuration_address[host], &data); + if (data != DataForAddrReg) + return 0xffffffff; + GT_REG_READ (pci_configuration_data[host], &data); + return data; +} + +/******************************************************************** +* pciOverBridgeWriteConfigReg - Write to a PCI configuration register where +* the agent is placed on another Bus. For more +* information read P2P in the PCI spec. +* +* Inputs: unsigned int regOffset - The register offset as it apears in the +* GT spec (or any other PCI device spec). +* unsigned int pciDevNum - The device number needs to be addressed. +* unsigned int busNum - On which bus does the Target agent connect +* to. +* unsigned int data - data to be written. +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|01| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +* The configuration Address is configure as type-I (bits[1:0] = '01') due to +* PCI spec referring to P2P. +* +*********************************************************************/ +void pciOverBridgeWriteConfigReg (PCI_HOST host, + unsigned int regOffset, + unsigned int pciDevNum, + unsigned int busNum, unsigned int data) +{ + unsigned int DataForReg; + unsigned int functionNum; + + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xff; + busNum = busNum << 16; + if (pciDevNum == SELF) { /* This board */ + DataForReg = (regOffset | pciDevNum | functionNum) | BIT0; + } else { + DataForReg = (regOffset | pciDevNum | functionNum | busNum) | + BIT31 | BIT0; + } + GT_REG_WRITE (pci_configuration_address[host], DataForReg); + GT_REG_WRITE (pci_configuration_data[host], data); +} + + +/******************************************************************** +* pciOverBridgeReadConfigReg - Read from a PCIn configuration register where +* the agent target locate on another PCI bus. +* - Make sure the GT is configured as a master +* before reading from another device on the PCI. +* - The function takes care of Big/Little endian +* conversion. +* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI +* spec). (configuration register offset.) +* pciDevNum: The device number needs to be addressed. +* busNum: the Bus number where the agent is place. +* RETURNS: data , if the data == 0xffffffff check the master abort bit in the +* cause register to make sure the data is valid +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|01| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ +unsigned int pciOverBridgeReadConfigReg (PCI_HOST host, + unsigned int regOffset, + unsigned int pciDevNum, + unsigned int busNum) +{ + unsigned int DataForReg; + unsigned int data; + unsigned int functionNum; + + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xff; + busNum = busNum << 16; + if (pciDevNum == SELF) { /* This board */ + DataForReg = (regOffset | pciDevNum | functionNum) | BIT31; + } else { /* agent on another bus */ + + DataForReg = (regOffset | pciDevNum | functionNum | busNum) | + BIT0 | BIT31; + } + GT_REG_WRITE (pci_configuration_address[host], DataForReg); + GT_REG_READ (pci_configuration_data[host], &data); + return data; +} + + +/******************************************************************** +* pciGetRegOffset - Gets the register offset for this region config. +* +* INPUT: Bus, Region - The bus and region we ask for its base address. +* OUTPUT: N/A +* RETURNS: PCI register base address +*********************************************************************/ +static unsigned int pciGetRegOffset (PCI_HOST host, PCI_REGION region) +{ + switch (host) { + case PCI_HOST0: + switch (region) { + case PCI_IO: + return PCI_0I_O_LOW_DECODE_ADDRESS; + case PCI_REGION0: + return PCI_0MEMORY0_LOW_DECODE_ADDRESS; + case PCI_REGION1: + return PCI_0MEMORY1_LOW_DECODE_ADDRESS; + case PCI_REGION2: + return PCI_0MEMORY2_LOW_DECODE_ADDRESS; + case PCI_REGION3: + return PCI_0MEMORY3_LOW_DECODE_ADDRESS; + } + case PCI_HOST1: + switch (region) { + case PCI_IO: + return PCI_1I_O_LOW_DECODE_ADDRESS; + case PCI_REGION0: + return PCI_1MEMORY0_LOW_DECODE_ADDRESS; + case PCI_REGION1: + return PCI_1MEMORY1_LOW_DECODE_ADDRESS; + case PCI_REGION2: + return PCI_1MEMORY2_LOW_DECODE_ADDRESS; + case PCI_REGION3: + return PCI_1MEMORY3_LOW_DECODE_ADDRESS; + } + } + return PCI_0MEMORY0_LOW_DECODE_ADDRESS; +} + +static unsigned int pciGetRemapOffset (PCI_HOST host, PCI_REGION region) +{ + switch (host) { + case PCI_HOST0: + switch (region) { + case PCI_IO: + return PCI_0I_O_ADDRESS_REMAP; + case PCI_REGION0: + return PCI_0MEMORY0_ADDRESS_REMAP; + case PCI_REGION1: + return PCI_0MEMORY1_ADDRESS_REMAP; + case PCI_REGION2: + return PCI_0MEMORY2_ADDRESS_REMAP; + case PCI_REGION3: + return PCI_0MEMORY3_ADDRESS_REMAP; + } + case PCI_HOST1: + switch (region) { + case PCI_IO: + return PCI_1I_O_ADDRESS_REMAP; + case PCI_REGION0: + return PCI_1MEMORY0_ADDRESS_REMAP; + case PCI_REGION1: + return PCI_1MEMORY1_ADDRESS_REMAP; + case PCI_REGION2: + return PCI_1MEMORY2_ADDRESS_REMAP; + case PCI_REGION3: + return PCI_1MEMORY3_ADDRESS_REMAP; + } + } + return PCI_0MEMORY0_ADDRESS_REMAP; +} + +/******************************************************************** +* pciGetBaseAddress - Gets the base address of a PCI. +* - If the PCI size is 0 then this base address has no meaning!!! +* +* +* INPUT: Bus, Region - The bus and region we ask for its base address. +* OUTPUT: N/A +* RETURNS: PCI base address. +*********************************************************************/ +unsigned int pciGetBaseAddress (PCI_HOST host, PCI_REGION region) +{ + unsigned int regBase; + unsigned int regEnd; + unsigned int regOffset = pciGetRegOffset (host, region); + + GT_REG_READ (regOffset, ®Base); + GT_REG_READ (regOffset + 8, ®End); + + if (regEnd <= regBase) + return 0xffffffff; /* ERROR !!! */ + + regBase = regBase << 16; + return regBase; +} + +bool pciMapSpace (PCI_HOST host, PCI_REGION region, unsigned int remapBase, + unsigned int bankBase, unsigned int bankLength) +{ + unsigned int low = 0xfff; + unsigned int high = 0x0; + unsigned int regOffset = pciGetRegOffset (host, region); + unsigned int remapOffset = pciGetRemapOffset (host, region); + + if (bankLength != 0) { + low = (bankBase >> 16) & 0xffff; + high = ((bankBase + bankLength) >> 16) - 1; + } + + GT_REG_WRITE (regOffset, low | (1 << 24)); /* no swapping */ + GT_REG_WRITE (regOffset + 8, high); + + if (bankLength != 0) { /* must do AFTER writing maps */ + GT_REG_WRITE (remapOffset, remapBase >> 16); /* sorry, 32 bits only. + dont support upper 32 + in this driver */ + } + return true; +} + +unsigned int pciGetSpaceBase (PCI_HOST host, PCI_REGION region) +{ + unsigned int low; + unsigned int regOffset = pciGetRegOffset (host, region); + + GT_REG_READ (regOffset, &low); + return (low & 0xffff) << 16; +} + +unsigned int pciGetSpaceSize (PCI_HOST host, PCI_REGION region) +{ + unsigned int low, high; + unsigned int regOffset = pciGetRegOffset (host, region); + + GT_REG_READ (regOffset, &low); + GT_REG_READ (regOffset + 8, &high); + return ((high & 0xffff) + 1) << 16; +} + + +/* ronen - 7/Dec/03*/ +/******************************************************************** +* gtPciDisable/EnableInternalBAR - This function enable/disable PCI BARS. +* Inputs: one of the PCI BAR +*********************************************************************/ +void gtPciEnableInternalBAR (PCI_HOST host, PCI_INTERNAL_BAR pciBAR) +{ + RESET_REG_BITS (pci_address_space_en[host], BIT0 << pciBAR); +} + +void gtPciDisableInternalBAR (PCI_HOST host, PCI_INTERNAL_BAR pciBAR) +{ + SET_REG_BITS (pci_address_space_en[host], BIT0 << pciBAR); +} + +/******************************************************************** +* pciMapMemoryBank - Maps PCI_host memory bank "bank" for the slave. +* +* Inputs: base and size of PCI SCS +*********************************************************************/ +void pciMapMemoryBank (PCI_HOST host, MEMORY_BANK bank, + unsigned int pciDramBase, unsigned int pciDramSize) +{ + /*ronen different function for 3rd bank. */ + unsigned int offset = (bank < 2) ? bank * 8 : 0x100 + (bank - 2) * 8; + + pciDramBase = pciDramBase & 0xfffff000; + pciDramBase = pciDramBase | (pciReadConfigReg (host, + PCI_SCS_0_BASE_ADDRESS + + offset, + SELF) & 0x00000fff); + pciWriteConfigReg (host, PCI_SCS_0_BASE_ADDRESS + offset, SELF, + pciDramBase); + if (pciDramSize == 0) + pciDramSize++; + GT_REG_WRITE (pci_scs_bank_size[host][bank], pciDramSize - 1); + gtPciEnableInternalBAR (host, bank); +} + +/******************************************************************** +* pciSetRegionFeatures - This function modifys one of the 8 regions with +* feature bits given as an input. +* - Be advised to check the spec before modifying them. +* Inputs: PCI_PROTECT_REGION region - one of the eight regions. +* unsigned int features - See file: pci.h there are defintion for those +* region features. +* unsigned int baseAddress - The region base Address. +* unsigned int topAddress - The region top Address. +* Returns: false if one of the parameters is erroneous true otherwise. +*********************************************************************/ +bool pciSetRegionFeatures (PCI_HOST host, PCI_ACCESS_REGIONS region, + unsigned int features, unsigned int baseAddress, + unsigned int regionLength) +{ + unsigned int accessLow; + unsigned int accessHigh; + unsigned int accessTop = baseAddress + regionLength; + + if (regionLength == 0) { /* close the region. */ + pciDisableAccessRegion (host, region); + return true; + } + /* base Address is store is bits [11:0] */ + accessLow = (baseAddress & 0xfff00000) >> 20; + /* All the features are update according to the defines in pci.h (to be on + the safe side we disable bits: [11:0] */ + accessLow = accessLow | (features & 0xfffff000); + /* write to the Low Access Region register */ + GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region, + accessLow); + + accessHigh = (accessTop & 0xfff00000) >> 20; + + /* write to the High Access Region register */ + GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region, + accessHigh - 1); + return true; +} + +/******************************************************************** +* pciDisableAccessRegion - Disable The given Region by writing MAX size +* to its low Address and MIN size to its high Address. +* +* Inputs: PCI_ACCESS_REGIONS region - The region we to be Disabled. +* Returns: N/A. +*********************************************************************/ +void pciDisableAccessRegion (PCI_HOST host, PCI_ACCESS_REGIONS region) +{ + /* writing back the registers default values. */ + GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region, + 0x01001fff); + GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region, 0); +} + +/******************************************************************** +* pciArbiterEnable - Enables PCI-0`s Arbitration mechanism. +* +* Inputs: N/A +* Returns: true. +*********************************************************************/ +bool pciArbiterEnable (PCI_HOST host) +{ + unsigned int regData; + + GT_REG_READ (pci_arbiter_control[host], ®Data); + GT_REG_WRITE (pci_arbiter_control[host], regData | BIT31); + return true; +} + +/******************************************************************** +* pciArbiterDisable - Disable PCI-0`s Arbitration mechanism. +* +* Inputs: N/A +* Returns: true +*********************************************************************/ +bool pciArbiterDisable (PCI_HOST host) +{ + unsigned int regData; + + GT_REG_READ (pci_arbiter_control[host], ®Data); + GT_REG_WRITE (pci_arbiter_control[host], regData & 0x7fffffff); + return true; +} + +/******************************************************************** +* pciSetArbiterAgentsPriority - Priority setup for the PCI agents (Hi or Low) +* +* Inputs: PCI_AGENT_PRIO internalAgent - priotity for internal agent. +* PCI_AGENT_PRIO externalAgent0 - priotity for external#0 agent. +* PCI_AGENT_PRIO externalAgent1 - priotity for external#1 agent. +* PCI_AGENT_PRIO externalAgent2 - priotity for external#2 agent. +* PCI_AGENT_PRIO externalAgent3 - priotity for external#3 agent. +* PCI_AGENT_PRIO externalAgent4 - priotity for external#4 agent. +* PCI_AGENT_PRIO externalAgent5 - priotity for external#5 agent. +* Returns: true +*********************************************************************/ +bool pciSetArbiterAgentsPriority (PCI_HOST host, PCI_AGENT_PRIO internalAgent, + PCI_AGENT_PRIO externalAgent0, + PCI_AGENT_PRIO externalAgent1, + PCI_AGENT_PRIO externalAgent2, + PCI_AGENT_PRIO externalAgent3, + PCI_AGENT_PRIO externalAgent4, + PCI_AGENT_PRIO externalAgent5) +{ + unsigned int regData; + unsigned int writeData; + + GT_REG_READ (pci_arbiter_control[host], ®Data); + writeData = (internalAgent << 7) + (externalAgent0 << 8) + + (externalAgent1 << 9) + (externalAgent2 << 10) + + (externalAgent3 << 11) + (externalAgent4 << 12) + + (externalAgent5 << 13); + regData = (regData & 0xffffc07f) | writeData; + GT_REG_WRITE (pci_arbiter_control[host], regData & regData); + return true; +} + +/******************************************************************** +* pciParkingDisable - Park on last option disable, with this function you can +* disable the park on last mechanism for each agent. +* disabling this option for all agents results parking +* on the internal master. +* +* Inputs: PCI_AGENT_PARK internalAgent - parking Disable for internal agent. +* PCI_AGENT_PARK externalAgent0 - parking Disable for external#0 agent. +* PCI_AGENT_PARK externalAgent1 - parking Disable for external#1 agent. +* PCI_AGENT_PARK externalAgent2 - parking Disable for external#2 agent. +* PCI_AGENT_PARK externalAgent3 - parking Disable for external#3 agent. +* PCI_AGENT_PARK externalAgent4 - parking Disable for external#4 agent. +* PCI_AGENT_PARK externalAgent5 - parking Disable for external#5 agent. +* Returns: true +*********************************************************************/ +bool pciParkingDisable (PCI_HOST host, PCI_AGENT_PARK internalAgent, + PCI_AGENT_PARK externalAgent0, + PCI_AGENT_PARK externalAgent1, + PCI_AGENT_PARK externalAgent2, + PCI_AGENT_PARK externalAgent3, + PCI_AGENT_PARK externalAgent4, + PCI_AGENT_PARK externalAgent5) +{ + unsigned int regData; + unsigned int writeData; + + GT_REG_READ (pci_arbiter_control[host], ®Data); + writeData = (internalAgent << 14) + (externalAgent0 << 15) + + (externalAgent1 << 16) + (externalAgent2 << 17) + + (externalAgent3 << 18) + (externalAgent4 << 19) + + (externalAgent5 << 20); + regData = (regData & ~(0x7f << 14)) | writeData; + GT_REG_WRITE (pci_arbiter_control[host], regData); + return true; +} + +/******************************************************************** +* pciEnableBrokenAgentDetection - A master is said to be broken if it fails to +* respond to grant assertion within a window specified in +* the input value: 'brokenValue'. +* +* Inputs: unsigned char brokenValue - A value which limits the Master to hold the +* grant without asserting frame. +* Returns: Error for illegal broken value otherwise true. +*********************************************************************/ +bool pciEnableBrokenAgentDetection (PCI_HOST host, unsigned char brokenValue) +{ + unsigned int data; + unsigned int regData; + + if (brokenValue > 0xf) + return false; /* brokenValue must be 4 bit */ + data = brokenValue << 3; + GT_REG_READ (pci_arbiter_control[host], ®Data); + regData = (regData & 0xffffff87) | data; + GT_REG_WRITE (pci_arbiter_control[host], regData | BIT1); + return true; +} + +/******************************************************************** +* pciDisableBrokenAgentDetection - This function disable the Broken agent +* Detection mechanism. +* NOTE: This operation may cause a dead lock on the +* pci0 arbitration. +* +* Inputs: N/A +* Returns: true. +*********************************************************************/ +bool pciDisableBrokenAgentDetection (PCI_HOST host) +{ + unsigned int regData; + + GT_REG_READ (pci_arbiter_control[host], ®Data); + regData = regData & 0xfffffffd; + GT_REG_WRITE (pci_arbiter_control[host], regData); + return true; +} + +/******************************************************************** +* pciP2PConfig - This function set the PCI_n P2P configurate. +* For more information on the P2P read PCI spec. +* +* Inputs: unsigned int SecondBusLow - Secondery PCI interface Bus Range Lower +* Boundry. +* unsigned int SecondBusHigh - Secondry PCI interface Bus Range upper +* Boundry. +* unsigned int busNum - The CPI bus number to which the PCI interface +* is connected. +* unsigned int devNum - The PCI interface's device number. +* +* Returns: true. +*********************************************************************/ +bool pciP2PConfig (PCI_HOST host, unsigned int SecondBusLow, + unsigned int SecondBusHigh, + unsigned int busNum, unsigned int devNum) +{ + unsigned int regData; + + regData = (SecondBusLow & 0xff) | ((SecondBusHigh & 0xff) << 8) | + ((busNum & 0xff) << 16) | ((devNum & 0x1f) << 24); + GT_REG_WRITE (pci_p2p_configuration[host], regData); + return true; +} + +/******************************************************************** +* pciSetRegionSnoopMode - This function modifys one of the 4 regions which +* supports Cache Coherency in the PCI_n interface. +* Inputs: region - One of the four regions. +* snoopType - There is four optional Types: +* 1. No Snoop. +* 2. Snoop to WT region. +* 3. Snoop to WB region. +* 4. Snoop & Invalidate to WB region. +* baseAddress - Base Address of this region. +* regionLength - Region length. +* Returns: false if one of the parameters is wrong otherwise return true. +*********************************************************************/ +bool pciSetRegionSnoopMode (PCI_HOST host, PCI_SNOOP_REGION region, + PCI_SNOOP_TYPE snoopType, + unsigned int baseAddress, + unsigned int regionLength) +{ + unsigned int snoopXbaseAddress; + unsigned int snoopXtopAddress; + unsigned int data; + unsigned int snoopHigh = baseAddress + regionLength; + + if ((region > PCI_SNOOP_REGION3) || (snoopType > PCI_SNOOP_WB)) + return false; + snoopXbaseAddress = + pci_snoop_control_base_0_low[host] + 0x10 * region; + snoopXtopAddress = pci_snoop_control_top_0[host] + 0x10 * region; + if (regionLength == 0) { /* closing the region */ + GT_REG_WRITE (snoopXbaseAddress, 0x0000ffff); + GT_REG_WRITE (snoopXtopAddress, 0); + return true; + } + baseAddress = baseAddress & 0xfff00000; /* Granularity of 1MByte */ + data = (baseAddress >> 20) | snoopType << 12; + GT_REG_WRITE (snoopXbaseAddress, data); + snoopHigh = (snoopHigh & 0xfff00000) >> 20; + GT_REG_WRITE (snoopXtopAddress, snoopHigh - 1); + return true; +} + +static int gt_read_config_dword (struct pci_controller *hose, + pci_dev_t dev, int offset, u32 * value) +{ + int bus = PCI_BUS (dev); + + if ((bus == local_buses[0]) || (bus == local_buses[1])) { + *value = pciReadConfigReg ((PCI_HOST) hose->cfg_addr, offset, + PCI_DEV (dev)); + } else { + *value = pciOverBridgeReadConfigReg ((PCI_HOST) hose-> + cfg_addr, offset, + PCI_DEV (dev), bus); + } + + return 0; +} + +static int gt_write_config_dword (struct pci_controller *hose, + pci_dev_t dev, int offset, u32 value) +{ + int bus = PCI_BUS (dev); + + if ((bus == local_buses[0]) || (bus == local_buses[1])) { + pciWriteConfigReg ((PCI_HOST) hose->cfg_addr, offset, + PCI_DEV (dev), value); + } else { + pciOverBridgeWriteConfigReg ((PCI_HOST) hose->cfg_addr, + offset, PCI_DEV (dev), bus, + value); + } + return 0; +} + + +static void gt_setup_ide (struct pci_controller *hose, + pci_dev_t dev, struct pci_config_table *entry) +{ + static const int ide_bar[] = { 8, 4, 8, 4, 0, 0 }; + u32 bar_response, bar_value; + int bar; + + for (bar = 0; bar < 6; bar++) { + /*ronen different function for 3rd bank. */ + unsigned int offset = + (bar < 2) ? bar * 8 : 0x100 + (bar - 2) * 8; + + pci_hose_write_config_dword (hose, dev, PCI_BASE_ADDRESS_0 + offset, + 0x0); + pci_hose_read_config_dword (hose, dev, PCI_BASE_ADDRESS_0 + offset, + &bar_response); + + pciauto_region_allocate (bar_response & + PCI_BASE_ADDRESS_SPACE_IO ? hose-> + pci_io : hose->pci_mem, ide_bar[bar], + &bar_value); + + pci_hose_write_config_dword (hose, dev, PCI_BASE_ADDRESS_0 + bar * 4, + bar_value); + } +} + +#ifdef CONFIG_USE_CPCIDVI +static void gt_setup_cpcidvi (struct pci_controller *hose, + pci_dev_t dev, struct pci_config_table *entry) +{ + u32 bar_value, pci_response; + + pci_hose_read_config_dword (hose, dev, PCI_COMMAND, &pci_response); + pci_hose_write_config_dword (hose, dev, PCI_BASE_ADDRESS_0, 0xffffffff); + pci_hose_read_config_dword (hose, dev, PCI_BASE_ADDRESS_0, &pci_response); + pciauto_region_allocate (hose->pci_mem, 0x01000000, &bar_value); + pci_hose_write_config_dword (hose, dev, PCI_BASE_ADDRESS_0, (bar_value & 0xffffff00)); + pci_hose_write_config_dword (hose, dev, PCI_ROM_ADDRESS, 0x0); + pciauto_region_allocate (hose->pci_mem, 0x40000, &bar_value); + pci_hose_write_config_dword (hose, dev, PCI_ROM_ADDRESS, (bar_value & 0xffffff00) | 0x01); + gt_cpcidvi_rom.base = bar_value & 0xffffff00; + gt_cpcidvi_rom.init = 1; +} + +unsigned char gt_cpcidvi_in8(unsigned int offset) +{ + unsigned char data; + + if (gt_cpcidvi_rom.init == 0) { + return(0); + } + data = in8((offset & 0x04) + 0x3f000 + gt_cpcidvi_rom.base); + return(data); +} + +void gt_cpcidvi_out8(unsigned int offset, unsigned char data) +{ + unsigned int off; + + if (gt_cpcidvi_rom.init == 0) { + return; + } + off = data; + off = ((off << 3) & 0x7f8) + (offset & 0x4) + 0x3e000 + gt_cpcidvi_rom.base; + in8(off); + return; +} +#endif + +/* TODO BJW: Change this for DB64360. This was pulled from the EV64260 */ +/* and is curently not called *. */ +#if 0 +static void gt_fixup_irq (struct pci_controller *hose, pci_dev_t dev) +{ + unsigned char pin, irq; + + pci_read_config_byte (dev, PCI_INTERRUPT_PIN, &pin); + + if (pin == 1) { /* only allow INT A */ + irq = pci_irq_swizzle[(PCI_HOST) hose-> + cfg_addr][PCI_DEV (dev)]; + if (irq) + pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); + } +} +#endif + +struct pci_config_table gt_config_table[] = { +#ifdef CONFIG_USE_CPCIDVI + {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69030, PCI_CLASS_DISPLAY_VGA, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, gt_setup_cpcidvi}, +#endif + {PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, gt_setup_ide}, + {} +}; + +struct pci_controller pci0_hose = { +/* fixup_irq: gt_fixup_irq, */ + config_table:gt_config_table, +}; + +struct pci_controller pci1_hose = { +/* fixup_irq: gt_fixup_irq, */ + config_table:gt_config_table, +}; + +void pci_init_board (void) +{ + unsigned int command; +#ifdef CONFIG_PCI_PNP + unsigned int bar; +#endif +#ifdef DEBUG + gt_pci_bus_mode_display (PCI_HOST0); +#endif +#ifdef CONFIG_USE_CPCIDVI + gt_cpcidvi_rom.init = 0; + gt_cpcidvi_rom.base = 0; +#endif + + pci0_hose.config_table = gt_config_table; + pci1_hose.config_table = gt_config_table; + +#ifdef CONFIG_USE_CPCIDVI + gt_config_table[0].config_device = gt_setup_cpcidvi; +#endif + gt_config_table[1].config_device = gt_setup_ide; + + pci0_hose.first_busno = 0; + pci0_hose.last_busno = 0xff; + local_buses[0] = pci0_hose.first_busno; + + /* PCI memory space */ + pci_set_region (pci0_hose.regions + 0, + CFG_PCI0_0_MEM_SPACE, + CFG_PCI0_0_MEM_SPACE, + CFG_PCI0_MEM_SIZE, PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region (pci0_hose.regions + 1, + CFG_PCI0_IO_SPACE_PCI, + CFG_PCI0_IO_SPACE, CFG_PCI0_IO_SIZE, PCI_REGION_IO); + + pci_set_ops (&pci0_hose, + pci_hose_read_config_byte_via_dword, + pci_hose_read_config_word_via_dword, + gt_read_config_dword, + pci_hose_write_config_byte_via_dword, + pci_hose_write_config_word_via_dword, + gt_write_config_dword); + pci0_hose.region_count = 2; + + pci0_hose.cfg_addr = (unsigned int *) PCI_HOST0; + + pci_register_hose (&pci0_hose); + pciArbiterDisable(PCI_HOST0); /* on PMC modules no arbiter is used */ + pciParkingDisable (PCI_HOST0, 1, 1, 1, 1, 1, 1, 1); + command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MASTER; + pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command); + command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MEMORY; + pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command); + +#ifdef CONFIG_PCI_PNP + pciauto_config_init(&pci0_hose); + pciauto_region_allocate(pci0_hose.pci_io, 0x400, &bar); +#endif +#ifdef CONFIG_PCI_SCAN_SHOW + printf("PCI: Bus Dev VenId DevId Class Int\n"); +#endif + pci0_hose.last_busno = pci_hose_scan_bus (&pci0_hose, pci0_hose.first_busno); + +#ifdef DEBUG + gt_pci_bus_mode_display (PCI_HOST1); +#endif + pci1_hose.first_busno = pci0_hose.last_busno + 1; + pci1_hose.last_busno = 0xff; + pci1_hose.current_busno = pci1_hose.first_busno; + local_buses[1] = pci1_hose.first_busno; + + /* PCI memory space */ + pci_set_region (pci1_hose.regions + 0, + CFG_PCI1_0_MEM_SPACE, + CFG_PCI1_0_MEM_SPACE, + CFG_PCI1_MEM_SIZE, PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region (pci1_hose.regions + 1, + CFG_PCI1_IO_SPACE_PCI, + CFG_PCI1_IO_SPACE, CFG_PCI1_IO_SIZE, PCI_REGION_IO); + + pci_set_ops (&pci1_hose, + pci_hose_read_config_byte_via_dword, + pci_hose_read_config_word_via_dword, + gt_read_config_dword, + pci_hose_write_config_byte_via_dword, + pci_hose_write_config_word_via_dword, + gt_write_config_dword); + + pci1_hose.region_count = 2; + + pci1_hose.cfg_addr = (unsigned int *) PCI_HOST1; + + pci_register_hose (&pci1_hose); + + pciArbiterEnable (PCI_HOST1); + pciParkingDisable (PCI_HOST1, 1, 1, 1, 1, 1, 1, 1); + + command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MASTER; + pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); + +#ifdef CONFIG_PCI_PNP + pciauto_config_init(&pci1_hose); + pciauto_region_allocate(pci1_hose.pci_io, 0x400, &bar); +#endif + pci1_hose.last_busno = pci_hose_scan_bus (&pci1_hose, pci1_hose.first_busno); + + command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MEMORY; + pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); + +} +#endif /* of CONFIG_PCI */ diff --git a/board/prodrive/p3mx/ppc_error_no.h b/board/prodrive/p3mx/ppc_error_no.h new file mode 100644 index 0000000000..53687c86bb --- /dev/null +++ b/board/prodrive/p3mx/ppc_error_no.h @@ -0,0 +1,164 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus + * + * 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 + */ + +/* + * BK Id: SCCS/s.errno.h 1.9 06/05/01 21:45:21 paulus + */ +#ifndef _MV_PPC_ERRNO_H +#define _MV_PPC_ERRNO_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ +#define EDEADLOCK 58 /* File locking deadlock error */ +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +/* Should never be seen by user programs */ +#define ERESTARTSYS 512 +#define ERESTARTNOINTR 513 +#define ERESTARTNOHAND 514 /* restart if no handler.. */ +#define ENOIOCTLCMD 515 /* No ioctl command */ + +#define _LAST_ERRNO 515 + +#endif diff --git a/board/prodrive/p3mx/sdram_init.c b/board/prodrive/p3mx/sdram_init.c new file mode 100644 index 0000000000..b4556debff --- /dev/null +++ b/board/prodrive/p3mx/sdram_init.c @@ -0,0 +1,433 @@ +/* + * (C) Copyright 2001 + * Josh Huber , Mission Critical Linux, 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 + */ + +/************************************************************************* + * adaption for the Marvell DB64460 Board + * Ingo Assmus (ingo.assmus@keymile.com) + *************************************************************************/ + +/* sdram_init.c - automatic memory sizing */ + +#include +#include <74xx_7xx.h> +#include "../../Marvell/include/memory.h" +#include "../../Marvell/include/pci.h" +#include "../../Marvell/include/mv_gen_reg.h" +#include + +#include "eth.h" +#include "mpsc.h" +#include "../../Marvell/common/i2c.h" +#include "64460.h" +#include "mv_regs.h" + +DECLARE_GLOBAL_DATA_PTR; + +#undef DEBUG +#define MAP_PCI + +#ifdef DEBUG +#define DP(x) x +#else +#define DP(x) +#endif + +int set_dfcdlInit (void); /* setup delay line of Mv64460 */ +int mvDmaIsChannelActive (int); +int mvDmaSetMemorySpace (ulong, ulong, ulong, ulong, ulong); +int mvDmaTransfer (int, ulong, ulong, ulong, ulong); + +#define D_CACHE_FLUSH_LINE(addr, offset) \ + { \ + __asm__ __volatile__ ("dcbf %0,%1" : : "r" (addr), "r" (offset)); \ + } + +int memory_map_bank (unsigned int bankNo, + unsigned int bankBase, unsigned int bankLength) +{ +#ifdef MAP_PCI + PCI_HOST host; +#endif + +#ifdef DEBUG + if (bankLength > 0) + printf ("mapping bank %d at %08x - %08x\n", + bankNo, bankBase, bankBase + bankLength - 1); + else + printf ("unmapping bank %d\n", bankNo); +#endif + + memoryMapBank (bankNo, bankBase, bankLength); + +#ifdef MAP_PCI + for (host = PCI_HOST0; host <= PCI_HOST1; host++) { + const int features = + PREFETCH_ENABLE | + DELAYED_READ_ENABLE | + AGGRESSIVE_PREFETCH | + READ_LINE_AGGRESSIVE_PREFETCH | + READ_MULTI_AGGRESSIVE_PREFETCH | + MAX_BURST_4 | PCI_NO_SWAP; + + pciMapMemoryBank (host, bankNo, bankBase, bankLength); + + pciSetRegionSnoopMode (host, bankNo, PCI_SNOOP_WB, bankBase, + bankLength); + + pciSetRegionFeatures (host, bankNo, features, bankBase, + bankLength); + } +#endif + + return 0; +} + +/* + * Check memory range for valid RAM. A simple memory test determines + * the actually available RAM size between addresses `base' and + * `base + maxsize'. Some (not all) hardware errors are detected: + * - short between address lines + * - short between data lines + */ +long int dram_size (long int *base, long int maxsize) +{ + volatile long int *addr, *b = base; + long int cnt, val, save1, save2; + +#define STARTVAL (1<<20) /* start test at 1M */ + for (cnt = STARTVAL / sizeof (long); cnt < maxsize / sizeof (long); + cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + + save1 = *addr; /* save contents of addr */ + save2 = *b; /* save contents of base */ + + *addr = cnt; /* write cnt to addr */ + *b = 0; /* put null at base */ + + /* check at base address */ + if ((*b) != 0) { + *addr = save1; /* restore *addr */ + *b = save2; /* restore *b */ + return (0); + } + val = *addr; /* read *addr */ + val = *addr; /* read *addr */ + + *addr = save1; + *b = save2; + + if (val != cnt) { + DP (printf + ("Found %08x at Address %08x (failure)\n", + (unsigned int) val, (unsigned int) addr)); + /* fix boundary condition.. STARTVAL means zero */ + if (cnt == STARTVAL / sizeof (long)) + cnt = 0; + return (cnt * sizeof (long)); + } + } + + return maxsize; +} + +#define SDRAM_NORMAL 0x0 +#define SDRAM_PRECHARGE_ALL 0x1 +#define SDRAM_REFRESH_ALL 0x2 +#define SDRAM_MODE_REG_SETUP 0x3 +#define SDRAM_XTEN_MODE_REG_SETUP 0x4 +#define SDRAM_NOP 0x5 +#define SDRAM_SELF_REFRESH 0x7 + +long int initdram (int board_type) +{ + int tmp; + int start; + ulong size; + ulong memSpaceAttr; + ulong dest; + + /* first disable all banks */ + memory_map_bank(0, 0, 0); + memory_map_bank(1, 0, 0); + memory_map_bank(2, 0, 0); + memory_map_bank(3, 0, 0); + + /* calibrate delay lines */ + set_dfcdlInit(); + + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_NOP); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* SDRAM controller configuration */ +#ifdef CONFIG_MV64460_ECC + GT_REG_WRITE(MV64460_SDRAM_CONFIG, 0x58201400); /* 0x1400 */ +#else + GT_REG_WRITE(MV64460_SDRAM_CONFIG, 0x58200400); /* 0x1400 */ +#endif + GT_REG_WRITE(MV64460_D_UNIT_CONTROL_LOW, 0xC3000540); /* 0x1404 */ + GT_REG_WRITE(MV64460_D_UNIT_CONTROL_HIGH, 0x0300F777); /* 0x1424 */ + GT_REG_WRITE(MV64460_SDRAM_TIMING_CONTROL_LOW, 0x01712220); /* 0x1408 */ + GT_REG_WRITE(MV64460_SDRAM_TIMING_CONTROL_HIGH, 0x0000005D); /* 0x140C */ + GT_REG_WRITE(MV64460_SDRAM_ADDR_CONTROL, 0x00000012); /* 0x1410 */ + GT_REG_WRITE(MV64460_SDRAM_OPEN_PAGES_CONTROL, 0x00000001); /* 0x1414 */ + + /* SDRAM drive strength */ + GT_REG_WRITE(MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x80000000); /* 0x14C0 */ + GT_REG_WRITE(MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x80000008); /* 0x14C0 */ + GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000000); /* 0x14C4 */ + GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000008); /* 0x14C4 */ + + /* setup SDRAM device registers */ + + /* precharge all */ + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* enable DLL */ + GT_REG_WRITE(MV64460_EXTENDED_DRAM_MODE, 0x00000000); /* 0x1420 */ + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_XTEN_MODE_REG_SETUP); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* reset DLL */ + GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000132); /* 0x141C */ + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* precharge all */ + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* wait for 2 auto refresh commands */ + udelay(20); + + /* un-reset DLL */ + GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000032); /* 0x141C */ + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* wait 200 cycles */ + udelay(2); /* FIXME make this dynamic for the system clock */ + + /* SDRAM init done */ + memory_map_bank(0, CFG_SDRAM_BASE, (256 << 20)); +#ifdef CFG_SDRAM1_BASE + memory_map_bank(1, CFG_SDRAM1_BASE, (256 << 20)); +#endif + + /* DUNIT_MMASK: enable SnoopHitEn bit to avoid errata CPU-#4 + */ + tmp = GTREGREAD(MV64460_D_UNIT_MMASK); /* 0x14B0 */ + GT_REG_WRITE(MV64460_D_UNIT_MMASK, tmp | 0x2); + + start = (0 << 20); +#ifdef CONFIG_P3M750 + size = (512 << 20); +#elif defined (CONFIG_P3M7448) + size = (128 << 20); +#endif + +#ifdef CONFIG_MV64460_ECC + memSpaceAttr = ((~(BIT0 << 0)) & 0xf) << 8; + mvDmaSetMemorySpace (0, 0, memSpaceAttr, start, size); + for (dest = start; dest < start + size; dest += _8M) { + mvDmaTransfer (0, start, dest, _8M, + BIT8 /*DMA_DTL_128BYTES */ | + BIT3 /*DMA_HOLD_SOURCE_ADDR */ | + BIT11 /*DMA_BLOCK_TRANSFER_MODE */ ); + while (mvDmaIsChannelActive (0)); + } +#endif + + return (size); +} + +void board_add_ram_info(int use_default) +{ + u32 val; + + puts(" (CL="); + switch ((GTREGREAD(MV64460_SDRAM_MODE) >> 4) & 0x7) { + case 0x2: + puts("2"); + break; + case 0x3: + puts("3"); + break; + case 0x5: + puts("1.5"); + break; + case 0x6: + puts("2.5"); + break; + } + + val = GTREGREAD(MV64460_SDRAM_CONFIG); + + puts(", ECC "); + if (val & 0x00001000) + puts("enabled)"); + else + puts("not enabled)"); +} + +/* + * mvDmaIsChannelActive - Check if IDMA channel is active + * + * channel = IDMA channel number from 0 to 7 + */ +int mvDmaIsChannelActive (int channel) +{ + ulong data; + + data = GTREGREAD (MV64460_DMA_CHANNEL0_CONTROL + 4 * channel); + if (data & BIT14) /* activity status */ + return 1; + + return 0; +} + +/* + * mvDmaSetMemorySpace - Set a DMA memory window for the DMA's address decoding + * map. + * + * memSpace = IDMA memory window number from 0 to 7 + * trg_if = Target interface: + * 0x0 DRAM + * 0x1 Device Bus + * 0x2 Integrated SDRAM (or CPU bus 60x only) + * 0x3 PCI0 + * 0x4 PCI1 + * attr = IDMA attributes (see MV datasheet) + * base_addr = Sets up memory window for transfers + * + */ +int mvDmaSetMemorySpace (ulong memSpace, + ulong trg_if, + ulong attr, ulong base_addr, ulong size) +{ + ulong temp; + + /* The base address must be aligned to the size. */ + if (base_addr % size != 0) + return 0; + + if (size >= 0x10000) { /* 64K */ + size &= 0xffff0000; + base_addr = (base_addr & 0xffff0000); + /* Set the new attributes */ + GT_REG_WRITE (MV64460_DMA_BASE_ADDR_REG0 + memSpace * 8, + (base_addr | trg_if | attr)); + GT_REG_WRITE ((MV64460_DMA_SIZE_REG0 + memSpace * 8), + (size - 1) & 0xffff0000); + temp = GTREGREAD (MV64460_DMA_BASE_ADDR_ENABLE_REG); + GT_REG_WRITE (DMA_BASE_ADDR_ENABLE_REG, + (temp & ~(BIT0 << memSpace))); + return 1; + } + + return 0; +} + +/* + * mvDmaTransfer - Transfer data from src_addr to dst_addr on one of the 4 + * DMA channels. + * + * channel = IDMA channel number from 0 to 3 + * destAddr = Destination address + * sourceAddr = Source address + * size = Size in bytes + * command = See MV datasheet + * + */ +int mvDmaTransfer (int channel, ulong sourceAddr, + ulong destAddr, ulong size, ulong command) +{ + ulong engOffReg = 0; /* Engine Offset Register */ + + if (size > 0xffff) + command = command | BIT31; /* DMA_16M_DESCRIPTOR_MODE */ + command = command | ((command >> 6) & 0x7); + engOffReg = channel * 4; + GT_REG_WRITE (MV64460_DMA_CHANNEL0_BYTE_COUNT + engOffReg, size); + GT_REG_WRITE (MV64460_DMA_CHANNEL0_SOURCE_ADDR + engOffReg, sourceAddr); + GT_REG_WRITE (MV64460_DMA_CHANNEL0_DESTINATION_ADDR + engOffReg, destAddr); + command = command | + BIT12 | /* DMA_CHANNEL_ENABLE */ + BIT9; /* DMA_NON_CHAIN_MODE */ + /* Activate DMA channel By writting to mvDmaControlRegister */ + GT_REG_WRITE (MV64460_DMA_CHANNEL0_CONTROL + engOffReg, command); + return 1; +} + +/**************************************************************************************** + * SDRAM INIT * + * This procedure detect all Sdram types: 64, 128, 256, 512 Mbit, 1Gbit and 2Gb * + * This procedure fits only the Atlantis * + * * + ***************************************************************************************/ + +/**************************************************************************************** + * DFCDL initialize MV643xx Design Considerations * + * * + ***************************************************************************************/ +int set_dfcdlInit (void) +{ + int i; + + /* Values from MV64460 User Manual */ + unsigned int dfcdl_tbl[] = { 0x00000000, 0x00000001, 0x00000042, 0x00000083, + 0x000000c4, 0x00000105, 0x00000146, 0x00000187, + 0x000001c8, 0x00000209, 0x0000024a, 0x0000028b, + 0x000002cc, 0x0000030d, 0x0000034e, 0x0000038f, + 0x000003d0, 0x00000411, 0x00000452, 0x00000493, + 0x000004d4, 0x00000515, 0x00000556, 0x00000597, + 0x000005d8, 0x00000619, 0x0000065a, 0x0000069b, + 0x000006dc, 0x0000071d, 0x0000075e, 0x0000079f, + 0x000007e0, 0x00000821, 0x00000862, 0x000008a3, + 0x000008e4, 0x00000925, 0x00000966, 0x000009a7, + 0x000009e8, 0x00000a29, 0x00000a6a, 0x00000aab, + 0x00000aec, 0x00000b2d, 0x00000b6e, 0x00000baf, + 0x00000bf0, 0x00000c31, 0x00000c72, 0x00000cb3, + 0x00000cf4, 0x00000d35, 0x00000d76, 0x00000db7, + 0x00000df8, 0x00000e39, 0x00000e7a, 0x00000ebb, + 0x00000efc, 0x00000f3d, 0x00000f7e, 0x00000fbf }; + + for (i = 0; i < 64; i++) + GT_REG_WRITE (SRAM_DATA0, dfcdl_tbl[i]); + GT_REG_WRITE (DFCDL_CONFIG0, 0x00300000); /* enable dynamic delay line updating */ + + return (0); +} diff --git a/board/prodrive/p3mx/serial.c b/board/prodrive/p3mx/serial.c new file mode 100644 index 0000000000..ba32ac12ac --- /dev/null +++ b/board/prodrive/p3mx/serial.c @@ -0,0 +1,107 @@ +/* + * (C) Copyright 2001 + * Josh Huber , Mission Critical Linux, Inc. + * + * modified for marvell db64360 eval board by + * Ingo Assmus + * + * modified for cpci750 board by + * Reinhard Arlt + * + * 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 + */ + +/* + * serial.c - serial support for esd cpci750 board + */ + +/* supports the MPSC */ + +#include +#include +#include "../../Marvell/include/memory.h" +#include "serial.h" + +#include "mpsc.h" + +DECLARE_GLOBAL_DATA_PTR; + +int serial_init (void) +{ + mpsc_init (gd->baudrate); + + return (0); +} + +void serial_putc (const char c) +{ + if (c == '\n') + mpsc_putchar ('\r'); + + mpsc_putchar (c); +} + +int serial_getc (void) +{ + return mpsc_getchar (); +} + +int serial_tstc (void) +{ + return mpsc_test_char (); +} + +void serial_setbrg (void) +{ + galbrg_set_baudrate (CONFIG_MPSC_PORT, gd->baudrate); +} + + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +void kgdb_serial_init (void) +{ +} + +void putDebugChar (int c) +{ + serial_putc (c); +} + +void putDebugStr (const char *str) +{ + serial_puts (str); +} + +int getDebugChar (void) +{ + return serial_getc (); +} + +void kgdb_interruptible (int yes) +{ + return; +} +#endif /* CFG_CMD_KGDB */ diff --git a/board/prodrive/p3mx/serial.h b/board/prodrive/p3mx/serial.h new file mode 100644 index 0000000000..c7fc8c162d --- /dev/null +++ b/board/prodrive/p3mx/serial.h @@ -0,0 +1,89 @@ +/* + * (C) Copyright 2001 + * Josh Huber , Mission Critical Linux, Inc. + * + * modified for marvell db64360 eval board by + * Ingo Assmus + * + * 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 + */ + +/* serial.h - mostly useful for DUART serial_init in serial.c */ + +#ifndef __SERIAL_H__ +#define __SERIAL_H__ + +#if 0 + +#define B230400 1 +#define B115200 2 +#define B57600 4 +#define B38400 82 +#define B19200 163 +#define B9600 24 +#define B4800 651 +#define B2400 1302 +#define B1200 2604 +#define B600 5208 +#define B300 10417 +#define B150 20833 +#define B110 28409 +#define BDEFAULT B115200 + + /* this stuff is important to initialize + the DUART channels */ + +#define Scale 0x01L /* distance between port addresses */ +#define COM1 0x000003f8 /* Keyboard */ +#define COM2 0x000002f8 /* Host */ + + +/* Port Definitions relative to base COM port addresses */ +#define DataIn (0x00*Scale) /* data input port */ +#define DataOut (0x00*Scale) /* data output port */ +#define BaudLsb (0x00*Scale) /* baud rate divisor least significant byte */ +#define BaudMsb (0x01*Scale) /* baud rate divisor most significant byte */ +#define Ier (0x01*Scale) /* interrupt enable register */ +#define Iir (0x02*Scale) /* interrupt identification register */ +#define Lcr (0x03*Scale) /* line control register */ +#define Mcr (0x04*Scale) /* modem control register */ +#define Lsr (0x05*Scale) /* line status register */ +#define Msr (0x06*Scale) /* modem status register */ + +/* Bit Definitions for above ports */ +#define LcrDlab 0x80 /* b7: enable baud rate divisor registers */ +#define LcrDflt 0x03 /* b6-0: no parity, 1 stop, 8 data */ + +#define McrRts 0x02 /* b1: request to send (I am ready to xmit) */ +#define McrDtr 0x01 /* b0: data terminal ready (I am alive ready to rcv) */ +#define McrDflt (McrRts|McrDtr) + +#define LsrTxD 0x6000 /* b5: transmit holding register empty (i.e. xmit OK!)*/ + /* b6: transmitter empty */ +#define LsrRxD 0x0100 /* b0: received data ready (i.e. got a byte!) */ + +#define MsrRi 0x0040 /* b6: ring indicator (other guy is ready to rcv) */ +#define MsrDsr 0x0020 /* b5: data set ready (other guy is alive ready to rcv */ +#define MsrCts 0x0010 /* b4: clear to send (other guy is ready to rcv) */ + +#define IerRda 0xf /* b0: Enable received data available interrupt */ + +#endif + +#endif /* __SERIAL_H__ */ diff --git a/board/prodrive/p3mx/u-boot.lds b/board/prodrive/p3mx/u-boot.lds new file mode 100644 index 0000000000..d89eb6cff2 --- /dev/null +++ b/board/prodrive/p3mx/u-boot.lds @@ -0,0 +1,138 @@ +/* + * (C) Copyright 2001 + * Josh Huber , Mission Critical Linux, 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 + */ + +/* + * u-boot.lds - linker script for U-Boot on the Galileo Eval Board. + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +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/74xx_7xx/start.o (.text) + +/* store the environment in a seperate sector in the boot flash */ +/* . = env_offset; */ +/* common/environment.o(.text) */ + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _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(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/cpu/74xx_7xx/cpu.c b/cpu/74xx_7xx/cpu.c index ca45e17edb..d98831cb48 100644 --- a/cpu/74xx_7xx/cpu.c +++ b/cpu/74xx_7xx/cpu.c @@ -101,6 +101,10 @@ get_cpu_type(void) type = CPU_7457; break; + case 0x8004: + type = CPU_7448; + break; + default: break; } @@ -152,6 +156,10 @@ int checkcpu (void) str = "MPC7410"; break; + case CPU_7448: + str = "MPC7448"; + break; + case CPU_7450: str = "MPC7450"; break; diff --git a/cpu/74xx_7xx/cpu_init.c b/cpu/74xx_7xx/cpu_init.c index 93f180f267..e02a4cc21c 100644 --- a/cpu/74xx_7xx/cpu_init.c +++ b/cpu/74xx_7xx/cpu_init.c @@ -43,6 +43,7 @@ cpu_init_f (void) case CPU_7450: case CPU_7455: case CPU_7457: + case CPU_7448: /* enable the timebase bit in HID0 */ set_hid0(get_hid0() | 0x4000000); break; diff --git a/cpu/74xx_7xx/speed.c b/cpu/74xx_7xx/speed.c index 2dc510746d..d1800ede05 100644 --- a/cpu/74xx_7xx/speed.c +++ b/cpu/74xx_7xx/speed.c @@ -91,6 +91,7 @@ int get_clocks (void) /* calculate the clock frequency based upon the CPU type */ switch (get_cpu_type()) { + case CPU_7448: case CPU_7455: case CPU_7457: /* diff --git a/cpu/74xx_7xx/start.S b/cpu/74xx_7xx/start.S index 1fc0fe6bc1..11430388f5 100644 --- a/cpu/74xx_7xx/start.S +++ b/cpu/74xx_7xx/start.S @@ -44,7 +44,8 @@ #if !defined(CONFIG_DB64360) && \ !defined(CONFIG_DB64460) && \ - !defined(CONFIG_CPCI750) + !defined(CONFIG_CPCI750) && \ + !defined(CONFIG_P3Mx) #include #endif @@ -270,7 +271,7 @@ in_flash: * gt-regs BAT can be reused after board_init_f calls * board_early_init_f (EVB only). */ -#if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC) +#if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC) && !defined(CONFIG_P3Mx) /* enable address translation */ bl enable_addr_trans sync @@ -757,7 +758,8 @@ in_ram: defined(CONFIG_DB64360) || \ defined(CONFIG_DB64460) || \ defined(CONFIG_CPCI750) || \ - defined(CONFIG_PPMC7XX) + defined(CONFIG_PPMC7XX) || \ + defined(CONFIG_P3Mx) mr r4, r9 /* Use RAM copy of the global data */ #endif bl after_reloc diff --git a/include/74xx_7xx.h b/include/74xx_7xx.h index a6287982a6..33e396a066 100644 --- a/include/74xx_7xx.h +++ b/include/74xx_7xx.h @@ -111,6 +111,7 @@ typedef enum __cpu_t { CPU_750CX, CPU_750FX, CPU_750GX, CPU_7400, CPU_7410, + CPU_7448, CPU_7450, CPU_7455, CPU_7457, CPU_UNKNOWN} cpu_t; diff --git a/include/configs/p3mx.h b/include/configs/p3mx.h new file mode 100644 index 0000000000..262e9d6acf --- /dev/null +++ b/include/configs/p3mx.h @@ -0,0 +1,450 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * Based on original work by + * Roel Loeffen, (C) Copyright 2006 Prodrive B.V. + * + * 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 + */ + +/************************************************************************ + * p3mx.h - configuration for Prodrive P3M750 & P3M7448 boards + * + * The defines: + * CONFIG_P3M750 or + * CONFIG_P3M7448 + * are written into include/config.h by the "make xxx_config" command + ***********************************************************************/ +#ifndef __CONFIG_H +#define __CONFIG_H + +/*----------------------------------------------------------------------- + * High Level Configuration Options + *----------------------------------------------------------------------*/ +#define CONFIG_P3Mx /* used for both board versions */ + +#if defined (CONFIG_P3M750) +#define CONFIG_750FX /* 750GL/GX/FX */ +#define CFG_BOARD_NAME "P3M750" +#define CFG_BUS_HZ 100000000 +#define CFG_BUS_CLK CFG_BUS_HZ +#define CFG_TCLK 100000000 +#elif defined (CONFIG_P3M7448) +#define CONFIG_74xx +#define CFG_BOARD_NAME "P3M7448" +#define CFG_BUS_HZ 133333333 +#define CFG_BUS_CLK CFG_BUS_HZ +#define CFG_TCLK 133333333 +#endif +#define CFG_GT_DUAL_CPU /* also for JTAG even with one cpu */ + +/* which initialization functions to call for this board */ +#define CFG_BOARD_ASM_INIT 1 +#define CONFIG_BOARD_EARLY_INIT_F 1 /* Call board_early_init_f */ +#define CONFIG_BOARD_EARLY_INIT_R 1 /* Call board_early_init_f */ +#define CONFIG_MISC_INIT_R 1 /* Call misc_init_r() */ +#define CONFIG_ADD_RAM_INFO 1 /* Print additional info */ + +/*----------------------------------------------------------------------- + * Base addresses -- Note these are effective addresses where the + * actual resources get mapped (not physical addresses) + *----------------------------------------------------------------------*/ +#define CFG_SDRAM_BASE 0x00000000 +#ifdef CONFIG_P3M750 +#define CFG_SDRAM1_BASE 0x10000000 /* each 256 MByte */ +#endif + +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#if defined (CONFIG_P3M750) +#define CFG_FLASH_BASE 0xff800000 /* start of flash banks */ +#define CFG_BOOT_SIZE _8M /* boot flash */ +#elif defined (CONFIG_P3M7448) +#define CFG_FLASH_BASE 0xff000000 /* start of flash banks */ +#define CFG_BOOT_SIZE _16M /* boot flash */ +#endif +#define CFG_BOOT_SPACE CFG_FLASH_BASE /* BOOT_CS0 flash 0 */ +#define CFG_MONITOR_BASE 0xfff00000 +#define CFG_RESET_ADDRESS 0xfff00100 +#define CFG_MALLOC_LEN (256 << 10) /* Reserve 256 kB for malloc */ +#define CFG_MISC_REGION_BASE 0xf0000000 + +#define CFG_DFL_GT_REGS 0xf1000000 /* boot time GT_REGS */ +#define CFG_GT_REGS 0xf1000000 /* GT Registers are mapped here */ +#define CFG_INT_SRAM_BASE 0x42000000 /* GT offers 256k internal SRAM */ + +/*----------------------------------------------------------------------- + * Initial RAM & stack pointer (placed in internal SRAM) + *----------------------------------------------------------------------*/ + /* + * When locking data in cache you should point the CFG_INIT_RAM_ADDRESS + * To an unused memory region. The stack will remain in cache until RAM + * is initialized +*/ +#undef CFG_INIT_RAM_LOCK +#define CFG_INIT_RAM_ADDR 0x42000000 +#define CFG_INIT_RAM_END 0x1000 +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for init data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) + + +/*----------------------------------------------------------------------- + * Serial Port + *----------------------------------------------------------------------*/ +#define CONFIG_MPSC /* MV64460 Serial */ +#define CONFIG_MPSC_PORT 0 +#define CONFIG_BAUDRATE 115200 /* console baudrate */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400 } +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + +/*----------------------------------------------------------------------- + * Ethernet + *----------------------------------------------------------------------*/ +/* Change the default ethernet port, use this define (options: 0, 1, 2) */ +#define CFG_ETH_PORT ETH_0 +#define CONFIG_NET_MULTI +#define MV_ETH_DEVS 2 +#define CONFIG_PHY_RESET 1 /* reset phy upon startup */ +#define CONFIG_PHY_GIGE 1 /* Include GbE speed/duplex detection */ + +/*----------------------------------------------------------------------- + * FLASH related + *----------------------------------------------------------------------*/ +#define CFG_FLASH_CFI /* The flash is CFI compatible */ +#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 512 /* max number of sectors on one chip */ +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ +#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */ +#define CFG_FLASH_PROTECTION 1 /* use hardware flash protection */ +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ + +#define CFG_ENV_IS_IN_FLASH 1 /* use FLASH for environment vars */ +#if defined (CONFIG_P3M750) +#define CFG_ENV_SECT_SIZE 0x20000 /* one sector (1 device)*/ +#elif defined (CONFIG_P3M7448) +#define CFG_ENV_SECT_SIZE 0x40000 /* two sectors (2 devices parallel */ +#endif +#define CFG_ENV_SIZE 0x2000 /* Total Size of Environment Sector */ +#define CFG_ENV_ADDR (CFG_MONITOR_BASE + CFG_MONITOR_LEN) + +/*----------------------------------------------------------------------- + * DDR SDRAM + *----------------------------------------------------------------------*/ +#define CONFIG_MV64460_ECC + +/*----------------------------------------------------------------------- + * I2C + *----------------------------------------------------------------------*/ +#define CFG_I2C_SPEED 100000 /* I2C speed default */ + +/* I2C RTC */ +#define CONFIG_RTC_M41T11 1 +#define CFG_I2C_RTC_ADDR 0x68 +#define CFG_M41T11_BASE_YEAR 1900 /* play along with linux */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------*/ +#define PCI_HOST_ADAPTER 0 /* configure ar pci adapter */ +#define PCI_HOST_FORCE 1 /* configure as pci host */ +#define PCI_HOST_AUTO 2 /* detected via arbiter enable */ + +#define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ +#define CONFIG_PCI_PNP /* do pci plug-and-play */ +#define CONFIG_PCI_SCAN_SHOW /* show devices on bus */ + +/* PCI MEMORY MAP section */ +#define CFG_PCI0_MEM_BASE 0x80000000 +#define CFG_PCI0_MEM_SIZE _128M +#define CFG_PCI1_MEM_BASE 0x88000000 +#define CFG_PCI1_MEM_SIZE _128M + +#define CFG_PCI0_0_MEM_SPACE (CFG_PCI0_MEM_BASE) +#define CFG_PCI1_0_MEM_SPACE (CFG_PCI1_MEM_BASE) + +/* PCI I/O MAP section */ +#define CFG_PCI0_IO_BASE 0xfa000000 +#define CFG_PCI0_IO_SIZE _16M +#define CFG_PCI1_IO_BASE 0xfb000000 +#define CFG_PCI1_IO_SIZE _16M + +#define CFG_PCI0_IO_SPACE (CFG_PCI0_IO_BASE) +#define CFG_PCI0_IO_SPACE_PCI 0x00000000 +#define CFG_PCI1_IO_SPACE (CFG_PCI1_IO_BASE) +#define CFG_PCI1_IO_SPACE_PCI 0x00000000 + +#define CFG_ISA_IO_BASE_ADDRESS (CFG_PCI0_IO_BASE) + +#define CFG_PCI_IDSEL 0x30 + +#undef CONFIG_BOOTARGS +#define CONFIG_EXTRA_ENV_SETTINGS_COMMON \ + "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" \ + "rootpath=/opt/eldk/ppc_6xx\0" \ + "u-boot=p3mx/u-boot/u-boot.bin\0" \ + "load=tftp 100000 ${u-boot}\0" \ + "update=protect off fff00000 fff3ffff;era fff00000 fff3ffff;" \ + "cp.b 100000 fff00000 40000;" \ + "setenv filesize;saveenv\0" \ + "upd=run load;run update\0" \ + "serverip=11.0.0.152\0" + +#if defined (CONFIG_P3M750) +#define CONFIG_EXTRA_ENV_SETTINGS \ + CONFIG_EXTRA_ENV_SETTINGS_COMMON \ + "hostname=p3m750\0" \ + "bootfile=/tftpboot/p3mx/vxWorks.st\0" \ + "kernel_addr=fc000000\0" \ + "ramdisk_addr=fc180000\0" \ + "vxfile=p3m750/vxWorks\0" \ + "vxuser=ddg\0" \ + "vxpass=ddg\0" \ + "vxtarget=target\0" \ + "vxflags=0x8\0" \ + "vxargs=setenv bootargs mgi(0,0)host:${vxfile} h=${serverip} " \ + "e=${ipaddr} u=${vxuser} pw=${vxpass} tn=${vxtarget} " \ + "f=${vxflags}\0" +#elif defined (CONFIG_P3M7448) +#define CONFIG_EXTRA_ENV_SETTINGS \ + CONFIG_EXTRA_ENV_SETTINGS_COMMON \ + "hostname=p3m7448\0" +#endif + +#if defined (CONFIG_P3M750) +#define CONFIG_BOOTCOMMAND "tftp;run vxargs;bootvx" +#elif defined (CONFIG_P3M7448) +#define CONFIG_BOOTCOMMAND " " +#endif + +#define CONFIG_BOOTDELAY 3 /* autoboot after 5 seconds */ +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | \ + CONFIG_BOOTP_BOOTFILESIZE) +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | \ + CFG_CMD_ASKENV | \ + CFG_CMD_DATE | \ + CFG_CMD_DIAG | \ + CFG_CMD_ELF | \ + CFG_CMD_I2C | \ + CFG_CMD_IRQ | \ + CFG_CMD_MII | \ + CFG_CMD_NET | \ + CFG_CMD_NFS | \ + CFG_CMD_PING | \ + CFG_CMD_REGINFO | \ + CFG_CMD_PCI | \ + CFG_CMD_CACHE | \ + CFG_CMD_SDRAM) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + +/*----------------------------------------------------------------------- + * Miscellaneous configurable options + *----------------------------------------------------------------------*/ +#define CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " + +#define CFG_LONGHELP /* undef to save memory */ +#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_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x08000000 /* default load address */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CONFIG_CMDLINE_EDITING 1 /* add command line history */ +#define CONFIG_LOOPW 1 /* enable loopw command */ +#define CONFIG_MX_CYCLIC 1 /* enable mdc/mwc commands */ +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ +#define CONFIG_VERSION_VARIABLE 1 /* include version env variable */ + +/*----------------------------------------------------------------------- + * Marvell MV64460 config settings + *----------------------------------------------------------------------*/ +/* Reset values for Port behavior (8bit/ 32bit, etc.) only corrected device width */ +#if defined (CONFIG_P3M750) +#define CFG_BOOT_PAR 0x8FDFF87F /* 16 bit flash, disable burst*/ +#elif defined (CONFIG_P3M7448) +#define CFG_BOOT_PAR 0x8FEFFFFF /* 32 bit flash, burst enabled */ +#endif + +/* + * MPP[0] Serial Port 0 TxD TxD OUT Connected to P14 (buffered) + * MPP[1] Serial Port 0 RxD RxD IN Connected to P14 (buffered) + * MPP[2] NC + * MPP[3] Serial Port 1 TxD TxD OUT Connected to P14 (buffered) + * MPP[4] PCI Monarch# GPIO IN Connected to P12 + * MPP[5] Serial Port 1 RxD RxD IN Connected to P14 (buffered) + * MPP[6] PMC Carrier Interrupt 0 Int IN Connected to P14 + * MPP[7] PMC Carrier Interrupt 1 Int IN Connected to P14 + * MPP[8] Reserved Do not use + * MPP[9] Reserved Do not use + * MPP[10] Reserved Do not use + * MPP[11] Reserved Do not use + * MPP[12] Phy 0 Interrupt Int IN + * MPP[13] Phy 1 Interrupt Int IN + * MPP[14] NC + * MPP[15] NC + * MPP[16] PCI Interrupt C Int IN Connected to P11 + * MPP[17] PCI Interrupt D Int IN Connected to P11 + * MPP[18] Watchdog NMI# GPIO IN Connected to MPP[24] + * MPP[19] Watchdog Expired# WDE OUT Connected to rst logic + * MPP[20] Watchdog Status WD_STS IN Read back of rst by watchdog + * MPP[21] NC + * MPP[22] GP LED Green GPIO OUT + * MPP[23] GP LED Red GPIO OUT + * MPP[24] Watchdog NMI# Int OUT + * MPP[25] NC + * MPP[26] NC + * MPP[27] PCI Interrupt A Int IN Connected to P11 + * MPP[28] NC + * MPP[29] PCI Interrupt B Int IN Connected to P11 + * MPP[30] Module reset GPIO OUT Board reset + * MPP[31] PCI EReady GPIO IN Connected to P12 + */ +#define CFG_MPP_CONTROL_0 0x00303022 +#define CFG_MPP_CONTROL_1 0x00000000 +#define CFG_MPP_CONTROL_2 0x00004000 +#define CFG_MPP_CONTROL_3 0x00000004 +#define CFG_GPP_LEVEL_CONTROL 0x280730D0 + +/*---------------------------------------------------------------------- + * Initial BAT mappings + */ + +/* NOTES: + * 1) GUARDED and WRITE_THRU not allowed in IBATS + * 2) CACHEINHIBIT and WRITETHROUGH not allowed together in same BAT + */ +/* SDRAM */ +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_RW | BATL_CACHEINHIBIT) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) +#define CFG_DBAT0L (CFG_SDRAM_BASE | BATL_PP_RW | BATL_GUARDEDSTORAGE | BATL_CACHEINHIBIT) +#define CFG_DBAT0U CFG_IBAT0U + +/* init ram */ +#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_RW | BATL_MEMCOHERENCE) +#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_256K | BATU_VS | BATU_VP) +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U + +/* PCI0, PCI1 in one BAT */ +#define CFG_IBAT2L BATL_NO_ACCESS +#define CFG_IBAT2U CFG_DBAT2U +#define CFG_DBAT2L (CFG_PCI0_MEM_BASE | BATL_CACHEINHIBIT | BATL_PP_RW | BATL_GUARDEDSTORAGE) +#define CFG_DBAT2U (CFG_PCI0_MEM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +/* GT regs, bootrom, all the devices, PCI I/O */ +#define CFG_IBAT3L (CFG_MISC_REGION_BASE | BATL_CACHEINHIBIT | BATL_PP_RW) +#define CFG_IBAT3U (CFG_MISC_REGION_BASE | BATU_VS | BATU_VP | BATU_BL_256M) +#define CFG_DBAT3L (CFG_MISC_REGION_BASE | BATL_CACHEINHIBIT | BATL_PP_RW | BATL_GUARDEDSTORAGE) +#define CFG_DBAT3U CFG_IBAT3U + +#define CFG_IBAT4L (CFG_SDRAM1_BASE | BATL_PP_RW | BATL_CACHEINHIBIT) +#define CFG_IBAT4U (CFG_SDRAM1_BASE | BATU_BL_256M | BATU_VS | BATU_VP) +#define CFG_DBAT4L (CFG_SDRAM1_BASE | BATL_PP_RW | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) +#define CFG_DBAT4U CFG_IBAT4U + +/* set rest out of range for Linux !!!!!!!!!!! */ + +/* IBAT5 and DBAT5 */ +#define CFG_IBAT5L (0x20000000 | BATL_PP_RW | BATL_CACHEINHIBIT) +#define CFG_IBAT5U (0x20000000 | BATU_BL_256M | BATU_VS | BATU_VP) +#define CFG_DBAT5L (0x20000000 | BATL_PP_RW | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) +#define CFG_DBAT5U CFG_IBAT5U + +/* IBAT6 and DBAT6 */ +#define CFG_IBAT6L (0x20000000 | BATL_PP_RW | BATL_CACHEINHIBIT) +#define CFG_IBAT6U (0x20000000 | BATU_BL_256M | BATU_VS | BATU_VP) +#define CFG_DBAT6L (0x20000000 | BATL_PP_RW | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) +#define CFG_DBAT6U CFG_IBAT6U + +/* IBAT7 and DBAT7 */ +#define CFG_IBAT7L (0x20000000 | BATL_PP_RW | BATL_CACHEINHIBIT) +#define CFG_IBAT7U (0x20000000 | BATU_BL_256M | BATU_VS | BATU_VP) +#define CFG_DBAT7L (0x20000000 | BATL_PP_RW | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) +#define CFG_DBAT7U CFG_IBAT7U + +/* + * 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 */ +#define CFG_VXWORKS_MAC_PTR 0x42010000 /* use some memory in SRAM that's not used!!! */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 /* For all MPC74xx CPUs */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/*----------------------------------------------------------------------- + * L2CR setup -- make sure this is right for your board! + * look in include/mpc74xx.h for the defines used here + */ +#define CFG_L2 + +#if defined (CONFIG_750CX) || defined (CONFIG_750FX) +#define L2_INIT 0 +#else +#define L2_INIT (L2CR_L2SIZ_2M | L2CR_L2CLK_3 | L2CR_L2RAM_BURST | \ + L2CR_L2OH_5 | L2CR_L2CTL | L2CR_L2WT) +#endif + +#define L2_ENABLE (L2_INIT | L2CR_L2E) + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/net/eth.c b/net/eth.c index e8ac251a4f..1e6a1c97ab 100644 --- a/net/eth.c +++ b/net/eth.c @@ -142,13 +142,10 @@ int eth_initialize(bd_t *bis) miiphy_init(); #endif -#ifdef CONFIG_DB64360 +#if defined(CONFIG_DB64360) || defined(CONFIG_CPCI750) mv6436x_eth_initialize(bis); #endif -#ifdef CONFIG_CPCI750 - mv6436x_eth_initialize(bis); -#endif -#ifdef CONFIG_DB64460 +#if defined(CONFIG_DB64460) || defined(CONFIG_P3Mx) mv6446x_eth_initialize(bis); #endif #if defined(CONFIG_4xx) && !defined(CONFIG_IOP480) && !defined(CONFIG_AP1000) From 726e90aacf0b1ecb0e7055be574622fbe3e450ba Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 29 Nov 2006 16:23:42 +0100 Subject: [PATCH 4/5] [PATCH] [MPC52xx] Use IPB bus frequency for SOC peripherals The soc node of the mpc52xx needs to be loaded with the IPB bus frequency, not the XLB frequency. This patch depends on the previous patches for MPC52xx device tree support Signed-off-by: Grant Likely Signed-off-by: Sylvain Munaut --- cpu/mpc5xxx/cpu.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cpu/mpc5xxx/cpu.c b/cpu/mpc5xxx/cpu.c index 20e6735de4..813aa7935d 100644 --- a/cpu/mpc5xxx/cpu.c +++ b/cpu/mpc5xxx/cpu.c @@ -112,21 +112,20 @@ void ft_cpu_setup(void *blob, bd_t *bd) { u32 *p; - ulong clock; int len; - clock = bd->bi_busfreq; + /* Core XLB bus frequency */ p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len); if (p != NULL) - *p = cpu_to_be32(clock); + *p = cpu_to_be32(bd->bi_busfreq); + /* SOC peripherals use the IPB bus frequency */ p = ft_get_prop(blob, "/" OF_SOC "/bus-frequency", &len); if (p != NULL) - *p = cpu_to_be32(clock); + *p = cpu_to_be32(bd->bi_ipbfreq); p = ft_get_prop(blob, "/" OF_SOC "/ethernet@3000/mac-address", &len); if (p != NULL) memcpy(p, bd->bi_enetaddr, 6); - } #endif From 8d9a8610b8256331132227e9e6585c6bd5742787 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Thu, 30 Nov 2006 01:54:07 +0100 Subject: [PATCH 5/5] Code cleanup. Update CHANGELOG. --- CHANGELOG | 165 ++++++++ board/prodrive/p3mx/mv_eth.c | 668 ++++++++++++++----------------- board/prodrive/p3mx/sdram_init.c | 35 +- 3 files changed, 480 insertions(+), 388 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 4c9a7445e4..305cee8fd3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,85 @@ +commit 726e90aacf0b1ecb0e7055be574622fbe3e450ba +Author: Grant Likely +Date: Wed Nov 29 16:23:42 2006 +0100 + + [PATCH] [MPC52xx] Use IPB bus frequency for SOC peripherals + + The soc node of the mpc52xx needs to be loaded with the IPB bus frequency, + not the XLB frequency. + + This patch depends on the previous patches for MPC52xx device tree support + + Signed-off-by: Grant Likely + Signed-off-by: Sylvain Munaut + +commit 1eac2a71417b6675b11aace72102a2e7fde8f5c6 +Author: Stefan Roese +Date: Wed Nov 29 15:42:37 2006 +0100 + + [PATCH] Add support for Prodrive P3M750 & P3M7448 (P3Mx) boards + + This patch adds support for the Prodrive P3M750 (PPC750 & MV64460) + and the P3M7448 (MPC7448 & MV64460) PMC modules. Both modules are + quite similar and share the same board directory "prodrive/p3mx" + and the same config file "p3mx.h". + + Signed-off-by: Stefan Roese + +commit 1bdd46832aeb569f5e04b1f20f64318525b6525a +Author: Stefan Roese +Date: Wed Nov 29 12:53:15 2006 +0100 + + [PATCH] common/cmd_elf.c: Enable loadaddr as parameter in bootvx command + + In the bootvx command the load address was only read from the env + variable "loadaddr" and not optionally passed as paramter as described + in the help. This is fixed with this patch. The behaviour is now the + same as in the bootelf command. + + Signed-off-by: Stefan Roese + +commit 4e26f1074c3ac1bd8fd094f0dc4a1c4a0b15a592 +Author: Stefan Roese +Date: Wed Nov 29 12:03:57 2006 +0100 + + [PATCH] include/ppc440.h minor error affecting interrupts + + Fixed include/ppc440.c for UIC address Bug + + Corrects bug affecting the addresses for the universal interrupt + controller UIC2 and UIC3 on the PPC440 Epx, GRx, and SPE chips. + + Signed-off-by: Jeff Mann + Signed-off-by: Stefan Roese + +commit e59581c56ab5d6e0207ddac3b2c1d55cb36ec706 +Author: Stefan Roese +Date: Tue Nov 28 17:55:49 2006 +0100 + + [PATCH] Enable the IceCube/lite5200 variants to pass a device tree to Linux. + + This patch adds the code and configuration necessary to boot with an + arch/powerpc Linux kernel. + + Signed-off-by: Grant Likely + Acked-by: Jon Loeliger + +commit e732faec95a83cb468b4850ae807c8301dde8f6a +Author: Stefan Roese +Date: Tue Nov 28 16:09:24 2006 +0100 + + [PATCH] PPC4xx: 440SP Rev. C detection added + + Signed-off-by: Stefan Roese + +commit e7f3e9ff01fbd7fa72eb42a9675fbed6bc4736b0 +Author: Stefan Roese +Date: Tue Nov 28 11:04:45 2006 +0100 + + [PATCH] nand: Fix patch merge problem + + Signed-off-by: Stefan Roese + commit 4f4b602ec7524a032bdf3c6d28c7f525a4a67eaa Author: Wolfgang Denk Date: Mon Nov 27 22:53:53 2006 +0100 @@ -67,6 +149,46 @@ Date: Mon Nov 27 15:32:42 2006 +0100 Minor code cleanup. Update CHANGELOG. +commit 1729b92cde575476684bffe819d0b7791b57bff2 +Author: Stefan Roese +Date: Mon Nov 27 14:52:04 2006 +0100 + + [PATCH] 4xx: Fix problem with board specific reset code (now for real) + + Signed-off-by: Stefan Roese + +commit cc5ee8a92a0e3ca6f727af71b8fd206460c7afd7 +Author: Stefan Roese +Date: Mon Nov 27 14:49:51 2006 +0100 + + [PATCH] alpr: remove unused board specific flash driver + + Signed-off-by: Stefan Roese + +commit 1f94d162e2b5f0edc28d9fb11482502c44d218e1 +Author: Stefan Roese +Date: Mon Nov 27 14:48:41 2006 +0100 + + [PATCH] 4xx: Fix problem with board specific reset code + + Signed-off-by: Stefan Roese + +commit ec0c2ec725aec9524a177a77ce75559e644a931a +Author: Stefan Roese +Date: Mon Nov 27 14:46:06 2006 +0100 + + [PATCH] Remove testing 4xx enet PHY setup + + Signed-off-by: Stefan Roese + +commit 1c2ce2262069510f31c7d3fd7efd3d58b8c0c148 +Author: Stefan Roese +Date: Mon Nov 27 14:12:17 2006 +0100 + + [PATCH] Update Prodrive ALPR board support (440GX) + + Signed-off-by: Stefan Roese + commit 78d620ebb5871d252270dedfad60c6568993b780 Author: Wolfgang Denk Date: Thu Nov 23 22:58:58 2006 +0100 @@ -641,6 +763,34 @@ Date: Tue Oct 10 17:02:22 2006 -0500 Fix whitespace and 80-col issues. +commit 5c912cb1c31266c66ca59b36f9b6f87296421d75 +Author: Stefan Roese +Date: Sat Oct 7 11:36:51 2006 +0200 + + CFG_NAND_QUIET_TEST added to not warn upon missing NAND device + Patch by Stefan Roese, 07 Oct 2006 + +commit 5bc528fa4da751d472397b308137238a6465afd2 +Author: Stefan Roese +Date: Sat Oct 7 11:35:25 2006 +0200 + + Update ALPR code (NAND support working now) + Patch by Stefan Roese, 07 Oct 2006 + +commit 77d5034847d328753b80c46b83f960a14a26f40e +Author: Stefan Roese +Date: Sat Oct 7 11:33:03 2006 +0200 + + Remove compile warnings in fpga code + Patch by Stefan Roese, 07 Oct 2006 + +commit f3443867e90d2979a7dd1c65b0d537777e1f9850 +Author: Stefan Roese +Date: Sat Oct 7 11:30:52 2006 +0200 + + Add CONFIG_BOARD_RESET to configure board specific reset function + Patch by Stefan Roese, 07 Oct 2006 + commit f55df18187e7a45cb73fec4370d12135e6691ae1 Author: John Traill Date: Fri Sep 29 08:23:12 2006 +0100 @@ -873,6 +1023,21 @@ Date: Wed Aug 16 10:54:09 2006 -0500 Signed-off-by: Matthew McClintock +commit 899620c2d66d4eef3b2a0034d062e71d45d886c9 +Author: Stefan Roese +Date: Tue Aug 15 14:22:35 2006 +0200 + + Add initial support for the ALPR board from Prodrive + NAND needs some additional testing + Patch by Heiko Schocher, 15 Aug 2006 + +commit f0ff4692ff3372dec55074a8eb444943ab095abb +Author: Stefan Roese +Date: Tue Aug 15 14:15:51 2006 +0200 + + Add FPGA Altera Cyclone 2 support + Patch by Heiko Schocher, 15 Aug 2006 + commit fecf1c7e4de1b2779edc18742b91c22bdc32b68b Author: Jon Loeliger Date: Mon Aug 14 15:33:38 2006 -0500 diff --git a/board/prodrive/p3mx/mv_eth.c b/board/prodrive/p3mx/mv_eth.c index 1127673648..8203b3cbf1 100644 --- a/board/prodrive/p3mx/mv_eth.c +++ b/board/prodrive/p3mx/mv_eth.c @@ -15,7 +15,7 @@ * * 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 + * 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 @@ -46,33 +46,28 @@ #endif /* PHY DFCDL Registers */ -#define ETH_PHY_DFCDL_CONFIG0_REG 0x2100 -#define ETH_PHY_DFCDL_CONFIG1_REG 0x2104 -#define ETH_PHY_DFCDL_ADDR_REG 0x2110 -#define ETH_PHY_DFCDL_DATA0_REG 0x2114 +#define ETH_PHY_DFCDL_CONFIG0_REG 0x2100 +#define ETH_PHY_DFCDL_CONFIG1_REG 0x2104 +#define ETH_PHY_DFCDL_ADDR_REG 0x2110 +#define ETH_PHY_DFCDL_DATA0_REG 0x2114 -#define PHY_AUTONEGOTIATE_TIMEOUT 4000 /* 4000 ms autonegotiate timeout */ -#define PHY_UPDATE_TIMEOUT 10000 +#define PHY_AUTONEGOTIATE_TIMEOUT 4000 /* 4000 ms autonegotiate timeout */ +#define PHY_UPDATE_TIMEOUT 10000 #undef MV64460_CHECKSUM_OFFLOAD /************************************************************************* -************************************************************************** -************************************************************************** -* The first part is the high level driver of the gigE ethernet ports. * -************************************************************************** -************************************************************************** +* The first part is the high level driver of the gigE ethernet ports. * *************************************************************************/ /* Definition for configuring driver */ /* #define UPDATE_STATS_BY_SOFTWARE */ #undef MV64460_RX_QUEUE_FILL_ON_TASK - /* Constants */ #define MAGIC_ETH_RUNNING 8031971 -#define MV64460_INTERNAL_SRAM_SIZE _256K +#define MV64460_INTERNAL_SRAM_SIZE _256K #define EXTRA_BYTES 32 -#define WRAP ETH_HLEN + 2 + 4 + 16 +#define WRAP ETH_HLEN + 2 + 4 + 16 #define BUFFER_MTU dev->mtu + WRAP #define INT_CAUSE_UNMASK_ALL 0x0007ffff #define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff @@ -111,7 +106,7 @@ int mv_miiphy_write(char *devname, unsigned char phy_addr, int phy_setup_aneg (char *devname, unsigned char addr); -#ifndef UPDATE_STATS_BY_SOFTWARE +#ifndef UPDATE_STATS_BY_SOFTWARE static void mv64460_eth_print_stat (struct eth_device *dev); #endif /* Processes a received packet */ @@ -141,8 +136,10 @@ void print_globals (struct eth_device *dev) printf ("GT Internal Base Address: %08x\n", INTERNAL_REG_BASE_ADDR); - printf ("Base Address for TX-DESCs: %08x Number of allocated Buffers %d\n", (unsigned int) ((ETH_PORT_INFO *) dev->priv)->p_tx_desc_area_base[0], MV64460_TX_QUEUE_SIZE); - printf ("Base Address for RX-DESCs: %08x Number of allocated Buffers %d\n", (unsigned int) ((ETH_PORT_INFO *) dev->priv)->p_rx_desc_area_base[0], MV64460_RX_QUEUE_SIZE); + printf ("Base Address for TX-DESCs: %08x Number of allocated Buffers %d\n", + (unsigned int) ((ETH_PORT_INFO *) dev->priv)->p_tx_desc_area_base[0], MV64460_TX_QUEUE_SIZE); + printf ("Base Address for RX-DESCs: %08x Number of allocated Buffers %d\n", + (unsigned int) ((ETH_PORT_INFO *) dev->priv)->p_rx_desc_area_base[0], MV64460_RX_QUEUE_SIZE); printf ("Base Address for RX-Buffer: %08x allocated Bytes %d\n", (unsigned int) ((ETH_PORT_INFO *) dev->priv)-> p_rx_buffer_base[0], @@ -154,8 +151,6 @@ void print_globals (struct eth_device *dev) } #endif - - /********************************************************************** * mv64460_eth_print_phy_status * @@ -221,84 +216,37 @@ void db64460_eth_disable (struct eth_device *dev) mv64460_eth_stop (dev); } - #define DFCDL(write,read) ((write << 6) | read) -unsigned int ethDfcdls[] = { DFCDL(0,0), - DFCDL(1,1), - DFCDL(2,2), - DFCDL(3,3), - DFCDL(4,4), - DFCDL(5,5), - DFCDL(6,6), - DFCDL(7,7), - DFCDL(8,8), - DFCDL(9,9), - DFCDL(10,10), - DFCDL(11,11), - DFCDL(12,12), - DFCDL(13,13), - DFCDL(14,14), - DFCDL(15,15), - DFCDL(16,16), - DFCDL(17,17), - DFCDL(18,18), - DFCDL(19,19), - DFCDL(20,20), - DFCDL(21,21), - DFCDL(22,22), - DFCDL(23,23), - DFCDL(24,24), - DFCDL(25,25), - DFCDL(26,26), - DFCDL(27,27), - DFCDL(28,28), - DFCDL(29,29), - DFCDL(30,30), - DFCDL(31,31), - DFCDL(32,32), - DFCDL(33,33), - DFCDL(34,34), - DFCDL(35,35), - DFCDL(36,36), - DFCDL(37,37), - DFCDL(38,38), - DFCDL(39,39), - DFCDL(40,40), - DFCDL(41,41), - DFCDL(42,42), - DFCDL(43,43), - DFCDL(44,44), - DFCDL(45,45), - DFCDL(46,46), - DFCDL(47,47), - DFCDL(48,48), - DFCDL(49,49), - DFCDL(50,50), - DFCDL(51,51), - DFCDL(52,52), - DFCDL(53,53), - DFCDL(54,54), - DFCDL(55,55), - DFCDL(56,56), - DFCDL(57,57), - DFCDL(58,58), - DFCDL(59,59), - DFCDL(60,60), - DFCDL(61,61), - DFCDL(62,62), - DFCDL(63,63) }; +unsigned int ethDfcdls[] = { + DFCDL(0,0), DFCDL(1,1), DFCDL(2,2), DFCDL(3,3), + DFCDL(4,4), DFCDL(5,5), DFCDL(6,6), DFCDL(7,7), + DFCDL(8,8), DFCDL(9,9), DFCDL(10,10), DFCDL(11,11), + DFCDL(12,12), DFCDL(13,13), DFCDL(14,14), DFCDL(15,15), + DFCDL(16,16), DFCDL(17,17), DFCDL(18,18), DFCDL(19,19), + DFCDL(20,20), DFCDL(21,21), DFCDL(22,22), DFCDL(23,23), + DFCDL(24,24), DFCDL(25,25), DFCDL(26,26), DFCDL(27,27), + DFCDL(28,28), DFCDL(29,29), DFCDL(30,30), DFCDL(31,31), + DFCDL(32,32), DFCDL(33,33), DFCDL(34,34), DFCDL(35,35), + DFCDL(36,36), DFCDL(37,37), DFCDL(38,38), DFCDL(39,39), + DFCDL(40,40), DFCDL(41,41), DFCDL(42,42), DFCDL(43,43), + DFCDL(44,44), DFCDL(45,45), DFCDL(46,46), DFCDL(47,47), + DFCDL(48,48), DFCDL(49,49), DFCDL(50,50), DFCDL(51,51), + DFCDL(52,52), DFCDL(53,53), DFCDL(54,54), DFCDL(55,55), + DFCDL(56,56), DFCDL(57,57), DFCDL(58,58), DFCDL(59,59), + DFCDL(60,60), DFCDL(61,61), DFCDL(62,62), DFCDL(63,63), +}; -void mv_eth_phy_init(void) +void mv_eth_phy_init (void) { - int i; + int i; - MV_REG_WRITE(ETH_PHY_DFCDL_ADDR_REG, 0); + MV_REG_WRITE (ETH_PHY_DFCDL_ADDR_REG, 0); - for (i = 0 ; i < 64; i++) { - MV_REG_WRITE(ETH_PHY_DFCDL_DATA0_REG, ethDfcdls[i]); - } + for (i = 0; i < 64; i++) { + MV_REG_WRITE (ETH_PHY_DFCDL_DATA0_REG, ethDfcdls[i]); + } - MV_REG_WRITE(ETH_PHY_DFCDL_CONFIG0_REG,0x300000); + MV_REG_WRITE (ETH_PHY_DFCDL_CONFIG0_REG, 0x300000); } void mv6446x_eth_initialize (bd_t * bis) @@ -309,9 +257,9 @@ void mv6446x_eth_initialize (bd_t * bis) int devnum, x, temp; char *s, *e, buf[64]; -/* P3M750 only - * Set RGMII clock drives strength - */ + /* P3M750 only + * Set RGMII clock drives strength + */ temp = MV_REG_READ(0x20A0); temp |= 0x04000080; MV_REG_WRITE(0x20A0, temp); @@ -338,15 +286,12 @@ void mv6446x_eth_initialize (bd_t * bis) case 0: s = "ethaddr"; break; - case 1: s = "eth1addr"; break; - case 2: s = "eth2addr"; break; - default: /* this should never happen */ printf ("%s: Invalid device number %d\n", __FUNCTION__, devnum); @@ -440,15 +385,12 @@ void mv6446x_eth_initialize (bd_t * bis) case 0: s = "ethaddr"; break; - case 1: s = "eth1addr"; break; - case 2: s = "eth2addr"; break; - default: /* this should never happen */ printf ("%s: Invalid device number %d\n", __FUNCTION__, devnum); @@ -538,13 +480,11 @@ static int mv64460_eth_real_open (struct eth_device *dev) see ./net/eth.c eth_set_enetaddr() */ memcpy (ethernet_private->port_mac_addr, dev->enetaddr, 6); - port_private = - (struct mv64460_eth_priv *) ethernet_private->port_private; + port_private = (struct mv64460_eth_priv *) ethernet_private->port_private; port_num = port_private->port_num; /* Stop RX Queues */ - MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num), - 0x0000ff00); + MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num), 0x0000ff00); /* Clear the ethernet port interrupts */ MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_REG (port_num), 0); @@ -685,7 +625,6 @@ static int mv64460_eth_real_open (struct eth_device *dev) return 1; } - static int mv64460_eth_free_tx_rings (struct eth_device *dev) { unsigned int queue; @@ -739,7 +678,6 @@ static int mv64460_eth_free_rx_rings (struct eth_device *dev) (struct mv64460_eth_priv *) ethernet_private->port_private; port_num = port_private->port_num; - /* Stop RX Queues */ MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num), 0x0000ff00); @@ -823,7 +761,7 @@ static int mv64460_eth_real_stop (struct eth_device *dev) MV_RESET_REG_BITS (MV64460_CPU_INTERRUPT0_MASK_HIGH, BIT0 << port_num); /* Print Network statistics */ -#ifndef UPDATE_STATS_BY_SOFTWARE +#ifndef UPDATE_STATS_BY_SOFTWARE /* * Print statistics (only if ethernet is running), * then zero all the stats fields in memory @@ -838,7 +776,6 @@ static int mv64460_eth_real_stop (struct eth_device *dev) return 0; } - /********************************************************************** * mv64460_eth_start_xmit * @@ -846,7 +783,7 @@ static int mv64460_eth_real_stop (struct eth_device *dev) * required port. * * Input : skb - a pointer to socket buffer - * dev - a pointer to the required port + * dev - a pointer to the required port * * Output : zero upon success **********************************************************************/ @@ -882,7 +819,7 @@ int mv64460_eth_xmit (struct eth_device *dev, volatile void *dataPtr, printf ("ETH Queue is full. \n"); if (status == ETH_QUEUE_LAST_RESOURCE) printf ("ETH Queue: using last available resource. \n"); - goto error; + return 1; } /* Update statistics and start of transmittion time */ @@ -918,10 +855,7 @@ int mv64460_eth_xmit (struct eth_device *dev, volatile void *dataPtr, } } while (release_result == ETH_OK); - return 0; /* success */ - - error: - return 1; /* Failed - higher layers will free the skb */ + return 0; /* success */ } /********************************************************************** @@ -931,7 +865,7 @@ int mv64460_eth_xmit (struct eth_device *dev, volatile void *dataPtr, * queues toward kernel core or FastRoute them to another interface. * * Input : dev - a pointer to the required interface - * max - maximum number to receive (0 means unlimted) + * max - maximum number to receive (0 means unlimted) * * Output : number of served packets **********************************************************************/ @@ -1054,7 +988,6 @@ static struct net_device_stats *mv64460_eth_get_stats (struct eth_device *dev) return port_private->stats; } - /********************************************************************** * mv64460_eth_update_stat * @@ -1136,7 +1069,7 @@ static void mv64460_eth_update_stat (struct eth_device *dev) /* detailed tx errors */ } -#ifndef UPDATE_STATS_BY_SOFTWARE +#ifndef UPDATE_STATS_BY_SOFTWARE /********************************************************************** * mv64460_eth_print_stat * @@ -1198,7 +1131,7 @@ bool db64460_eth_start (struct eth_device *dev) /************************************************************************* ************************************************************************** ************************************************************************** -* The second part is the low level driver of the gigE ethernet ports. * +* The second part is the low level driver of the gigE ethernet ports. * ************************************************************************** ************************************************************************** *************************************************************************/ @@ -1214,7 +1147,7 @@ bool db64460_eth_start (struct eth_device *dev) * 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 + * 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 @@ -1227,7 +1160,7 @@ bool db64460_eth_start (struct eth_device *dev) * Marvell's Gigabit Ethernet controller low level driver * * DESCRIPTION: - * This file introduce low level API to Marvell's Gigabit Ethernet + * This file introduce low level API to Marvell's Gigabit Ethernet * controller. This Gigabit Ethernet Controller driver API controls * 1) Operations (i.e. port init, start, reset etc'). * 2) Data flow (i.e. port send, receive etc'). @@ -1339,23 +1272,23 @@ bool db64460_eth_start (struct eth_device *dev) * * EXTERNAL INTERFACE * - * Prior to calling the initialization routine eth_port_init() the user + * Prior to calling the initialization routine eth_port_init() the user * must set the following fields under ETH_PORT_INFO struct: - * port_num User Ethernet port number. - * port_phy_addr User PHY address of Ethernet port. - * port_mac_addr[6] User defined port MAC address. - * port_config User port configuration value. - * port_config_extend User port config extend value. - * port_sdma_config User port SDMA config value. - * port_serial_control User port serial control value. - * *port_virt_to_phys () User function to cast virtual addr to CPU bus addr. - * *port_private User scratch pad for user specific data structures. + * port_num User Ethernet port number. + * port_phy_addr User PHY address of Ethernet port. + * port_mac_addr[6] User defined port MAC address. + * port_config User port configuration value. + * port_config_extend User port config extend value. + * port_sdma_config User port SDMA config value. + * port_serial_control User port serial control value. + * *port_virt_to_phys () User function to cast virtual addr to CPU bus addr. + * *port_private User scratch pad for user specific data structures. * - * This driver introduce a set of default values: - * PORT_CONFIG_VALUE Default port configuration value - * PORT_CONFIG_EXTEND_VALUE Default port extend configuration value - * PORT_SDMA_CONFIG_VALUE Default sdma control value - * PORT_SERIAL_CONTROL_VALUE Default port serial control value + * This driver introduce a set of default values: + * PORT_CONFIG_VALUE Default port configuration value + * PORT_CONFIG_EXTEND_VALUE Default port extend configuration value + * PORT_SDMA_CONFIG_VALUE Default sdma control value + * PORT_SERIAL_CONTROL_VALUE Default port serial control value * * This driver data flow is done using the PKT_INFO struct which is * a unified struct for Rx and Tx operations: @@ -1374,7 +1307,7 @@ bool db64460_eth_start (struct eth_device *dev) * * This macro applies assembly code to flush and invalidate cache * line. - * address - address base. + * address - address base. * address offset - address offset * * @@ -1522,25 +1455,25 @@ u32 mv_get_internal_sram_base (void) * eth_port_init - Initialize the Ethernet port driver * * DESCRIPTION: -* This function prepares the ethernet port to start its activity: -* 1) Completes the ethernet port driver struct initialization toward port -* start routine. -* 2) Resets the device to a quiescent state in case of warm reboot. -* 3) Enable SDMA access to all four DRAM banks as well as internal SRAM. -* 4) Clean MAC tables. The reset status of those tables is unknown. -* 5) Set PHY address. -* Note: Call this routine prior to eth_port_start routine and after setting -* user values in the user fields of Ethernet port control struct (i.e. -* port_phy_addr). +* This function prepares the ethernet port to start its activity: +* 1) Completes the ethernet port driver struct initialization toward port +* start routine. +* 2) Resets the device to a quiescent state in case of warm reboot. +* 3) Enable SDMA access to all four DRAM banks as well as internal SRAM. +* 4) Clean MAC tables. The reset status of those tables is unknown. +* 5) Set PHY address. +* Note: Call this routine prior to eth_port_start routine and after setting +* user values in the user fields of Ethernet port control struct (i.e. +* port_phy_addr). * * INPUT: -* ETH_PORT_INFO *p_eth_port_ctrl Ethernet port control struct +* ETH_PORT_INFO *p_eth_port_ctrl Ethernet port control struct * * OUTPUT: -* See description. +* See description. * * RETURN: -* None. +* None. * *******************************************************************************/ static void eth_port_init (ETH_PORT_INFO * p_eth_port_ctrl) @@ -1574,7 +1507,7 @@ static void eth_port_init (ETH_PORT_INFO * p_eth_port_ctrl) /* Set access parameters for DRAM bank 0 */ win_param.win = ETH_WIN0; /* Use Ethernet window 0 */ - win_param.target = ETH_TARGET_DRAM; /* Window target - DDR */ + win_param.target = ETH_TARGET_DRAM; /* Window target - DDR */ win_param.attributes = EBAR_ATTR_DRAM_CS0; /* Enable DRAM bank */ #ifndef CONFIG_NOT_COHERENT_CACHE win_param.attributes |= EBAR_ATTR_DRAM_CACHE_COHERENCY_WB; @@ -1582,7 +1515,7 @@ static void eth_port_init (ETH_PORT_INFO * p_eth_port_ctrl) win_param.high_addr = 0; /* Get bank base */ win_param.base_addr = mv_get_dram_bank_base_addr (BANK0); - win_param.size = mv_get_dram_bank_size (BANK0); /* Get bank size */ + win_param.size = mv_get_dram_bank_size (BANK0); /* Get bank size */ if (win_param.size == 0) win_param.enable = 0; else @@ -1602,7 +1535,7 @@ static void eth_port_init (ETH_PORT_INFO * p_eth_port_ctrl) win_param.high_addr = 0; /* Get bank base */ win_param.base_addr = mv_get_dram_bank_base_addr (BANK1); - win_param.size = mv_get_dram_bank_size (BANK1); /* Get bank size */ + win_param.size = mv_get_dram_bank_size (BANK1); /* Get bank size */ if (win_param.size == 0) win_param.enable = 0; else @@ -1622,7 +1555,7 @@ static void eth_port_init (ETH_PORT_INFO * p_eth_port_ctrl) win_param.high_addr = 0; /* Get bank base */ win_param.base_addr = mv_get_dram_bank_base_addr (BANK2); - win_param.size = mv_get_dram_bank_size (BANK2); /* Get bank size */ + win_param.size = mv_get_dram_bank_size (BANK2); /* Get bank size */ if (win_param.size == 0) win_param.enable = 0; else @@ -1642,7 +1575,7 @@ static void eth_port_init (ETH_PORT_INFO * p_eth_port_ctrl) win_param.high_addr = 0; /* Get bank base */ win_param.base_addr = mv_get_dram_bank_base_addr (BANK3); - win_param.size = mv_get_dram_bank_size (BANK3); /* Get bank size */ + win_param.size = mv_get_dram_bank_size (BANK3); /* Get bank size */ if (win_param.size == 0) win_param.enable = 0; else @@ -1678,30 +1611,30 @@ static void eth_port_init (ETH_PORT_INFO * p_eth_port_ctrl) * eth_port_start - Start the Ethernet port activity. * * DESCRIPTION: -* This routine prepares the Ethernet port for Rx and Tx activity: -* 1. Initialize Tx and Rx Current Descriptor Pointer for each queue that -* has been initialized a descriptor's ring (using ether_init_tx_desc_ring -* for Tx and ether_init_rx_desc_ring for Rx) -* 2. Initialize and enable the Ethernet configuration port by writing to -* the port's configuration and command registers. -* 3. Initialize and enable the SDMA by writing to the SDMA's +* This routine prepares the Ethernet port for Rx and Tx activity: +* 1. Initialize Tx and Rx Current Descriptor Pointer for each queue that +* has been initialized a descriptor's ring (using ether_init_tx_desc_ring +* for Tx and ether_init_rx_desc_ring for Rx) +* 2. Initialize and enable the Ethernet configuration port by writing to +* the port's configuration and command registers. +* 3. Initialize and enable the SDMA by writing to the SDMA's * configuration and command registers. -* After completing these steps, the ethernet port SDMA can starts to -* perform Rx and Tx activities. +* After completing these steps, the ethernet port SDMA can starts to +* perform Rx and Tx activities. * -* Note: Each Rx and Tx queue descriptor's list must be initialized prior -* to calling this function (use ether_init_tx_desc_ring for Tx queues and -* ether_init_rx_desc_ring for Rx queues). +* Note: Each Rx and Tx queue descriptor's list must be initialized prior +* to calling this function (use ether_init_tx_desc_ring for Tx queues and +* ether_init_rx_desc_ring for Rx queues). * * INPUT: -* ETH_PORT_INFO *p_eth_port_ctrl Ethernet port control struct +* ETH_PORT_INFO *p_eth_port_ctrl Ethernet port control struct * * OUTPUT: -* Ethernet port is ready to receive and transmit. +* Ethernet port is ready to receive and transmit. * * RETURN: -* false if the port PHY is not up. -* true otherwise. +* false if the port PHY is not up. +* true otherwise. * *******************************************************************************/ static bool eth_port_start (ETH_PORT_INFO * p_eth_port_ctrl) @@ -1712,7 +1645,6 @@ static bool eth_port_start (ETH_PORT_INFO * p_eth_port_ctrl) unsigned int phy_reg_data; ETH_PORT eth_port_num = p_eth_port_ctrl->port_num; - /* Assignment of Tx CTRP of given queue */ for (queue = 0; queue < MAX_TX_QUEUE_NUM; queue++) { CURR_TFD_GET (p_tx_curr_desc, queue); @@ -1782,13 +1714,13 @@ static bool eth_port_start (ETH_PORT_INFO * p_eth_port_ctrl) * This function Set the port Ethernet MAC address. * * INPUT: -* ETH_PORT eth_port_num Port number. -* char * p_addr Address to be set -* ETH_QUEUE queue Rx queue number for this MAC address. +* ETH_PORT eth_port_num Port number. +* char * p_addr Address to be set +* ETH_QUEUE queue Rx queue number for this MAC address. * * OUTPUT: * Set MAC address low and high registers. also calls eth_port_uc_addr() -* To set the unicast table with the proper information. +* To set the unicast table with the proper information. * * RETURN: * N/A. @@ -1822,10 +1754,10 @@ static void eth_port_uc_addr_set (ETH_PORT eth_port_num, * parameters. * * INPUT: -* ETH_PORT eth_port_num Port number. +* ETH_PORT eth_port_num Port number. * unsigned char uc_nibble Unicast MAC Address last nibble. -* ETH_QUEUE queue Rx queue number for this MAC address. -* int option 0 = Add, 1 = remove address. +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. * * OUTPUT: * This function add/removes MAC addresses from the port unicast address @@ -1904,10 +1836,10 @@ static bool eth_port_uc_addr (ETH_PORT eth_port_num, * In this case, the function calculates the CRC-8bit value and calls * eth_port_omc_addr() routine to set the Other Multicast Table. * INPUT: -* ETH_PORT eth_port_num Port number. -* unsigned char *p_addr Unicast MAC Address. -* ETH_QUEUE queue Rx queue number for this MAC address. -* int option 0 = Add, 1 = remove address. +* ETH_PORT eth_port_num Port number. +* unsigned char *p_addr Unicast MAC Address. +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. * * OUTPUT: * See description. @@ -1928,13 +1860,12 @@ static void eth_port_mc_addr (ETH_PORT eth_port_num, int crc[8]; int i; - if ((p_addr[0] == 0x01) && (p_addr[1] == 0x00) && - (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) + (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) { eth_port_smc_addr (eth_port_num, p_addr[5], queue, option); - else { + } else { /* Calculate CRC-8 out of the given address */ mac_h = (p_addr[0] << 8) | (p_addr[1]); mac_l = (p_addr[2] << 24) | (p_addr[3] << 16) | @@ -1945,7 +1876,6 @@ static void eth_port_mc_addr (ETH_PORT eth_port_num, for (i = 32; i < 48; i++) mac_array[i] = (mac_h >> (i - 32)) & 0x1; - crc[0] = mac_array[45] ^ mac_array[43] ^ mac_array[40] ^ mac_array[39] ^ mac_array[35] ^ mac_array[34] ^ mac_array[31] ^ mac_array[30] ^ mac_array[28] ^ @@ -2038,10 +1968,10 @@ static void eth_port_mc_addr (ETH_PORT eth_port_num, * according to the argument given. * * INPUT: -* ETH_PORT eth_port_num Port number. -* unsigned char mc_byte Multicast addr last byte (MAC DA[7:0] bits). -* ETH_QUEUE queue Rx queue number for this MAC address. -* int option 0 = Add, 1 = remove address. +* ETH_PORT eth_port_num Port number. +* unsigned char mc_byte Multicast addr last byte (MAC DA[7:0] bits). +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. * * OUTPUT: * See description. @@ -2060,7 +1990,7 @@ static bool eth_port_smc_addr (ETH_PORT eth_port_num, unsigned int reg_offset; /* Locate the SMC table entry */ - tbl_offset = (mc_byte / 4) * 4; /* Register offset from SMC table base */ + tbl_offset = (mc_byte / 4) * 4; /* Register offset from SMC table base */ reg_offset = mc_byte % 4; /* Entry offset within the above register */ queue &= 0x7; @@ -2102,10 +2032,10 @@ static bool eth_port_smc_addr (ETH_PORT eth_port_num, * CRC-8 argument given. * * INPUT: -* ETH_PORT eth_port_num Port number. -* unsigned char crc8 A CRC-8bit (Polynomial: x^8+x^2+x^1+1). -* ETH_QUEUE queue Rx queue number for this MAC address. -* int option 0 = Add, 1 = remove address. +* ETH_PORT eth_port_num Port number. +* unsigned char crc8 A CRC-8bit (Polynomial: x^8+x^2+x^1+1). +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. * * OUTPUT: * See description. @@ -2158,17 +2088,17 @@ static bool eth_port_omc_addr (ETH_PORT eth_port_num, * eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables * * DESCRIPTION: -* Go through all the DA filter tables (Unicast, Special Multicast & Other -* Multicast) and set each entry to 0. +* Go through all the DA filter tables (Unicast, Special Multicast & Other +* Multicast) and set each entry to 0. * * INPUT: * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. * * OUTPUT: -* Multicast and Unicast packets are rejected. +* Multicast and Unicast packets are rejected. * * RETURN: -* None. +* None. * *******************************************************************************/ static void eth_port_init_mac_tables (ETH_PORT eth_port_num) @@ -2192,17 +2122,17 @@ static void eth_port_init_mac_tables (ETH_PORT eth_port_num) * eth_clear_mib_counters - Clear all MIB counters * * DESCRIPTION: -* This function clears all MIB counters of a specific ethernet port. -* A read from the MIB counter will reset the counter. +* This function clears all MIB counters of a specific ethernet port. +* A read from the MIB counter will reset the counter. * * INPUT: * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. * * OUTPUT: -* After reading all MIB counters, the counters resets. +* After reading all MIB counters, the counters resets. * * RETURN: -* MIB counter value. +* MIB counter value. * *******************************************************************************/ static void eth_clear_mib_counters (ETH_PORT eth_port_num) @@ -2223,21 +2153,21 @@ static void eth_clear_mib_counters (ETH_PORT eth_port_num) * eth_read_mib_counter - Read a MIB counter * * DESCRIPTION: -* This function reads a MIB counter of a specific ethernet port. -* NOTE - If read from ETH_MIB_GOOD_OCTETS_RECEIVED_LOW, then the -* following read must be from ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH -* register. The same applies for ETH_MIB_GOOD_OCTETS_SENT_LOW and -* ETH_MIB_GOOD_OCTETS_SENT_HIGH +* This function reads a MIB counter of a specific ethernet port. +* NOTE - If read from ETH_MIB_GOOD_OCTETS_RECEIVED_LOW, then the +* following read must be from ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH +* register. The same applies for ETH_MIB_GOOD_OCTETS_SENT_LOW and +* ETH_MIB_GOOD_OCTETS_SENT_HIGH * * INPUT: * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. -* unsigned int mib_offset MIB counter offset (use ETH_MIB_... macros). +* unsigned int mib_offset MIB counter offset (use ETH_MIB_... macros). * * OUTPUT: -* After reading the MIB counter, the counter resets. +* After reading the MIB counter, the counter resets. * * RETURN: -* MIB counter value. +* MIB counter value. * *******************************************************************************/ unsigned int eth_read_mib_counter (ETH_PORT eth_port_num, @@ -2251,17 +2181,17 @@ unsigned int eth_read_mib_counter (ETH_PORT eth_port_num, * ethernet_phy_set - Set the ethernet port PHY address. * * DESCRIPTION: -* This routine set the ethernet port PHY address according to given -* parameter. +* This routine set the ethernet port PHY address according to given +* parameter. * * INPUT: -* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. * * OUTPUT: -* Set PHY Address Register with given PHY address parameter. +* Set PHY Address Register with given PHY address parameter. * * RETURN: -* None. +* None. * *******************************************************************************/ static void ethernet_phy_set (ETH_PORT eth_port_num, int phy_addr) @@ -2282,16 +2212,16 @@ static void ethernet_phy_set (ETH_PORT eth_port_num, int phy_addr) * ethernet_phy_get - Get the ethernet port PHY address. * * DESCRIPTION: - * This routine returns the given ethernet port PHY address. + * This routine returns the given ethernet port PHY address. * * INPUT: - * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. * * OUTPUT: - * None. + * None. * * RETURN: - * PHY address. + * PHY address. * *******************************************************************************/ static int ethernet_phy_get (ETH_PORT eth_port_num) @@ -2333,17 +2263,17 @@ int phy_setup_aneg (char *devname, unsigned char addr) * ethernet_phy_reset - Reset Ethernet port PHY. * * DESCRIPTION: - * This routine utilize the SMI interface to reset the ethernet port PHY. - * The routine waits until the link is up again or link up is timeout. + * This routine utilize the SMI interface to reset the ethernet port PHY. + * The routine waits until the link is up again or link up is timeout. * * INPUT: - * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. * * OUTPUT: - * The ethernet port PHY renew its link. + * The ethernet port PHY renew its link. * * RETURN: - * None. + * None. * *******************************************************************************/ static bool ethernet_phy_reset (ETH_PORT eth_port_num) @@ -2352,12 +2282,12 @@ static bool ethernet_phy_reset (ETH_PORT eth_port_num) unsigned int phy_reg_data; eth_port_read_smi_reg (eth_port_num, 20, &phy_reg_data); - phy_reg_data |= 0x0083; /* Set bit 7 to 1 for different RGMII timing */ + phy_reg_data |= 0x0083; /* Set bit 7 to 1 for different RGMII timing */ eth_port_write_smi_reg (eth_port_num, 20, phy_reg_data); /* Reset the PHY */ eth_port_read_smi_reg (eth_port_num, 0, &phy_reg_data); - phy_reg_data |= 0x8000; /* Set bit 15 to reset the PHY */ + phy_reg_data |= 0x8000; /* Set bit 15 to reset the PHY */ eth_port_write_smi_reg (eth_port_num, 0, phy_reg_data); /* Poll on the PHY LINK */ @@ -2376,18 +2306,18 @@ static bool ethernet_phy_reset (ETH_PORT eth_port_num) * eth_port_reset - Reset Ethernet port * * DESCRIPTION: - * This routine resets the chip by aborting any SDMA engine activity and - * clearing the MIB counters. The Receiver and the Transmit unit are in - * idle state after this command is performed and the port is disabled. + * This routine resets the chip by aborting any SDMA engine activity and + * clearing the MIB counters. The Receiver and the Transmit unit are in + * idle state after this command is performed and the port is disabled. * * INPUT: - * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. * * OUTPUT: - * Channel activity is halted. + * Channel activity is halted. * * RETURN: - * None. + * None. * *******************************************************************************/ static void eth_port_reset (ETH_PORT eth_port_num) @@ -2455,19 +2385,19 @@ static void eth_port_reset (ETH_PORT eth_port_num) * ethernet_set_config_reg - Set specified bits in configuration register. * * DESCRIPTION: - * This function sets specified bits in the given ethernet - * configuration register. + * This function sets specified bits in the given ethernet + * configuration register. * * INPUT: - * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. - * unsigned int value 32 bit value. + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int value 32 bit value. * * OUTPUT: - * The set bits in the value parameter are set in the configuration - * register. + * The set bits in the value parameter are set in the configuration + * register. * * RETURN: - * None. + * None. * *******************************************************************************/ static void ethernet_set_config_reg (ETH_PORT eth_port_num, @@ -2490,19 +2420,19 @@ static void ethernet_set_config_reg (ETH_PORT eth_port_num, * ethernet_reset_config_reg - Reset specified bits in configuration register. * * DESCRIPTION: - * This function resets specified bits in the given Ethernet - * configuration register. + * This function resets specified bits in the given Ethernet + * configuration register. * * INPUT: - * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. - * unsigned int value 32 bit value. + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int value 32 bit value. * * OUTPUT: - * The set bits in the value parameter are reset in the configuration - * register. + * The set bits in the value parameter are reset in the configuration + * register. * * RETURN: - * None. + * None. * *******************************************************************************/ static void ethernet_reset_config_reg (ETH_PORT eth_port_num, @@ -2525,17 +2455,17 @@ static void ethernet_reset_config_reg (ETH_PORT eth_port_num, * ethernet_get_config_reg - Get the port configuration register * * DESCRIPTION: - * This function returns the configuration register value of the given - * ethernet port. + * This function returns the configuration register value of the given + * ethernet port. * * INPUT: - * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. * * OUTPUT: - * None. + * None. * * RETURN: - * Port configuration register value. + * Port configuration register value. * *******************************************************************************/ static unsigned int ethernet_get_config_reg (ETH_PORT eth_port_num) @@ -2553,20 +2483,20 @@ static unsigned int ethernet_get_config_reg (ETH_PORT eth_port_num) * eth_port_read_smi_reg - Read PHY registers * * DESCRIPTION: - * This routine utilize the SMI interface to interact with the PHY in - * order to perform PHY register read. + * This routine utilize the SMI interface to interact with the PHY in + * order to perform PHY register read. * * INPUT: - * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. - * unsigned int phy_reg PHY register address offset. - * unsigned int *value Register value buffer. + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int phy_reg PHY register address offset. + * unsigned int *value Register value buffer. * * OUTPUT: - * Write the value of a specified PHY register into given buffer. + * Write the value of a specified PHY register into given buffer. * * RETURN: - * false if the PHY is busy or read data is not in valid state. - * true otherwise. + * false if the PHY is busy or read data is not in valid state. + * true otherwise. * *******************************************************************************/ static bool eth_port_read_smi_reg (ETH_PORT eth_port_num, @@ -2601,7 +2531,7 @@ static bool eth_port_read_smi_reg (ETH_PORT eth_port_num, return false; } } - while ((reg_value & ETH_SMI_READ_VALID) != ETH_SMI_READ_VALID); /* Bit set equ operation done */ + while ((reg_value & ETH_SMI_READ_VALID) != ETH_SMI_READ_VALID); /* Bit set equ operation done */ /* Wait for the data to update in the SMI register */ #define PHY_UPDATE_TIMEOUT 10000 @@ -2642,7 +2572,7 @@ int mv_miiphy_read(char *devname, unsigned char phy_addr, return false; } } - while ((reg_value & ETH_SMI_READ_VALID) != ETH_SMI_READ_VALID); /* Bit set equ operation done */ + while ((reg_value & ETH_SMI_READ_VALID) != ETH_SMI_READ_VALID); /* Bit set equ operation done */ /* Wait for the data to update in the SMI register */ for (time_out = 0; time_out < PHY_UPDATE_TIMEOUT; time_out++); @@ -2658,20 +2588,20 @@ int mv_miiphy_read(char *devname, unsigned char phy_addr, * eth_port_write_smi_reg - Write to PHY registers * * DESCRIPTION: - * This routine utilize the SMI interface to interact with the PHY in - * order to perform writes to PHY registers. + * This routine utilize the SMI interface to interact with the PHY in + * order to perform writes to PHY registers. * * INPUT: - * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. - * unsigned int phy_reg PHY register address offset. - * unsigned int value Register value. + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int phy_reg PHY register address offset. + * unsigned int value Register value. * * OUTPUT: - * Write the given value to the specified PHY register. + * Write the given value to the specified PHY register. * * RETURN: - * false if the PHY is busy. - * true otherwise. + * false if the PHY is busy. + * true otherwise. * *******************************************************************************/ static bool eth_port_write_smi_reg (ETH_PORT eth_port_num, @@ -2725,18 +2655,18 @@ int mv_miiphy_write(char *devname, unsigned char phy_addr, * eth_set_access_control - Config address decode parameters for Ethernet unit * * DESCRIPTION: - * This function configures the address decode parameters for the Gigabit - * Ethernet Controller according the given parameters struct. + * This function configures the address decode parameters for the Gigabit + * Ethernet Controller according the given parameters struct. * * INPUT: - * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. - * ETH_WIN_PARAM *param Address decode parameter struct. + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * ETH_WIN_PARAM *param Address decode parameter struct. * * OUTPUT: - * An access window is opened using the given access parameters. + * An access window is opened using the given access parameters. * * RETURN: - * None. + * None. * *******************************************************************************/ static void eth_set_access_control (ETH_PORT eth_port_num, @@ -2779,30 +2709,30 @@ static void eth_set_access_control (ETH_PORT eth_port_num, * ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory. * * DESCRIPTION: - * This function prepares a Rx chained list of descriptors and packet - * buffers in a form of a ring. The routine must be called after port - * initialization routine and before port start routine. - * The Ethernet SDMA engine uses CPU bus addresses to access the various - * devices in the system (i.e. DRAM). This function uses the ethernet - * struct 'virtual to physical' routine (set by the user) to set the ring - * with physical addresses. + * This function prepares a Rx chained list of descriptors and packet + * buffers in a form of a ring. The routine must be called after port + * initialization routine and before port start routine. + * The Ethernet SDMA engine uses CPU bus addresses to access the various + * devices in the system (i.e. DRAM). This function uses the ethernet + * struct 'virtual to physical' routine (set by the user) to set the ring + * with physical addresses. * * INPUT: - * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. - * ETH_QUEUE rx_queue Number of Rx queue. - * int rx_desc_num Number of Rx descriptors - * int rx_buff_size Size of Rx buffer - * unsigned int rx_desc_base_addr Rx descriptors memory area base addr. - * unsigned int rx_buff_base_addr Rx buffer memory area base addr. + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * int rx_desc_num Number of Rx descriptors + * int rx_buff_size Size of Rx buffer + * unsigned int rx_desc_base_addr Rx descriptors memory area base addr. + * unsigned int rx_buff_base_addr Rx buffer memory area base addr. * * OUTPUT: - * The routine updates the Ethernet port control struct with information - * regarding the Rx descriptors and buffers. + * The routine updates the Ethernet port control struct with information + * regarding the Rx descriptors and buffers. * * RETURN: - * false if the given descriptors memory area is not aligned according to - * Ethernet SDMA specifications. - * true otherwise. + * false if the given descriptors memory area is not aligned according to + * Ethernet SDMA specifications. + * true otherwise. * *******************************************************************************/ static bool ether_init_rx_desc_ring (ETH_PORT_INFO * p_eth_port_ctrl, @@ -2817,7 +2747,6 @@ static bool ether_init_rx_desc_ring (ETH_PORT_INFO * p_eth_port_ctrl, unsigned int buffer_addr; int ix; /* a counter */ - p_rx_desc = (ETH_RX_DESC *) rx_desc_base_addr; p_rx_prev_desc = p_rx_desc; buffer_addr = rx_buff_base_addr; @@ -2830,7 +2759,7 @@ static bool ether_init_rx_desc_ring (ETH_PORT_INFO * p_eth_port_ctrl, if ((rx_buff_size < 8) || (rx_buff_size > RX_BUFFER_MAX_SIZE)) return false; - /* Rx buffers must be 64-bit aligned. */ + /* Rx buffers must be 64-bit aligned. */ if ((rx_buff_base_addr + rx_buff_size) & 0x7) return false; @@ -2873,30 +2802,30 @@ static bool ether_init_rx_desc_ring (ETH_PORT_INFO * p_eth_port_ctrl, * ether_init_tx_desc_ring - Curve a Tx chain desc list and buffer in memory. * * DESCRIPTION: - * This function prepares a Tx chained list of descriptors and packet - * buffers in a form of a ring. The routine must be called after port - * initialization routine and before port start routine. - * The Ethernet SDMA engine uses CPU bus addresses to access the various - * devices in the system (i.e. DRAM). This function uses the ethernet - * struct 'virtual to physical' routine (set by the user) to set the ring - * with physical addresses. + * This function prepares a Tx chained list of descriptors and packet + * buffers in a form of a ring. The routine must be called after port + * initialization routine and before port start routine. + * The Ethernet SDMA engine uses CPU bus addresses to access the various + * devices in the system (i.e. DRAM). This function uses the ethernet + * struct 'virtual to physical' routine (set by the user) to set the ring + * with physical addresses. * * INPUT: - * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. - * ETH_QUEUE tx_queue Number of Tx queue. - * int tx_desc_num Number of Tx descriptors - * int tx_buff_size Size of Tx buffer - * unsigned int tx_desc_base_addr Tx descriptors memory area base addr. - * unsigned int tx_buff_base_addr Tx buffer memory area base addr. + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * int tx_desc_num Number of Tx descriptors + * int tx_buff_size Size of Tx buffer + * unsigned int tx_desc_base_addr Tx descriptors memory area base addr. + * unsigned int tx_buff_base_addr Tx buffer memory area base addr. * * OUTPUT: - * The routine updates the Ethernet port control struct with information - * regarding the Tx descriptors and buffers. + * The routine updates the Ethernet port control struct with information + * regarding the Tx descriptors and buffers. * * RETURN: - * false if the given descriptors memory area is not aligned according to - * Ethernet SDMA specifications. - * true otherwise. + * false if the given descriptors memory area is not aligned according to + * Ethernet SDMA specifications. + * true otherwise. * *******************************************************************************/ static bool ether_init_tx_desc_ring (ETH_PORT_INFO * p_eth_port_ctrl, @@ -2912,7 +2841,6 @@ static bool ether_init_tx_desc_ring (ETH_PORT_INFO * p_eth_port_ctrl, unsigned int buffer_addr; int ix; /* a counter */ - /* save the first desc pointer to link with the last descriptor */ p_tx_desc = (ETH_TX_DESC *) tx_desc_base_addr; p_tx_prev_desc = p_tx_desc; @@ -2968,27 +2896,27 @@ static bool ether_init_tx_desc_ring (ETH_PORT_INFO * p_eth_port_ctrl, * * DESCRIPTION: * This routine send a given packet described by p_pktinfo parameter. It - * supports transmitting of a packet spaned over multiple buffers. The - * routine updates 'curr' and 'first' indexes according to the packet - * segment passed to the routine. In case the packet segment is first, - * the 'first' index is update. In any case, the 'curr' index is updated. - * If the routine get into Tx resource error it assigns 'curr' index as - * 'first'. This way the function can abort Tx process of multiple - * descriptors per packet. + * supports transmitting of a packet spaned over multiple buffers. The + * routine updates 'curr' and 'first' indexes according to the packet + * segment passed to the routine. In case the packet segment is first, + * the 'first' index is update. In any case, the 'curr' index is updated. + * If the routine get into Tx resource error it assigns 'curr' index as + * 'first'. This way the function can abort Tx process of multiple + * descriptors per packet. * * INPUT: - * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. - * ETH_QUEUE tx_queue Number of Tx queue. - * PKT_INFO *p_pkt_info User packet buffer. + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * PKT_INFO *p_pkt_info User packet buffer. * * OUTPUT: * Tx ring 'curr' and 'first' indexes are updated. * * RETURN: - * ETH_QUEUE_FULL in case of Tx resource error. + * ETH_QUEUE_FULL in case of Tx resource error. * ETH_ERROR in case the routine can not access Tx desc ring. * ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource. - * ETH_OK otherwise. + * ETH_OK otherwise. * *******************************************************************************/ static ETH_FUNC_RET_STATUS eth_port_send (ETH_PORT_INFO * p_eth_port_ctrl, @@ -3026,7 +2954,7 @@ static ETH_FUNC_RET_STATUS eth_port_send (ETH_PORT_INFO * p_eth_port_ctrl, } /* Buffers with a payload smaller than 8 bytes must be aligned to 64-bit */ - /* boundary. We use the memory allocated for Tx descriptor. This memory */ + /* boundary. We use the memory allocated for Tx descriptor. This memory */ /* located in TX_BUF_OFFSET_IN_DESC offset within the Tx descriptor. */ if (p_pkt_info->byte_cnt <= 8) { printf ("You have failed in the < 8 bytes errata - fixme\n"); /* RABEEH - TBD */ @@ -3087,24 +3015,24 @@ static ETH_FUNC_RET_STATUS eth_port_send (ETH_PORT_INFO * p_eth_port_ctrl, * * DESCRIPTION: * This routine returns the transmitted packet information to the caller. - * It uses the 'first' index to support Tx desc return in case a transmit - * of a packet spanned over multiple buffer still in process. - * In case the Tx queue was in "resource error" condition, where there are - * no available Tx resources, the function resets the resource error flag. + * It uses the 'first' index to support Tx desc return in case a transmit + * of a packet spanned over multiple buffer still in process. + * In case the Tx queue was in "resource error" condition, where there are + * no available Tx resources, the function resets the resource error flag. * * INPUT: - * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. - * ETH_QUEUE tx_queue Number of Tx queue. - * PKT_INFO *p_pkt_info User packet buffer. + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * PKT_INFO *p_pkt_info User packet buffer. * * OUTPUT: * Tx ring 'first' and 'used' indexes are updated. * * RETURN: * ETH_ERROR in case the routine can not access Tx desc ring. - * ETH_RETRY in case there is transmission in process. + * ETH_RETRY in case there is transmission in process. * ETH_END_OF_JOB if the routine has nothing to release. - * ETH_OK otherwise. + * ETH_OK otherwise. * *******************************************************************************/ static ETH_FUNC_RET_STATUS eth_tx_return_desc (ETH_PORT_INFO * @@ -3116,12 +3044,10 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc (ETH_PORT_INFO * volatile ETH_TX_DESC *p_tx_desc_first = NULL; unsigned int command_status; - /* Get the Tx Desc ring indexes */ USED_TFD_GET (p_tx_desc_used, tx_queue); FIRST_TFD_GET (p_tx_desc_first, tx_queue); - /* Sanity check */ if (p_tx_desc_used == NULL) return ETH_ERROR; @@ -3163,16 +3089,16 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc (ETH_PORT_INFO * * eth_port_receive - Get received information from Rx ring. * * DESCRIPTION: - * This routine returns the received data to the caller. There is no + * This routine returns the received data to the caller. There is no * data copying during routine operation. All information is returned * using pointer to packet information struct passed from the caller. - * If the routine exhausts Rx ring resources then the resource error flag - * is set. + * If the routine exhausts Rx ring resources then the resource error flag + * is set. * * INPUT: - * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. - * ETH_QUEUE rx_queue Number of Rx queue. - * PKT_INFO *p_pkt_info User packet buffer. + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * PKT_INFO *p_pkt_info User packet buffer. * * OUTPUT: * Rx ring current and used indexes are updated. @@ -3181,7 +3107,7 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc (ETH_PORT_INFO * * ETH_ERROR in case the routine can not access Rx desc ring. * ETH_QUEUE_FULL if Rx ring resources are exhausted. * ETH_END_OF_JOB if there is no received data. - * ETH_OK otherwise. + * ETH_OK otherwise. * *******************************************************************************/ static ETH_FUNC_RET_STATUS eth_port_receive (ETH_PORT_INFO * p_eth_port_ctrl, @@ -3213,7 +3139,7 @@ static ETH_FUNC_RET_STATUS eth_port_receive (ETH_PORT_INFO * p_eth_port_ctrl, /* Nothing to receive... */ if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) { -/* DP(printf("Rx: command_status: %08x\n", command_status)); */ +/* DP(printf("Rx: command_status: %08x\n", command_status)); */ D_CACHE_FLUSH_LINE ((unsigned int) p_rx_curr_desc, 0); /* DP(printf("\nETH_END_OF_JOB ...\n"));*/ return ETH_END_OF_JOB; @@ -3223,10 +3149,10 @@ static ETH_FUNC_RET_STATUS eth_port_receive (ETH_PORT_INFO * p_eth_port_ctrl, p_pkt_info->cmd_sts = command_status; p_pkt_info->buf_ptr = (p_rx_curr_desc->buf_ptr) + RX_BUF_OFFSET; p_pkt_info->return_info = p_rx_curr_desc->return_info; - p_pkt_info->l4i_chk = p_rx_curr_desc->buf_size; /* IP fragment indicator */ + p_pkt_info->l4i_chk = p_rx_curr_desc->buf_size; /* IP fragment indicator */ /* Clean the return info field to indicate that the packet has been */ - /* moved to the upper layers */ + /* moved to the upper layers */ p_rx_curr_desc->return_info = 0; /* Update 'curr' in data structure */ @@ -3247,21 +3173,21 @@ static ETH_FUNC_RET_STATUS eth_port_receive (ETH_PORT_INFO * p_eth_port_ctrl, * * DESCRIPTION: * This routine returns a Rx buffer back to the Rx ring. It retrieves the - * next 'used' descriptor and attached the returned buffer to it. - * In case the Rx ring was in "resource error" condition, where there are - * no available Rx resources, the function resets the resource error flag. + * next 'used' descriptor and attached the returned buffer to it. + * In case the Rx ring was in "resource error" condition, where there are + * no available Rx resources, the function resets the resource error flag. * * INPUT: - * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. - * ETH_QUEUE rx_queue Number of Rx queue. - * PKT_INFO *p_pkt_info Information on the returned buffer. + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * PKT_INFO *p_pkt_info Information on the returned buffer. * * OUTPUT: * New available Rx resource in Rx descriptor ring. * * RETURN: * ETH_ERROR in case the routine can not access Rx desc ring. - * ETH_OK otherwise. + * ETH_OK otherwise. * *******************************************************************************/ static ETH_FUNC_RET_STATUS eth_rx_return_buff (ETH_PORT_INFO * @@ -3316,9 +3242,9 @@ static ETH_FUNC_RET_STATUS eth_rx_return_buff (ETH_PORT_INFO * * , and the required delay of the interrupt in usec. * * INPUT: - * ETH_PORT eth_port_num Ethernet port number - * unsigned int t_clk t_clk of the MV-643xx chip in HZ units - * unsigned int delay Delay in usec + * ETH_PORT eth_port_num Ethernet port number + * unsigned int t_clk t_clk of the MV-643xx chip in HZ units + * unsigned int delay Delay in usec * * OUTPUT: * Interrupt coalescing mechanism value is set in MV-643xx chip. @@ -3357,9 +3283,9 @@ static unsigned int eth_port_set_rx_coal (ETH_PORT eth_port_num, * MV-643xx chip and the required delay in the interrupt in uSec * * INPUT: - * ETH_PORT eth_port_num Ethernet port number - * unsigned int t_clk t_clk of the MV-643xx chip in HZ units - * unsigned int delay Delay in uSeconds + * ETH_PORT eth_port_num Ethernet port number + * unsigned int t_clk t_clk of the MV-643xx chip in HZ units + * unsigned int delay Delay in uSeconds * * OUTPUT: * Interrupt coalescing mechanism value is set in MV-643xx chip. @@ -3387,20 +3313,20 @@ static unsigned int eth_port_set_tx_coal (ETH_PORT eth_port_num, * eth_b_copy - Copy bytes from source to destination * * DESCRIPTION: - * This function supports the eight bytes limitation on Tx buffer size. - * The routine will zero eight bytes starting from the destination address - * followed by copying bytes from the source address to the destination. + * This function supports the eight bytes limitation on Tx buffer size. + * The routine will zero eight bytes starting from the destination address + * followed by copying bytes from the source address to the destination. * * INPUT: - * unsigned int src_addr 32 bit source address. - * unsigned int dst_addr 32 bit destination address. - * int byte_count Number of bytes to copy. + * unsigned int src_addr 32 bit source address. + * unsigned int dst_addr 32 bit destination address. + * int byte_count Number of bytes to copy. * * OUTPUT: - * See description. + * See description. * * RETURN: - * None. + * None. * *******************************************************************************/ static void eth_b_copy (unsigned int src_addr, unsigned int dst_addr, diff --git a/board/prodrive/p3mx/sdram_init.c b/board/prodrive/p3mx/sdram_init.c index b4556debff..176252efee 100644 --- a/board/prodrive/p3mx/sdram_init.c +++ b/board/prodrive/p3mx/sdram_init.c @@ -12,7 +12,7 @@ * * 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 + * 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 @@ -44,7 +44,7 @@ DECLARE_GLOBAL_DATA_PTR; #undef DEBUG -#define MAP_PCI +#define MAP_PCI #ifdef DEBUG #define DP(x) x @@ -70,11 +70,12 @@ int memory_map_bank (unsigned int bankNo, #endif #ifdef DEBUG - if (bankLength > 0) + if (bankLength > 0) { printf ("mapping bank %d at %08x - %08x\n", bankNo, bankBase, bankBase + bankLength - 1); - else + } else { printf ("unmapping bank %d\n", bankNo); + } #endif memoryMapBank (bankNo, bankBase, bankLength); @@ -176,7 +177,7 @@ long int initdram (int board_type) /* calibrate delay lines */ set_dfcdlInit(); - GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_NOP); /* 0x1418 */ + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_NOP); /* 0x1418 */ do { tmp = GTREGREAD(MV64460_SDRAM_OPERATION); } while(tmp != 0x0); @@ -197,8 +198,8 @@ long int initdram (int board_type) /* SDRAM drive strength */ GT_REG_WRITE(MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x80000000); /* 0x14C0 */ GT_REG_WRITE(MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x80000008); /* 0x14C0 */ - GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000000); /* 0x14C4 */ - GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000008); /* 0x14C4 */ + GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000000); /* 0x14C4 */ + GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000008); /* 0x14C4 */ /* setup SDRAM device registers */ @@ -306,22 +307,22 @@ void board_add_ram_info(int use_default) /* * mvDmaIsChannelActive - Check if IDMA channel is active * - * channel = IDMA channel number from 0 to 7 + * channel = IDMA channel number from 0 to 7 */ int mvDmaIsChannelActive (int channel) { - ulong data; + ulong data; - data = GTREGREAD (MV64460_DMA_CHANNEL0_CONTROL + 4 * channel); - if (data & BIT14) /* activity status */ - return 1; + data = GTREGREAD (MV64460_DMA_CHANNEL0_CONTROL + 4 * channel); + if (data & BIT14) /* activity status */ + return 1; - return 0; + return 0; } /* * mvDmaSetMemorySpace - Set a DMA memory window for the DMA's address decoding - * map. + * map. * * memSpace = IDMA memory window number from 0 to 7 * trg_if = Target interface: @@ -363,9 +364,9 @@ int mvDmaSetMemorySpace (ulong memSpace, /* * mvDmaTransfer - Transfer data from src_addr to dst_addr on one of the 4 - * DMA channels. + * DMA channels. * - * channel = IDMA channel number from 0 to 3 + * channel = IDMA channel number from 0 to 3 * destAddr = Destination address * sourceAddr = Source address * size = Size in bytes @@ -385,7 +386,7 @@ int mvDmaTransfer (int channel, ulong sourceAddr, GT_REG_WRITE (MV64460_DMA_CHANNEL0_SOURCE_ADDR + engOffReg, sourceAddr); GT_REG_WRITE (MV64460_DMA_CHANNEL0_DESTINATION_ADDR + engOffReg, destAddr); command = command | - BIT12 | /* DMA_CHANNEL_ENABLE */ + BIT12 | /* DMA_CHANNEL_ENABLE */ BIT9; /* DMA_NON_CHAIN_MODE */ /* Activate DMA channel By writting to mvDmaControlRegister */ GT_REG_WRITE (MV64460_DMA_CHANNEL0_CONTROL + engOffReg, command);