diff options
author | wdenk <wdenk> | 2004-01-03 00:43:19 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2004-01-03 00:43:19 +0000 |
commit | 3a473b2a6523db9cdf2b5aed22d9730b4ebc5693 (patch) | |
tree | 40da84736871e773141ea971d832bf0c908d59b7 /board | |
parent | b6e4c4033c4f889c452c511d38c77808c67f9cf7 (diff) | |
download | u-boot-imx-3a473b2a6523db9cdf2b5aed22d9730b4ebc5693.zip u-boot-imx-3a473b2a6523db9cdf2b5aed22d9730b4ebc5693.tar.gz u-boot-imx-3a473b2a6523db9cdf2b5aed22d9730b4ebc5693.tar.bz2 |
* Patch by Ronen Shitrit, 10 Dec 2003:
Add support for the Marvell DB64360 / DB64460 development boards
* Patch by Detlev Zundel, 10 Dec 2003:
fix dependency problem in examples/Makefile
Diffstat (limited to 'board')
46 files changed, 28617 insertions, 116 deletions
diff --git a/board/Marvell/common/bootseq.txt b/board/Marvell/common/bootseq.txt new file mode 100644 index 0000000..648c2ff --- /dev/null +++ b/board/Marvell/common/bootseq.txt @@ -0,0 +1,94 @@ +(cpu/mpc7xxx/start.S) + +start: + b boot_cold + +start_warm: + b boot_warm + + +boot_cold: +boot_warm: + clear bats + init l2 (if enabled) + init altivec (if enabled) + invalidate l2 (if enabled) + setup bats (from defines in config_EVB) + enable_addr_trans: (if MMU enabled) + enable MSR_IR and MSR_DR + jump to in_flash + +in_flash: + enable l1 dcache + gal_low_init: (board/evb64260/sdram_init.S) + config SDRAM (CFG, TIMING, DECODE) + init scratch regs (810 + 814) + + detect DIMM0 (bank 0 only) + config SDRAM_PARA0 to 256/512Mbit + bl sdram_op_mode + detect bank0 width + write scratch reg 810 + config SDRAM_PARA0 with results + config SDRAM_PARA1 with results + + detect DIMM1 (bank 2 only) + config SDRAM_PARA2 to 256/512Mbit + detect bank2 width + write scratch reg 814 + config SDRAM_PARA2 with results + config SDRAM_PARA3 with results + + setup device bus timings/width + setup boot device timings/width + + setup CPU_CONF (0x0) + setup cpu master control register 0x160 + setup PCI0 TIMEOUT + setup PCI1 TIMEOUT + setup PCI0 BAR + setup PCI1 BAR + + setup MPP control 0-3 + setup GPP level control + setup Serial ports multiplex + + setup stack pointer (r1) + setup GOT + call cpu_init_f + debug leds + board_init_f: (common/board.c) + board_pre_init: + remap gt regs? + map PCI mem/io + map device space + clear out interupts + init_timebase + env_init + serial_init + console_init_f + display_options + initdram: (board/evb64260/evb64260.c) + detect memory + for each bank: + dram_size() + setup PCI slave memory mappings + setup SCS + setup monitor + alloc board info struct + init bd struct + relocate_code: (cpu/mpc7xxx/start.S) + copy,got,clearbss + board_init_r(bd, dest_addr) (common/board.c) + setup bd function pointers + trap_init + flash_init: (board/evb64260/flash.c) + setup bd flash info + cpu_init_r: (cpu/mpc7xxx/cpu_init.c) + nothing + mem_malloc_init + malloc_bin_reloc + spi_init (r or f)??? (CFG_ENV_IS_IN_EEPROM) + env_relocated + misc_init_r(bd): (board/evb64260/evb64260.c) + mpsc_init2 diff --git a/board/Marvell/common/ecctest.c b/board/Marvell/common/ecctest.c new file mode 100644 index 0000000..6247b45 --- /dev/null +++ b/board/Marvell/common/ecctest.c @@ -0,0 +1,133 @@ +indent: Standard input:49: Warning:old style assignment ambiguity in "=*". Assuming "= *" + +/* + * (C) Copyright 2001 + * + * 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 + */ + +#ifdef ECC_TEST +static inline void ecc_off (void) +{ + *(volatile int *) (INTERNAL_REG_BASE_ADDR + 0x4b4) &= ~0x00200000; +} + +static inline void ecc_on (void) +{ + *(volatile int *) (INTERNAL_REG_BASE_ADDR + 0x4b4) |= 0x00200000; +} + +static int putshex (const char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + printf ("%02x", buf[i]); + } + return 0; +} + +static int char_memcpy (void *d, const void *s, int len) +{ + int i; + char *cd = d; + const char *cs = s; + + for (i = 0; i < len; i++) { + *(cd++) = *(cs++); + } + return 0; +} + +static int memory_test (char *buf) +{ + const char src[][16] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}, + {0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, + {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, + {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}, + {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}, + {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, + {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}, + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + }; + const int foo[] = { 0 }; + int i, j, a; + + printf ("\ntest @ %d %p\n", foo[0], buf); + for (i = 0; i < 12; i++) { + for (a = 0; a < 8; a++) { + const char *s = src[i] + a; + int align = (unsigned) (s) & 0x7; + + /* ecc_off(); */ + memcpy (buf, s, 8); + /* ecc_on(); */ + putshex (s, 8); + if (memcmp (buf, s, 8)) { + putc ('\n'); + putshex (buf, 8); + printf (" [FAIL] (%p) align=%d\n", s, align); + for (j = 0; j < 8; j++) { + s[j] == buf[j] ? puts (" ") : + printf ("%02x", + (s[j]) ^ (buf[j])); + } + putc ('\n'); + } else { + printf (" [PASS] (%p) align=%d\n", s, align); + } + /* ecc_off(); */ + char_memcpy (buf, s, 8); + /* ecc_on(); */ + putshex (s, 8); + if (memcmp (buf, s, 8)) { + putc ('\n'); + putshex (buf, 8); + printf (" [FAIL] (%p) align=%d\n", s, align); + for (j = 0; j < 8; j++) { + s[j] == buf[j] ? puts (" ") : + printf ("%02x", + (s[j]) ^ (buf[j])); + } + putc ('\n'); + } else { + printf (" [PASS] (%p) align=%d\n", s, align); + } + } + } + + return 0; +} +#endif diff --git a/board/Marvell/common/flash.c b/board/Marvell/common/flash.c new file mode 100644 index 0000000..c2c5b76 --- /dev/null +++ b/board/Marvell/common/flash.c @@ -0,0 +1,1072 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, 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 + */ + +/* + * flash.c - flash support for the 512k, 8bit boot flash + and the 8MB 32bit extra flash on the DB64360 + * most of this file was based on the existing U-Boot + * flash drivers. + * + * written or collected and sometimes rewritten by + * Ingo Assmus <ingo.assmus@keymile.com> + * + */ + +#include <common.h> +#include <mpc8xx.h> +#include "../include/mv_gen_reg.h" +#include "../include/memory.h" +#include "intel_flash.h" + +#define FLASH_ROM 0xFFFD /* unknown flash type */ +#define FLASH_RAM 0xFFFE /* unknown flash type */ +#define FLASH_MAN_UNKNOWN 0xFFFF0000 + +/* #define DEBUG */ + +/* Intel flash commands */ +int flash_erase_intel (flash_info_t * info, int s_first, int s_last); +int write_word_intel (bank_addr_t addr, bank_word_t value); + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (int portwidth, vu_long * addr, + flash_info_t * info); +static int write_word (flash_info_t * info, ulong dest, ulong data); +static void flash_get_offsets (ulong base, flash_info_t * info); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned int i; + unsigned long size_b0 = 0, size_b1 = 0; + unsigned long base, flash_size; + + /* Init: no FLASHes known */ + for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* the boot flash */ + base = CFG_FLASH_BASE; + size_b0 = + flash_get_size (CFG_BOOT_FLASH_WIDTH, (vu_long *) base, + &flash_info[0]); + + printf ("[%ldkB@%lx] ", size_b0 / 1024, base); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n", base, size_b0, size_b0 << 20); + } + + base = memoryGetDeviceBaseAddress (CFG_EXTRA_FLASH_DEVICE); +/* base = memoryGetDeviceBaseAddress(DEV_CS3_BASE_ADDR);*/ + for (i = 1; i < CFG_MAX_FLASH_BANKS; i++) { + unsigned long size = + flash_get_size (CFG_EXTRA_FLASH_WIDTH, + (vu_long *) base, &flash_info[i]); + + printf ("[%ldMB@%lx] ", size >> 20, base); + + if (flash_info[i].flash_id == FLASH_UNKNOWN) { + if (i == 1) { + printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n", base, size_b1, size_b1 << 20); + } + break; + } + size_b1 += size; + base += size; + } + + flash_size = size_b0 + size_b1; + return flash_size; +} + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t * info) +{ + int i; + int sector_size; + + if (!info->sector_count) + return; + + /* set up sector start address table */ + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: + case FLASH_28F128J3A: + case FLASH_28F640J3A: + case FLASH_RAM: + /* this chip has uniformly spaced sectors */ + sector_size = info->size / info->sector_count; + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * sector_size); + break; + default: + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00008000; + info->start[2] = base + 0x0000C000; + info->start[3] = base + 0x00010000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = + base + (i * 0x00020000) - 0x00060000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00008000; + info->start[i--] = base + info->size - 0x0000C000; + info->start[i--] = base + info->size - 0x00010000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00020000; + } + } + } +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_STM: + printf ("STM "); + break; + case FLASH_MAN_AMD: + printf ("AMD "); + break; + case FLASH_MAN_FUJ: + printf ("FUJITSU "); + break; + case FLASH_MAN_INTEL: + printf ("INTEL "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: + printf ("AM29LV040B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400B: + printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: + printf ("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: + printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: + printf ("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AM160B: + printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: + printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: + printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: + printf ("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + case FLASH_28F640J3A: + printf ("28F640J3A (64 Mbit)\n"); + break; + case FLASH_28F128J3A: + printf ("28F128J3A (128 Mbit)\n"); + break; + case FLASH_ROM: + printf ("ROM\n"); + break; + case FLASH_RAM: + printf ("RAM\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + if ((info->size >> 20) > 0) { + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + } else { + printf (" Size: %ld kB in %d Sectors\n", + info->size >> 10, info->sector_count); + } + + printf (" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], info->protect[i] ? " (RO)" : " "); + } + printf ("\n"); + return; +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ + +static inline void flash_cmd (int width, volatile unsigned char *addr, + int offset, unsigned char cmd) +{ + /* supports 1x8, 1x16, and 2x16 */ + /* 2x8 and 4x8 are not supported */ + if (width == 4) { + /* assuming chips are in 16 bit mode */ + /* 2x16 */ + unsigned long cmd32 = (cmd << 16) | cmd; + + *(volatile unsigned long *) (addr + offset * 2) = cmd32; + } else { + /* 1x16 or 1x8 */ + *(volatile unsigned char *) (addr + offset) = cmd; + } +} + +static ulong +flash_get_size (int portwidth, vu_long * addr, flash_info_t * info) +{ + short i; + volatile unsigned char *caddr = (unsigned char *) addr; + volatile unsigned short *saddr = (unsigned short *) addr; + volatile unsigned long *laddr = (unsigned long *) addr; + char old[2], save; + ulong id = 0, manu = 0, base = (ulong) addr; + +#ifdef DEBUG + printf ("%s: enter\n", __FUNCTION__); +#endif + info->portwidth = portwidth; + + save = *caddr; + + flash_cmd (portwidth, caddr, 0, 0xf0); + flash_cmd (portwidth, caddr, 0, 0xf0); + + udelay (10); + + old[0] = caddr[0]; + old[1] = caddr[1]; + + + if (old[0] != 0xf0) { + flash_cmd (portwidth, caddr, 0, 0xf0); + flash_cmd (portwidth, caddr, 0, 0xf0); + + udelay (10); + + if (*caddr == 0xf0) { + /* this area is ROM */ + *caddr = save; + info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN; + info->sector_count = 8; + info->size = 0x80000; + flash_get_offsets (base, info); + return info->size; + } + } else { + *caddr = 0; + + udelay (10); + + if (*caddr == 0) { + /* this area is RAM */ + *caddr = save; + info->flash_id = FLASH_RAM + FLASH_MAN_UNKNOWN; + info->sector_count = 8; + info->size = 0x80000; + flash_get_offsets (base, info); + return info->size; + } + flash_cmd (portwidth, caddr, 0, 0xf0); + + udelay (10); + } + + /* Write auto select command: read Manufacturer ID */ + flash_cmd (portwidth, caddr, 0x555, 0xAA); + flash_cmd (portwidth, caddr, 0x2AA, 0x55); + flash_cmd (portwidth, caddr, 0x555, 0x90); + + udelay (10); + + if ((caddr[0] == old[0]) && (caddr[1] == old[1])) { + + /* this area is ROM */ + info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN; + info->sector_count = 8; + info->size = 0x80000; + flash_get_offsets (base, info); + return info->size; +#ifdef DEBUG + } else { + printf ("%px%d: %02x:%02x -> %02x:%02x\n", + caddr, portwidth, old[0], old[1], caddr[0], caddr[1]); +#endif + } + + switch (portwidth) { + case 1: + manu = caddr[0]; + manu |= manu << 16; + id = caddr[1]; + break; + case 2: + manu = saddr[0]; + manu |= manu << 16; + id = saddr[1]; + id |= id << 16; + break; + case 4: + manu = laddr[0]; + id = laddr[1]; + break; + } + +#ifdef DEBUG + flash_cmd (portwidth, caddr, 0, 0xf0); + + printf ("\n%08lx:%08lx:%08lx\n", base, manu, id); + printf ("%08lx %08lx %08lx %08lx\n", + laddr[0], laddr[1], laddr[2], laddr[3]); +#endif + + switch (manu) { + case STM_MANUFACT: + info->flash_id = FLASH_MAN_STM; + break; + case AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + break; + default: + flash_cmd (portwidth, caddr, 0, 0xf0); + + printf ("Unknown Mfr [%08lx]:%08lx\n", manu, id); + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + + switch (id) { + case AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00100000; + info->chipwidth = 1; + break; /* => 1 MB */ + + case AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00100000; + info->chipwidth = 1; + break; /* => 1 MB */ + + case AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00200000; + info->chipwidth = 1; + break; /* => 2 MB */ + + case AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00200000; + info->chipwidth = 1; + break; /* => 2 MB */ + + case AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00400000; + info->chipwidth = 1; + break; /* => 4 MB */ + + case AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00400000; + info->chipwidth = 1; + break; /* => 4 MB */ +#if 0 /* enable when device IDs are available */ + case AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ + + case AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ +#endif + case AMD_ID_LV040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x80000; + info->chipwidth = 1; + break; /* => 512 kB */ + + case INTEL_ID_28F640J3A: + info->flash_id += FLASH_28F640J3A; + info->sector_count = 64; + info->size = 128 * 1024 * 64; /* 128kbytes x 64 blocks */ + info->chipwidth = 2; + if (portwidth == 4) + info->size *= 2; /* 2x16 */ + break; + + case INTEL_ID_28F128J3A: + info->flash_id += FLASH_28F128J3A; + info->sector_count = 128; + info->size = 128 * 1024 * 128; /* 128kbytes x 128 blocks */ + info->chipwidth = 2; + if (portwidth == 4) + info->size *= 2; /* 2x16 */ + break; + + default: + flash_cmd (portwidth, caddr, 0, 0xf0); + + printf ("Unknown id %lx:[%lx]\n", manu, id); + info->flash_id = FLASH_UNKNOWN; + info->chipwidth = 1; + return (0); /* => no or unknown flash */ + + } + + flash_get_offsets (base, info); + + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address, (A7 .. A0)=0x02 */ + /* D0 = 1 if protected */ + caddr = (volatile unsigned char *) (info->start[i]); + saddr = (volatile unsigned short *) (info->start[i]); + laddr = (volatile unsigned long *) (info->start[i]); + if (portwidth == 1) + info->protect[i] = caddr[2] & 1; + else if (portwidth == 2) + info->protect[i] = saddr[2] & 1; + else + info->protect[i] = laddr[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + caddr = (volatile unsigned char *) info->start[0]; + + flash_cmd (portwidth, caddr, 0, 0xF0); /* reset bank */ + } + + return (info->size); +} + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ + volatile unsigned char *addr = (char *) (info->start[0]); + int flag, prot, sect, l_sect; + ulong start, now, last; + +/* modified to support 2x16 Intel flash */ +/* Note that the code will not exit on a flash erasure error or timeout */ +/* but will print and error message and continue processing sectors */ +/* until they are all erased. */ +/* 10-16-2002 P. Marchese */ + ulong mask; + int timeout; + + if (info->portwidth == 4) +/* { + printf ("- Warning: erasing of 32Bit (2*16Bit i.e. 2*28F640J3A) not supported yet !!!! \n"); + return 1; + }*/ + { + /* make sure it's Intel flash */ + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + /* yup! it's an Intel flash */ + /* is it 16-bits wide? */ + if (info->chipwidth == 2) { + /* yup! it's 16-bits wide */ + /* are there any sectors to process? */ + if ((s_first < 0) || (s_first > s_last)) { + printf ("Error: There are no sectors to erase\n"); + printf ("Either sector %d is less than zero\n", s_first); + printf ("or sector %d is greater than sector %d\n", s_first, s_last); + return 1; + } + /* check for protected sectors */ + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) + if (info->protect[sect]) + prot++; + /* if variable "prot" is nonzero, there are protected sectors */ + if (prot) + printf ("- Warning: %d protected sectors will not be erased!\n", prot); + /* reset the flash */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + /* Clear the status register */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_CLR_STAT); + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + /* is the sector unprotected? */ + if (info->protect[sect] == 0) { /* not protected */ + /* issue the single block erase command, 0x20 */ + flash_cmd (info->portwidth, + (volatile unsigned + char *) info-> + start[sect], 0, + CHIP_CMD_ERASE1); + /* issue the erase confirm command, 0xD0 */ + flash_cmd (info->portwidth, + (volatile unsigned + char *) info-> + start[sect], 0, + CHIP_CMD_ERASE2); + l_sect = sect; + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + /* poll for erasure completion */ + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info->portwidth, + addr, 0, + CHIP_CMD_RD_STAT); + /* setup the status register mask */ + mask = CHIP_STAT_RDY | + (CHIP_STAT_RDY << 16); + /* init. the timeout counter */ + start = get_timer (0); + /* keep looping while the flash is not ready */ + /* exit the loop by timing out or the flash */ + /* becomes ready again */ + timeout = 0; + while ((* + (volatile unsigned + long *) info-> + start[sect] & mask) != + mask) { + /* has the timeout limit been reached? */ + if (get_timer (start) + > + CFG_FLASH_ERASE_TOUT) + { + /* timeout limit reached */ + printf ("Time out limit reached erasing sector at address %08lx\n", info->start[sect]); + printf ("Continuing with next sector\n"); + timeout = 1; + goto timed_out_error; + } + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info-> + portwidth, + addr, 0, + CHIP_CMD_RD_STAT); + } + /* did we timeout? */ + timed_out_error:if (timeout == 0) + { + /* didn't timeout, so check the status register */ + /* create the status mask to check for errors */ + mask = CHIP_STAT_ECLBS; + mask = mask | (mask << + 16); + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info-> + portwidth, + addr, 0, + CHIP_CMD_RD_STAT); + /* are there any errors? */ + if ((* + (volatile + unsigned long *) + info-> + start[sect] & + mask) != 0) { + /* We got an erasure error */ + printf ("Flash erasure error at address 0x%08lx\n", info->start[sect]); + printf ("Continuing with next sector\n"); + /* reset the flash */ + flash_cmd + (info-> + portwidth, + addr, + 0, + CHIP_CMD_RST); + } + } + /* erasure completed without errors */ + /* reset the flash */ + flash_cmd (info->portwidth, + addr, 0, + CHIP_CMD_RST); + } /* end if not protected */ + } /* end for loop */ + printf ("Flash erasure done\n"); + return 0; + } else { + /* The Intel flash is not 16-bit wide */ + /* print and error message and return */ + /* NOTE: you can add routines here to handle other size flash */ + printf ("Error: Intel flash device is only %d-bits wide\n", info->chipwidth * 8); + printf ("The erasure code only handles Intel 16-bit wide flash memory\n"); + return 1; + } + } else { + /* Not Intel flash so return an error as a write timeout */ + /* NOTE: if it's another type flash, stick its routine here */ + printf ("Error: The flash device is not Intel type\n"); + printf ("The erasure code only supports Intel flash in a 32-bit port width\n"); + return 1; + } + } + + /* end 32-bit wide flash code */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) + return 1; /* Rom can not be erased */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) { /* RAM just copy 0s to RAM */ + for (sect = s_first; sect <= s_last; sect++) { + int sector_size = info->size / info->sector_count; + + addr = (char *) (info->start[sect]); + memset ((void *) addr, 0, sector_size); + } + return 0; + } + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { /* Intel works spezial */ + return flash_erase_intel (info, + (unsigned short) s_first, + (unsigned short) s_last); + } +#if 0 + if ((info->flash_id == FLASH_UNKNOWN) || /* Flash is unknown to PPCBoot */ + (info->flash_id > FLASH_AMD_COMP)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } +#endif + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", prot); + } else { + printf ("\n"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + flash_cmd (info->portwidth, addr, 0x555, 0xAA); /* start erase routine */ + flash_cmd (info->portwidth, addr, 0x2AA, 0x55); + flash_cmd (info->portwidth, addr, 0x555, 0x80); + flash_cmd (info->portwidth, addr, 0x555, 0xAA); + flash_cmd (info->portwidth, addr, 0x2AA, 0x55); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = (char *) (info->start[sect]); + flash_cmd (info->portwidth, addr, 0, 0x30); + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; + addr = (volatile unsigned char *) (info->start[l_sect]); + /* broken for 2x16: TODO */ + while ((addr[0] & 0x80) != 0x80) { + if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return 1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + } + + DONE: + /* reset to read mode */ + addr = (volatile unsigned char *) info->start[0]; + flash_cmd (info->portwidth, addr, 0, 0xf0); + flash_cmd (info->portwidth, addr, 0, 0xf0); + + printf (" done\n"); + return 0; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +/* broken for 2x16: TODO */ +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, rc; + +/* Commented out since the below code should work for 32-bit(2x 16 flash) */ +/* 10-16-2002 P. Marchese */ +/* if(info->portwidth==4) return 1; */ +/* if(info->portwidth==4) { + printf ("- Warning: writting of 32Bit (2*16Bit i.e. 2*28F640J3A) not supported yet !!!! \n"); + return 1; + }*/ + + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) + return 0; + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) { + memcpy ((void *) addr, src, cnt); + return 0; + } + + wp = (addr & ~3); /* get lower word aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i = 0, cp = wp; i < l; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + for (; i < 4 && cnt > 0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt == 0 && i < 4; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + if ((rc = write_word (info, wp, data)) != 0) { + return (rc); + } + wp += 4; + } + + /* + * handle word aligned part + */ + while (cnt >= 4) { + data = 0; + for (i = 0; i < 4; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_word (info, wp, data)) != 0) { + return (rc); + } + wp += 4; + cnt -= 4; + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i < 4; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + return (write_word (info, wp, data)); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +/* broken for 2x16: TODO */ +static int write_word (flash_info_t * info, ulong dest, ulong data) +{ + volatile unsigned char *addr = (char *) (info->start[0]); + ulong start; + int flag, i; + ulong mask; + +/* modified so that it handles 32-bit(2x16 Intel flash programming */ +/* 10-16-2002 P. Marchese */ + + if (info->portwidth == 4) +/* { + printf ("- Warning: writting of 32Bit (2*16Bit i.e. 2*28F640J3A) not supported yet !!!! \n"); + return 1; + }*/ + { + /* make sure it's Intel flash */ + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + /* yup! it's an Intel flash */ + /* is it 16-bits wide? */ + if (info->chipwidth == 2) { + /* yup! it's 16-bits wide */ + /* so we know how to program it */ + /* reset the flash */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + /* Clear the status register */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_CLR_STAT); + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + /* 1st cycle of word/byte program */ + /* write 0x40 to the location to program */ + flash_cmd (info->portwidth, (char *) dest, 0, + CHIP_CMD_PROG); + /* 2nd cycle of word/byte program */ + /* write the data to the destination address */ + *(ulong *) dest = data; + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + /* setup the status register mask */ + mask = CHIP_STAT_RDY | (CHIP_STAT_RDY << 16); + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RD_STAT); + /* init. the timeout counter */ + start = get_timer (0); + /* keep looping while the flash is not ready */ + /* exit the loop by timing out or the flash */ + /* becomes ready again */ +/* 11-13-2002 Paul Marchese */ +/* modified while loop conditional statement */ +/* because we were always timing out. */ +/* there is a type mismatch, "addr[0]" */ +/* returns a byte but "mask" is a 32-bit value */ + while ((*(volatile unsigned long *) info-> + start[0] & mask) != mask) +/* original code */ +/* while (addr[0] & mask) != mask) */ + { + /* has the timeout limit been reached? */ + if (get_timer (start) > + CFG_FLASH_WRITE_TOUT) { + /* timeout limit reached */ + printf ("Time out limit reached programming address %08lx with data %08lx\n", dest, data); + /* reset the flash */ + flash_cmd (info->portwidth, + addr, 0, + CHIP_CMD_RST); + return (1); + } + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RD_STAT); + } + /* flash is ready, so check the status */ + /* create the status mask to check for errors */ + mask = CHIP_STAT_DPS | CHIP_STAT_VPPS | + CHIP_STAT_PSLBS; + mask = mask | (mask << 16); + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RD_STAT); + /* are there any errors? */ + if ((addr[0] & mask) != 0) { + /* We got a one of the following errors: */ + /* Voltage range, Device protect, or programming */ + /* return the error as a device timeout */ + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RD_STAT); + printf ("Flash programming error at address 0x%08lx\n", dest); + printf ("Flash status register contains 0x%08lx\n", (unsigned long) addr[0]); + /* reset the flash */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + return 1; + } + /* write completed without errors */ + /* reset the flash */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + return 0; + } else { + /* it's not 16-bits wide, so return an error as a write timeout */ + /* NOTE: you can add routines here to handle other size flash */ + printf ("Error: Intel flash device is only %d-bits wide\n", info->chipwidth * 8); + printf ("The write code only handles Intel 16-bit wide flash memory\n"); + return 1; + } + } else { + /* not Intel flash so return an error as a write timeout */ + /* NOTE: if it's another type flash, stick its routine here */ + printf ("Error: The flash device is not Intel type\n"); + printf ("The code only supports Intel flash in a 32-bit port width\n"); + return 1; + } + } + + /* end of 32-bit flash code */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) + return 1; + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) { + *(unsigned long *) dest = data; + return 0; + } + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + unsigned short low = data & 0xffff; + unsigned short hi = (data >> 16) & 0xffff; + int ret = write_word_intel ((bank_addr_t) dest, hi); + + if (!ret) + ret = write_word_intel ((bank_addr_t) (dest + 2), + low); + + return ret; + } + + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_long *) dest) & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + /* first, perform an unlock bypass command to speed up flash writes */ + addr[0x555] = 0xAA; + addr[0x2AA] = 0x55; + addr[0x555] = 0x20; + + /* write each byte out */ + for (i = 0; i < 4; i++) { + char *data_ch = (char *) &data; + + addr[0] = 0xA0; + *(((char *) dest) + i) = data_ch[i]; + udelay (10); /* XXX */ + } + + /* we're done, now do an unlock bypass reset */ + addr[0] = 0x90; + addr[0] = 0x00; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + + /* data polling for D7 */ + start = get_timer (0); + while ((*((vu_long *) dest) & 0x00800080) != (data & 0x00800080)) { + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + return (0); +} diff --git a/board/Marvell/common/i2c.c b/board/Marvell/common/i2c.c new file mode 100644 index 0000000..624ee5c --- /dev/null +++ b/board/Marvell/common/i2c.c @@ -0,0 +1,532 @@ +/* + * (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 + * + * Hacked for the DB64360 board by Ingo.Assmus@keymile.com + * extra improvments by Brain Waite + */ +#include <common.h> +#include <mpc8xx.h> +#include <malloc.h> +#include "../include/mv_gen_reg.h" +#include "../include/core.h" + +#define MAX_I2C_RETRYS 10 +#define I2C_DELAY 1000 /* Should be at least the # of MHz of Tclk */ +#undef DEBUG_I2C +/*#define DEBUG_I2C*/ + +#ifdef DEBUG_I2C +#define DP(x) x +#else +#define DP(x) +#endif + +/* Assuming that there is only one master on the bus (us) */ + +static void i2c_init (int speed, int slaveaddr) +{ + unsigned int n, m, freq, margin, power; + unsigned int actualN = 0, actualM = 0; + unsigned int control, status; + unsigned int minMargin = 0xffffffff; + unsigned int tclk = CFG_TCLK; + unsigned int i2cFreq = speed; /* 100000 max. Fast mode not supported */ + + DP (puts ("i2c_init\n")); +/* gtI2cMasterInit */ + for (n = 0; n < 8; n++) { + for (m = 0; m < 16; m++) { + power = 2 << n; /* power = 2^(n+1) */ + freq = tclk / (10 * (m + 1) * power); + if (i2cFreq > freq) + margin = i2cFreq - freq; + else + margin = freq - i2cFreq; + if (margin < minMargin) { + minMargin = margin; + actualN = n; + actualM = m; + } + } + } + + DP (puts ("setup i2c bus\n")); + + /* Setup bus */ +/* gtI2cReset */ + GT_REG_WRITE (I2C_SOFT_RESET, 0); + + DP (puts ("udelay...\n")); + + udelay (I2C_DELAY); + + DP (puts ("set baudrate\n")); + + GT_REG_WRITE (I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN); + GT_REG_WRITE (I2C_CONTROL, (0x1 << 2) | (0x1 << 6)); + + udelay (I2C_DELAY * 10); + + DP (puts ("read control, baudrate\n")); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + GT_REG_READ (I2C_CONTROL, &control); +} + +static uchar i2c_start (void) +{ /* DB64360 checked -> ok */ + unsigned int control, status; + int count = 0; + + DP (puts ("i2c_start\n")); + + /* Set the start bit */ + +/* gtI2cGenerateStartBit() */ + + GT_REG_READ (I2C_CONTROL, &control); + control |= (0x1 << 5); /* generate the I2C_START_BIT */ + GT_REG_WRITE (I2C_CONTROL, control); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + + count = 0; + while ((status & 0xff) != 0x08) { + udelay (I2C_DELAY); + if (count > 20) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return (status); + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + + return (0); +} + +static uchar i2c_select_device (uchar dev_addr, uchar read, int ten_bit) +{ + unsigned int status, data, bits = 7; + int count = 0; + + DP (puts ("i2c_select_device\n")); + + /* Output slave address */ + + if (ten_bit) { + bits = 10; + } + + data = (dev_addr << 1); + /* set the read bit */ + data |= read; + GT_REG_WRITE (I2C_DATA, data); + /* assert the address */ + RESET_REG_BITS (I2C_CONTROL, BIT3); + + udelay (I2C_DELAY); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count = 0; + while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) { + udelay (I2C_DELAY); + if (count > 20) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return (status); + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + + if (bits == 10) { + printf ("10 bit I2C addressing not yet implemented\n"); + return (0xff); + } + + return (0); +} + +static uchar i2c_get_data (uchar * return_data, int len) +{ + + unsigned int data, status; + int count = 0; + + DP (puts ("i2c_get_data\n")); + + while (len) { + + /* Get and return the data */ + + RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); + + udelay (I2C_DELAY * 5); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + while ((status & 0xff) != 0x50) { + udelay (I2C_DELAY); + if (count > 2) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return 0; + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + GT_REG_READ (I2C_DATA, &data); + len--; + *return_data = (uchar) data; + return_data++; + } + RESET_REG_BITS (I2C_CONTROL, BIT2 | BIT3); + while ((status & 0xff) != 0x58) { + udelay (I2C_DELAY); + if (count > 200) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return (status); + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /* stop */ + + return (0); +} + +static uchar i2c_write_data (unsigned int *data, int len) +{ + unsigned int status; + int count = 0; + unsigned int temp; + unsigned int *temp_ptr = data; + + DP (puts ("i2c_write_data\n")); + + while (len) { + temp = (unsigned int) (*temp_ptr); + GT_REG_WRITE (I2C_DATA, temp); + RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); + + udelay (I2C_DELAY); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + while ((status & 0xff) != 0x28) { + udelay (I2C_DELAY); + if (count > 20) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return (status); + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + len--; + temp_ptr++; + } +/* 11-14-2002 Paul Marchese */ +/* Can't have the write issuing a stop command */ +/* it's wrong to have a stop bit in read stream or write stream */ +/* since we don't know if it's really the end of the command */ +/* or whether we have just send the device address + offset */ +/* we will push issuing the stop command off to the original */ +/* calling function */ + /* set the interrupt bit in the control register */ + GT_REG_WRITE (I2C_CONTROL, (0x1 << 3)); + udelay (I2C_DELAY * 10); + return (0); +} + +/* 11-14-2002 Paul Marchese */ +/* created this function to get the i2c_write() */ +/* function working properly. */ +/* function to write bytes out on the i2c bus */ +/* this is identical to the function i2c_write_data() */ +/* except that it requires a buffer that is an */ +/* unsigned character array. You can't use */ +/* i2c_write_data() to send an array of unsigned characters */ +/* since the byte of interest ends up on the wrong end of the bus */ +/* aah, the joys of big endian versus little endian! */ +/* */ +/* returns 0 = success */ +/* anything other than zero is failure */ +static uchar i2c_write_byte (unsigned char *data, int len) +{ + unsigned int status; + int count = 0; + unsigned int temp; + unsigned char *temp_ptr = data; + + DP (puts ("i2c_write_byte\n")); + + while (len) { + /* Set and assert the data */ + temp = *temp_ptr; + GT_REG_WRITE (I2C_DATA, temp); + RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); + + udelay (I2C_DELAY); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + while ((status & 0xff) != 0x28) { + udelay (I2C_DELAY); + if (count > 20) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return (status); + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + len--; + temp_ptr++; + } +/* Can't have the write issuing a stop command */ +/* it's wrong to have a stop bit in read stream or write stream */ +/* since we don't know if it's really the end of the command */ +/* or whether we have just send the device address + offset */ +/* we will push issuing the stop command off to the original */ +/* calling function */ +/* GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4)); + GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); */ + /* set the interrupt bit in the control register */ + GT_REG_WRITE (I2C_CONTROL, (0x1 << 3)); + udelay (I2C_DELAY * 10); + + return (0); +} + +static uchar +i2c_set_dev_offset (uchar dev_addr, unsigned int offset, int ten_bit, + int alen) +{ + uchar status; + unsigned int table[2]; + +/* initialize the table of address offset bytes */ +/* utilized for 2 byte address offsets */ +/* NOTE: the order is high byte first! */ + table[1] = offset & 0xff; /* low byte */ + table[0] = offset / 0x100; /* high byte */ + + DP (puts ("i2c_set_dev_offset\n")); + + status = i2c_select_device (dev_addr, 0, ten_bit); + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to select device setting offset: 0x%02x\n", + status); +#endif + return status; + } +/* check the address offset length */ + if (alen == 0) + /* no address offset */ + return (0); + else if (alen == 1) { + /* 1 byte address offset */ + status = i2c_write_data (&offset, 1); + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to write data: 0x%02x\n", status); +#endif + return status; + } + } else if (alen == 2) { + /* 2 bytes address offset */ + status = i2c_write_data (table, 2); + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to write data: 0x%02x\n", status); +#endif + return status; + } + } else { + /* address offset unknown or not supported */ + printf ("Address length offset %d is not supported\n", alen); + return 1; + } + return 0; /* sucessful completion */ +} + +uchar +i2c_read (uchar dev_addr, unsigned int offset, int alen, uchar * data, + int len) +{ + uchar status = 0; + unsigned int i2cFreq = CFG_I2C_SPEED; + + DP (puts ("i2c_read\n")); + + i2c_init (i2cFreq, 0); /* set the i2c frequency */ + + status = i2c_start (); + + if (status) { +#ifdef DEBUG_I2C + printf ("Transaction start failed: 0x%02x\n", status); +#endif + return status; + } + + status = i2c_set_dev_offset (dev_addr, offset, 0, alen); /* send the slave address + offset */ + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to set slave address & offset: 0x%02x\n", + status); +#endif + return status; + } + + i2c_init (i2cFreq, 0); /* set the i2c frequency again */ + + status = i2c_start (); + if (status) { +#ifdef DEBUG_I2C + printf ("Transaction restart failed: 0x%02x\n", status); +#endif + return status; + } + + status = i2c_select_device (dev_addr, 1, 0); /* send the slave address */ + if (status) { +#ifdef DEBUG_I2C + printf ("Address not acknowledged: 0x%02x\n", status); +#endif + return status; + } + + status = i2c_get_data (data, len); + if (status) { +#ifdef DEBUG_I2C + printf ("Data not recieved: 0x%02x\n", status); +#endif + return status; + } + + return 0; +} + +/* 11-14-2002 Paul Marchese */ +/* Function to set the I2C stop bit */ +void i2c_stop (void) +{ + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); +} + +/* 11-14-2002 Paul Marchese */ +/* I2C write function */ +/* dev_addr = device address */ +/* offset = address offset */ +/* alen = length in bytes of the address offset */ +/* data = pointer to buffer to read data into */ +/* len = # of bytes to read */ +/* */ +/* returns 0 = succesful */ +/* anything but zero is failure */ +uchar +i2c_write (uchar dev_addr, unsigned int offset, int alen, uchar * data, + int len) +{ + uchar status = 0; + unsigned int i2cFreq = CFG_I2C_SPEED; + + DP (puts ("i2c_write\n")); + + i2c_init (i2cFreq, 0); /* set the i2c frequency */ + + status = i2c_start (); /* send a start bit */ + + if (status) { +#ifdef DEBUG_I2C + printf ("Transaction start failed: 0x%02x\n", status); +#endif + return status; + } + + status = i2c_set_dev_offset (dev_addr, offset, 0, alen); /* send the slave address + offset */ + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to set slave address & offset: 0x%02x\n", + status); +#endif + return status; + } + + + status = i2c_write_byte (data, len); /* write the data */ + if (status) { +#ifdef DEBUG_I2C + printf ("Data not written: 0x%02x\n", status); +#endif + return status; + } + /* issue a stop bit */ + i2c_stop (); + return 0; +} + +/* 11-14-2002 Paul Marchese */ +/* function to determine if an I2C device is present */ +/* chip = device address of chip to check for */ +/* */ +/* returns 0 = sucessful, the device exists */ +/* anything other than zero is failure, no device */ +int i2c_probe (uchar chip) +{ + + /* We are just looking for an <ACK> back. */ + /* To see if the device/chip is there */ + +#ifdef DEBUG_I2C + unsigned int i2c_status; +#endif + uchar status = 0; + unsigned int i2cFreq = CFG_I2C_SPEED; + + DP (puts ("i2c_probe\n")); + + i2c_init (i2cFreq, 0); /* set the i2c frequency */ + + status = i2c_start (); /* send a start bit */ + + if (status) { +#ifdef DEBUG_I2C + printf ("Transaction start failed: 0x%02x\n", status); +#endif + return (int) status; + } + + status = i2c_set_dev_offset (chip, 0, 0, 0); /* send the slave address + no offset */ + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to set slave address: 0x%02x\n", status); +#endif + return (int) status; + } +#ifdef DEBUG_I2C + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &i2c_status); + printf ("address %#x returned %#x\n", chip, i2c_status); +#endif + /* issue a stop bit */ + i2c_stop (); + return 0; /* successful completion */ +} diff --git a/board/Marvell/common/i2c.h b/board/Marvell/common/i2c.h new file mode 100644 index 0000000..b669ff0 --- /dev/null +++ b/board/Marvell/common/i2c.h @@ -0,0 +1,32 @@ +/* + * (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 + * + * Hacked for the DB64360 board by Ingo.Assmus@keymile.com + */ + +#ifndef __I2C_H__ +#define __I2C_H__ + +/* function declarations */ +uchar i2c_read(uchar, unsigned int, int, uchar*, int); + +#endif diff --git a/board/Marvell/common/intel_flash.c b/board/Marvell/common/intel_flash.c new file mode 100644 index 0000000..d26f883 --- /dev/null +++ b/board/Marvell/common/intel_flash.c @@ -0,0 +1,269 @@ +/* + * (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 + * + * Hacked for the marvell db64360 eval board by + * Ingo Assmus <ingo.assmus@keymile.com> + */ + +#include <common.h> +#include <mpc8xx.h> +#include "../include/mv_gen_reg.h" +#include "../include/memory.h" +#include "intel_flash.h" + + +/*----------------------------------------------------------------------- + * Protection Flags: + */ +#define FLAG_PROTECT_SET 0x01 +#define FLAG_PROTECT_CLEAR 0x02 + +static void bank_reset (flash_info_t * info, int sect) +{ + bank_addr_t addrw, eaddrw; + + addrw = (bank_addr_t) info->start[sect]; + eaddrw = BANK_ADDR_NEXT_WORD (addrw); + + while (addrw < eaddrw) { +#ifdef FLASH_DEBUG + printf (" writing reset cmd to addr 0x%08lx\n", + (unsigned long) addrw); +#endif + *addrw = BANK_CMD_RST; + addrw++; + } +} + +static void bank_erase_init (flash_info_t * info, int sect) +{ + bank_addr_t addrw, saddrw, eaddrw; + int flag; + +#ifdef FLASH_DEBUG + printf ("0x%08x BANK_CMD_PROG\n", BANK_CMD_PROG); + printf ("0x%08x BANK_CMD_ERASE1\n", BANK_CMD_ERASE1); + printf ("0x%08x BANK_CMD_ERASE2\n", BANK_CMD_ERASE2); + printf ("0x%08x BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT); + printf ("0x%08x BANK_CMD_RST\n", BANK_CMD_RST); + printf ("0x%08x BANK_STAT_RDY\n", BANK_STAT_RDY); + printf ("0x%08x BANK_STAT_ERR\n", BANK_STAT_ERR); +#endif + + saddrw = (bank_addr_t) info->start[sect]; + eaddrw = BANK_ADDR_NEXT_WORD (saddrw); + +#ifdef FLASH_DEBUG + printf ("erasing sector %d, start addr = 0x%08lx " + "(bank next word addr = 0x%08lx)\n", sect, + (unsigned long) saddrw, (unsigned long) eaddrw); +#endif + + /* Disable intrs which might cause a timeout here */ + flag = disable_interrupts (); + + for (addrw = saddrw; addrw < eaddrw; addrw++) { +#ifdef FLASH_DEBUG + printf (" writing erase cmd to addr 0x%08lx\n", + (unsigned long) addrw); +#endif + *addrw = BANK_CMD_ERASE1; + *addrw = BANK_CMD_ERASE2; + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); +} + +static int bank_erase_poll (flash_info_t * info, int sect) +{ + bank_addr_t addrw, saddrw, eaddrw; + int sectdone, haderr; + + saddrw = (bank_addr_t) info->start[sect]; + eaddrw = BANK_ADDR_NEXT_WORD (saddrw); + + sectdone = 1; + haderr = 0; + + for (addrw = saddrw; addrw < eaddrw; addrw++) { + bank_word_t stat = *addrw; + +#ifdef FLASH_DEBUG + printf (" checking status at addr " + "0x%08x [0x%08x]\n", (unsigned long) addrw, stat); +#endif + if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY) + sectdone = 0; + else if ((stat & BANK_STAT_ERR) != 0) { + printf (" failed on sector %d " + "(stat = 0x%08x) at " + "address 0x%p\n", sect, stat, addrw); + *addrw = BANK_CMD_CLR_STAT; + haderr = 1; + } + } + + if (haderr) + return (-1); + else + return (sectdone); +} + +int write_word_intel (bank_addr_t addr, bank_word_t value) +{ + bank_word_t stat; + ulong start; + int flag, retval; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + *addr = BANK_CMD_PROG; + + *addr = value; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + + retval = 0; + + /* data polling for D7 */ + start = get_timer (0); + do { + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { + retval = 1; + goto done; + } + stat = *addr; + } while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY); + + if ((stat & BANK_STAT_ERR) != 0) { + printf ("flash program failed (stat = 0x%08lx) " + "at address 0x%08lx\n", (ulong) stat, (ulong) addr); + *addr = BANK_CMD_CLR_STAT; + retval = 3; + } + + done: + /* reset to read mode */ + *addr = BANK_CMD_RST; + + return (retval); +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase_intel (flash_info_t * info, int s_first, int s_last) +{ + int prot, sect, haderr; + ulong start, now, last; + +#ifdef FLASH_DEBUG + printf ("\nflash_erase: erase %d sectors (%d to %d incl.) from\n" + " Bank # %d: ", s_last - s_first + 1, s_first, s_last, + (info - flash_info) + 1); + flash_print_info (info); +#endif + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sector%s will not be erased!\n", prot, (prot > 1 ? "s" : "")); + } + + start = get_timer (0); + last = 0; + haderr = 0; + + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + ulong estart; + int sectdone; + + bank_erase_init (info, sect); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + estart = get_timer (start); + + do { + now = get_timer (start); + + if (now - estart > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout (sect %d)\n", sect); + haderr = 1; + break; + } +#ifndef FLASH_DEBUG + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } +#endif + + sectdone = bank_erase_poll (info, sect); + + if (sectdone < 0) { + haderr = 1; + break; + } + + } while (!sectdone); + + if (haderr) + break; + } + } + + if (haderr > 0) + printf (" failed\n"); + else + printf (" done\n"); + + /* reset to read mode */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + bank_reset (info, sect); + } + } + return haderr; +} diff --git a/board/Marvell/common/intel_flash.h b/board/Marvell/common/intel_flash.h new file mode 100644 index 0000000..666a4cd --- /dev/null +++ b/board/Marvell/common/intel_flash.h @@ -0,0 +1,186 @@ +/* + * (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 + * + * Hacked for the marvell db64360 eval board by + * Ingo Assmus <ingo.assmus@keymile.com> + */ + +/*************** DEFINES for Intel StrataFlash FLASH chip ********************/ + +/* + * acceptable chips types are: + * + * 28F320J5, 28F640J5, 28F320J3A, 28F640J3A and 28F128J3A + */ + +/* register addresses, valid only following an CHIP_CMD_RD_ID command */ +#define CHIP_ADDR_REG_MAN 0x000000 /* manufacturer's id */ +#define CHIP_ADDR_REG_DEV 0x000001 /* device id */ +#define CHIP_ADDR_REG_CFGM 0x000003 /* master lock config */ +#define CHIP_ADDR_REG_CFG(b) (((b)<<16)|2) /* lock config for block b */ + +/* Commands */ +#define CHIP_CMD_RST 0xFF /* reset flash */ +#define CHIP_CMD_RD_ID 0x90 /* read the id and lock bits */ +#define CHIP_CMD_RD_QUERY 0x98 /* read device capabilities */ +#define CHIP_CMD_RD_STAT 0x70 /* read the status register */ +#define CHIP_CMD_CLR_STAT 0x50 /* clear the staus register */ +#define CHIP_CMD_WR_BUF 0xE8 /* clear the staus register */ +#define CHIP_CMD_PROG 0x40 /* program word command */ +#define CHIP_CMD_ERASE1 0x20 /* 1st word for block erase */ +#define CHIP_CMD_ERASE2 0xD0 /* 2nd word for block erase */ +#define CHIP_CMD_ERASE_SUSP 0xB0 /* suspend block erase */ +#define CHIP_CMD_LOCK 0x60 /* 1st word for all lock cmds */ +#define CHIP_CMD_SET_LOCK_BLK 0x01 /* 2nd wrd set block lock bit */ +#define CHIP_CMD_SET_LOCK_MSTR 0xF1 /* 2nd wrd set master lck bit */ +#define CHIP_CMD_CLR_LOCK_BLK 0xD0 /* 2nd wrd clear blk lck bit */ + +/* status register bits */ +#define CHIP_STAT_DPS 0x02 /* Device Protect Status */ +#define CHIP_STAT_VPPS 0x08 /* VPP Status */ +#define CHIP_STAT_PSLBS 0x10 /* Program+Set Lock Bit Stat */ +#define CHIP_STAT_ECLBS 0x20 /* Erase+Clr Lock Bit Stat */ +#define CHIP_STAT_ESS 0x40 /* Erase Suspend Status */ +#define CHIP_STAT_RDY 0x80 /* WSM Mach Status, 1=rdy */ + +#define CHIP_STAT_ERR (CHIP_STAT_VPPS | CHIP_STAT_DPS | \ + CHIP_STAT_ECLBS | CHIP_STAT_PSLBS) + +/* ID and Lock Configuration */ +#define CHIP_RD_ID_LOCK 0x01 /* Bit 0 of each byte */ +#define CHIP_RD_ID_MAN 0x89 /* Manufacturer code = 0x89 */ +#define CHIP_RD_ID_DEV CFG_FLASH_ID + +/* dimensions */ +#define CHIP_WIDTH 2 /* chips are in 16 bit mode */ +#define CHIP_WSHIFT 1 /* (log2 of CHIP_WIDTH) */ +#define CHIP_NBLOCKS 128 +#define CHIP_BLKSZ (128 * 1024) /* of 128Kbytes each */ +#define CHIP_SIZE (CHIP_BLKSZ * CHIP_NBLOCKS) + +/********************** DEFINES for Hymod Flash ******************************/ + +/* + * The hymod board has 2 x 28F320J5 chips running in + * 16 bit mode, for a 32 bit wide bank. + */ + +typedef unsigned short bank_word_t; /* 8/16/32/64bit unsigned int */ +typedef volatile bank_word_t *bank_addr_t; +typedef unsigned long bank_size_t; /* want this big - >= 32 bit */ + +#define BANK_CHIP_WIDTH 1 /* each bank is 1 chip wide */ +#define BANK_CHIP_WSHIFT 0 /* (log2 of BANK_CHIP_WIDTH) */ + +#define BANK_WIDTH (CHIP_WIDTH * BANK_CHIP_WIDTH) +#define BANK_WSHIFT (CHIP_WSHIFT + BANK_CHIP_WSHIFT) +#define BANK_NBLOCKS CHIP_NBLOCKS +#define BANK_BLKSZ (CHIP_BLKSZ * BANK_CHIP_WIDTH) +#define BANK_SIZE (CHIP_SIZE * BANK_CHIP_WIDTH) + +#define MAX_BANKS 1 /* only one bank possible */ + +/* align bank addresses and sizes to bank word boundaries */ +#define BANK_ADDR_WORD_ALIGN(a) ((bank_addr_t)((bank_size_t)(a) \ + & ~(BANK_WIDTH - 1))) +#define BANK_SIZE_WORD_ALIGN(s) ((bank_size_t)BANK_ADDR_WORD_ALIGN( \ + (bank_size_t)(s) + (BANK_WIDTH - 1))) + +/* align bank addresses and sizes to bank block boundaries */ +#define BANK_ADDR_BLK_ALIGN(a) ((bank_addr_t)((bank_size_t)(a) \ + & ~(BANK_BLKSZ - 1))) +#define BANK_SIZE_BLK_ALIGN(s) ((bank_size_t)BANK_ADDR_BLK_ALIGN( \ + (bank_size_t)(s) + (BANK_BLKSZ - 1))) + +/* align bank addresses and sizes to bank boundaries */ +#define BANK_ADDR_BANK_ALIGN(a) ((bank_addr_t)((bank_size_t)(a) \ + & ~(BANK_SIZE - 1))) +#define BANK_SIZE_BANK_ALIGN(s) ((bank_size_t)BANK_ADDR_BANK_ALIGN( \ + (bank_size_t)(s) + (BANK_SIZE - 1))) + +/* add an offset to a bank address */ +#define BANK_ADDR_OFFSET(a, o) (bank_addr_t)((bank_size_t)(a) + \ + (bank_size_t)(o)) + +/* get base address of bank b, given flash base address a */ +#define BANK_ADDR_BASE(a, b) BANK_ADDR_OFFSET(BANK_ADDR_BANK_ALIGN(a), \ + (bank_size_t)(b) * BANK_SIZE) + +/* adjust a bank address to start of next word, block or bank */ +#define BANK_ADDR_NEXT_WORD(a) BANK_ADDR_OFFSET(BANK_ADDR_WORD_ALIGN(a), \ + BANK_WIDTH) +#define BANK_ADDR_NEXT_BLK(a) BANK_ADDR_OFFSET(BANK_ADDR_BLK_ALIGN(a), \ + BANK_BLKSZ) +#define BANK_ADDR_NEXT_BANK(a) BANK_ADDR_OFFSET(BANK_ADDR_BANK_ALIGN(a), \ + BANK_SIZE) + +/* get bank address of chip register r given a bank base address a */ +#define BANK_ADDR_REG(a, r) BANK_ADDR_OFFSET(BANK_ADDR_BANK_ALIGN(a), \ + ((bank_size_t)(r) << BANK_WSHIFT)) + +/* make a bank address for each chip register address */ + +#define BANK_ADDR_REG_MAN(a) BANK_ADDR_REG((a), CHIP_ADDR_REG_MAN) +#define BANK_ADDR_REG_DEV(a) BANK_ADDR_REG((a), CHIP_ADDR_REG_DEV) +#define BANK_ADDR_REG_CFGM(a) BANK_ADDR_REG((a), CHIP_ADDR_REG_CFGM) +#define BANK_ADDR_REG_CFG(b,a) BANK_ADDR_REG((a), CHIP_ADDR_REG_CFG(b)) + +/* + * replicate a chip cmd/stat/rd value into each byte position within a word + * so that multiple chips are accessed in a single word i/o operation + * + * this must be as wide as the bank_word_t type, and take into account the + * chip width and bank layout + */ + +#define BANK_FILL_WORD(o) ((bank_word_t)(o)) + +/* make a bank word value for each chip cmd/stat/rd value */ + +/* Commands */ +#define BANK_CMD_RST BANK_FILL_WORD(CHIP_CMD_RST) +#define BANK_CMD_RD_ID BANK_FILL_WORD(CHIP_CMD_RD_ID) +#define BANK_CMD_RD_STAT BANK_FILL_WORD(CHIP_CMD_RD_STAT) +#define BANK_CMD_CLR_STAT BANK_FILL_WORD(CHIP_CMD_CLR_STAT) +#define BANK_CMD_ERASE1 BANK_FILL_WORD(CHIP_CMD_ERASE1) +#define BANK_CMD_ERASE2 BANK_FILL_WORD(CHIP_CMD_ERASE2) +#define BANK_CMD_PROG BANK_FILL_WORD(CHIP_CMD_PROG) +#define BANK_CMD_LOCK BANK_FILL_WORD(CHIP_CMD_LOCK) +#define BANK_CMD_SET_LOCK_BLK BANK_FILL_WORD(CHIP_CMD_SET_LOCK_BLK) +#define BANK_CMD_SET_LOCK_MSTR BANK_FILL_WORD(CHIP_CMD_SET_LOCK_MSTR) +#define BANK_CMD_CLR_LOCK_BLK BANK_FILL_WORD(CHIP_CMD_CLR_LOCK_BLK) + +/* status register bits */ +#define BANK_STAT_DPS BANK_FILL_WORD(CHIP_STAT_DPS) +#define BANK_STAT_PSS BANK_FILL_WORD(CHIP_STAT_PSS) +#define BANK_STAT_VPPS BANK_FILL_WORD(CHIP_STAT_VPPS) +#define BANK_STAT_PSLBS BANK_FILL_WORD(CHIP_STAT_PSLBS) +#define BANK_STAT_ECLBS BANK_FILL_WORD(CHIP_STAT_ECLBS) +#define BANK_STAT_ESS BANK_FILL_WORD(CHIP_STAT_ESS) +#define BANK_STAT_RDY BANK_FILL_WORD(CHIP_STAT_RDY) + +#define BANK_STAT_ERR BANK_FILL_WORD(CHIP_STAT_ERR) + +/* ID and Lock Configuration */ +#define BANK_RD_ID_LOCK BANK_FILL_WORD(CHIP_RD_ID_LOCK) +#define BANK_RD_ID_MAN BANK_FILL_WORD(CHIP_RD_ID_MAN) +#define BANK_RD_ID_DEV BANK_FILL_WORD(CHIP_RD_ID_DEV) diff --git a/board/Marvell/common/memory.c b/board/Marvell/common/memory.c new file mode 100644 index 0000000..45353af --- /dev/null +++ b/board/Marvell/common/memory.c @@ -0,0 +1,1390 @@ +/* + * Copyright - Galileo technology. + * + * 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 + */ + +/* + * + * written or collected and sometimes rewritten by + * Ingo Assmus <ingo.assmus@keymile.com> + * + */ + + +#include <common.h> +#include "../include/core.h" +#include "../include/memory.h" + +/******************************************************************************* +* memoryGetBankBaseAddress - Returns the base address of a memory bank. +* DESCRIPTION: +* This function returns the base address of one of the SDRAM’s memory +* banks. There are 4 memory banks and each one represents one DIMM side. +* INPUT: +* MEMORY_BANK bank - Selects one of the four banks as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit Memory bank base address. +*******************************************************************************/ +static unsigned long memoryGetBankRegOffset (MEMORY_BANK bank) +{ + switch (bank) { + case BANK0: + return SCS_0_LOW_DECODE_ADDRESS; + case BANK1: + return SCS_1_LOW_DECODE_ADDRESS; + case BANK2: + return SCS_2_LOW_DECODE_ADDRESS; + case BANK3: + return SCS_3_LOW_DECODE_ADDRESS; + + } + return SCS_0_LOW_DECODE_ADDRESS; /* default value */ +} + +unsigned int memoryGetBankBaseAddress (MEMORY_BANK bank) +{ + unsigned int base; + unsigned int regOffset = memoryGetBankRegOffset (bank); + + GT_REG_READ (regOffset, &base); + base = base << 16; /* MV6436x */ + return base; +} + +/******************************************************************************* +* memoryGetDeviceBaseAddress - Returns the base address of a device. +* DESCRIPTION: +* This function returns the base address of a device on the system. There +* are 5 possible devices (0 - 4 and one boot device) as defined in +* gtMemory.h. Each of the device parameters is maped to one of the CS +* (Devices chip selects) base address register. +* INPUT: +* device - Selects one of the five devices as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit Device base address. +* +*******************************************************************************/ +static unsigned int memoryGetDeviceRegOffset (DEVICE device) +{ + switch (device) { + case DEVICE0: + return CS_0_LOW_DECODE_ADDRESS; + case DEVICE1: + return CS_1_LOW_DECODE_ADDRESS; + case DEVICE2: + return CS_2_LOW_DECODE_ADDRESS; + case DEVICE3: + return CS_3_LOW_DECODE_ADDRESS; + case BOOT_DEVICE: + return BOOTCS_LOW_DECODE_ADDRESS; + } + return CS_0_LOW_DECODE_ADDRESS; /* default value */ +} + +unsigned int memoryGetDeviceBaseAddress (DEVICE device) +{ + unsigned int regBase; + unsigned int regOffset = memoryGetDeviceRegOffset (device); + + GT_REG_READ (regOffset, ®Base); + + regBase = regBase << 16; /* MV6436x */ + return regBase; +} + +/******************************************************************************* +* MemoryGetPciBaseAddr - Returns the base address of a PCI window. +* DESCRIPTION: +* This function returns the base address of a PCI window. There are 5 +* possible PCI windows (memory 0 - 3 and one for I/O) for each PCI +* interface as defined in gtMemory.h, used by the CPU's address decoding +* mechanism. +* New in MV6436x +* INPUT: +* pciWindow - Selects one of the PCI windows as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit PCI window base address. +*******************************************************************************/ +unsigned int MemoryGetPciBaseAddr (PCI_MEM_WINDOW pciWindow) +{ + unsigned int baseAddrReg, base; + + switch (pciWindow) { + case PCI_0_IO: + baseAddrReg = PCI_0I_O_LOW_DECODE_ADDRESS; /*PCI_0_IO_BASE_ADDR; */ + break; + case PCI_0_MEM0: + baseAddrReg = PCI_0MEMORY0_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY0_BASE_ADDR; */ + break; + case PCI_0_MEM1: + baseAddrReg = PCI_0MEMORY1_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY1_BASE_ADDR; */ + break; + case PCI_0_MEM2: + baseAddrReg = PCI_0MEMORY2_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY2_BASE_ADDR; */ + break; + case PCI_0_MEM3: + baseAddrReg = PCI_0MEMORY3_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY3_BASE_ADDR; */ + break; +#ifdef INCLUDE_PCI_1 + case PCI_1_IO: + baseAddrReg = PCI_1I_O_LOW_DECODE_ADDRESS; /*PCI_1_IO_BASE_ADDR; */ + break; + case PCI_1_MEM0: + baseAddrReg = PCI_1MEMORY0_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY0_BASE_ADDR; */ + break; + case PCI_1_MEM1: + baseAddrReg = PCI_1MEMORY1_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY1_BASE_ADDR; */ + break; + case PCI_1_MEM2: + baseAddrReg = PCI_1MEMORY2_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY2_BASE_ADDR; */ + break; + case PCI_1_MEM3: + baseAddrReg = PCI_1MEMORY3_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY3_BASE_ADDR; */ + break; +#endif /* INCLUDE_PCI_1 */ + default: + return 0xffffffff; + } + GT_REG_READ (baseAddrReg, &base); + return (base << 16); +} + +/******************************************************************************* +* memoryGetBankSize - Returns the size of a memory bank. +* DESCRIPTION: +* This function returns the size of memory bank as described in +* 'gtMemoryGetBankBaseAddress' function. +* INPUT: +* bank - Selects one of the four banks as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit size memory bank size or 0 for a closed or non populated bank. +* +*******************************************************************************/ +unsigned int memoryGetBankSize (MEMORY_BANK bank) +{ + unsigned int sizeReg, size; + MEMORY_WINDOW window; + + switch (bank) { + case BANK0: + sizeReg = SCS_0_HIGH_DECODE_ADDRESS; /* CS_0_SIZE; */ + window = CS_0_WINDOW; + break; + case BANK1: + sizeReg = SCS_1_HIGH_DECODE_ADDRESS; /* CS_1_SIZE; */ + window = CS_1_WINDOW; + break; + case BANK2: + sizeReg = SCS_2_HIGH_DECODE_ADDRESS; /* CS_2_SIZE; */ + window = CS_2_WINDOW; + break; + case BANK3: + sizeReg = SCS_3_HIGH_DECODE_ADDRESS; /* CS_3_SIZE; */ + window = CS_3_WINDOW; + break; + default: + return 0; + break; + } + /* If the window is closed, a size of 0 is returned */ + if (MemoryGetMemWindowStatus (window) != MEM_WINDOW_ENABLED) + return 0; + GT_REG_READ (sizeReg, &size); + size = ((size << 16) | 0xffff) + 1; + return size; +} + +/******************************************************************************* +* memoryGetDeviceSize - Returns the size of a device memory space. +* DESCRIPTION: +* This function returns the memory space size of a given device. +* INPUT: +* device - Selects one of the five devices as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit size of a device memory space. +*******************************************************************************/ +unsigned int memoryGetDeviceSize (DEVICE device) +{ + unsigned int sizeReg, size; + MEMORY_WINDOW window; + + switch (device) { + case DEVICE0: + sizeReg = CS_0_HIGH_DECODE_ADDRESS; /*DEV_CS0_SIZE; */ + window = DEVCS_0_WINDOW; + break; + case DEVICE1: + sizeReg = CS_1_HIGH_DECODE_ADDRESS; /*DEV_CS1_SIZE; */ + window = DEVCS_1_WINDOW; + break; + case DEVICE2: + sizeReg = CS_2_HIGH_DECODE_ADDRESS; /*DEV_CS2_SIZE; */ + window = DEVCS_2_WINDOW; + break; + case DEVICE3: + sizeReg = CS_3_HIGH_DECODE_ADDRESS; /*DEV_CS3_SIZE; */ + window = DEVCS_3_WINDOW; + break; + case BOOT_DEVICE: + sizeReg = BOOTCS_HIGH_DECODE_ADDRESS; /*BOOTCS_SIZE; */ + window = BOOT_CS_WINDOW; + break; + default: + return 0; + break; + } + /* If the window is closed, a size of 0 is returned */ + if (MemoryGetMemWindowStatus (window) != MEM_WINDOW_ENABLED) + return 0; + GT_REG_READ (sizeReg, &size); + size = ((size << 16) | 0xffff) + 1; + return size; +} + +/******************************************************************************* +* MemoryGetPciWindowSize - Returns the size of a PCI memory window. +* DESCRIPTION: +* This function returns the size of a PCI window. +* INPUT: +* pciWindow - Selects one of the PCI memory windows as defined in +* Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit size of a PCI memory window. +*******************************************************************************/ +unsigned int MemoryGetPciWindowSize (PCI_MEM_WINDOW pciWindow) +{ + unsigned int sizeReg, size; + + switch (pciWindow) { + case PCI_0_IO: + sizeReg = PCI_0I_O_HIGH_DECODE_ADDRESS; /*PCI_0_IO_SIZE; */ + break; + case PCI_0_MEM0: + sizeReg = PCI_0MEMORY0_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY0_SIZE; */ + break; + case PCI_0_MEM1: + sizeReg = PCI_0MEMORY1_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY1_SIZE; */ + break; + case PCI_0_MEM2: + sizeReg = PCI_0MEMORY2_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY2_SIZE; */ + break; + case PCI_0_MEM3: + sizeReg = PCI_0MEMORY3_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY3_SIZE; */ + break; +#ifdef INCLUDE_PCI_1 + case PCI_1_IO: + sizeReg = PCI_1I_O_HIGH_DECODE_ADDRESS; /*PCI_1_IO_SIZE; */ + break; + case PCI_1_MEM0: + sizeReg = PCI_1MEMORY0_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY0_SIZE; */ + break; + case PCI_1_MEM1: + sizeReg = PCI_1MEMORY1_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY1_SIZE; */ + break; + case PCI_1_MEM2: + sizeReg = PCI_1MEMORY2_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY2_SIZE; */ + break; + case PCI_1_MEM3: + sizeReg = PCI_1MEMORY3_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY3_SIZE; */ + break; +#endif /* INCLUDE_PCI_1 */ + default: + return 0x0; + } + /* If the memory window is disabled, retrun size = 0 */ + if (MemoryGetMemWindowStatus (PCI_0_IO_WINDOW << pciWindow) + == MEM_WINDOW_DISABLED) + return 0; + GT_REG_READ (sizeReg, &size); + size = ((size << 16) | 0xffff) + 1; + return size; +} + +/******************************************************************************* +* memoryGetDeviceWidth - Returns the width of a given device. +* DESCRIPTION: +* The MV's device interface supports up to 32 Bit wide devices. A device +* can have a 1, 2, 4 or 8 Bytes data width. This function returns the +* width of a device as defined by the user or the operating system. +* INPUT: +* device - Selects one of the five devices as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* Device width in Bytes (1,2,4 or 8), 0 if error had occurred. +*******************************************************************************/ +unsigned int memoryGetDeviceWidth (DEVICE device) +{ + unsigned int width; + unsigned int regValue; + + GT_REG_READ (DEVICE_BANK0PARAMETERS + device * 4, ®Value); + width = (regValue & (BIT20 | BIT21)) >> 20; + return (BIT0 << width); +} + +/******************************************************************************* +* memoryMapBank - Set new base address and size for one of the memory +* banks. +* +* DESCRIPTION: +* The CPU interface address decoding map consists of 21 address windows +* for the different devices (e.g. CS[3:0] ,PCI0 Mem 0/1/2/3...). Each +* window can have a minimum of 1Mbytes of address space, and up to 4Gbyte +* space. Each address window is defined by two registers - base and size. +* The CPU address is compared with the values in the various CPU windows +* until a match is found and the address is than targeted to that window. +* This function sets new base and size for one the memory banks +* (CS0 - CS3). It is the programmer`s responsibility to make sure that +* there are no conflicts with other memory spaces. When two memory spaces +* overlap, the MV’s behavior is not defined .If a bank needs to be closed, +* set the ’bankLength’ parameter size to 0x0. +* +* INPUT: +* bank - One of the memory banks (CS0-CS3) as defined in gtMemory.h. +* bankBase - The memory bank base address. +* bankLength - The memory bank size. This function will decrement the +* 'bankLength' parameter by one and then check if the size is +* valid. A valid size must be programed from LSB to MSB as +* sequence of ‘1’s followed by sequence of ‘0’s. +* To close a memory window simply set the size to 0. +* NOTE!!! +* The size must be in 64Kbyte granularity. +* The base address must be aligned to the size. +* OUTPUT: +* None. +* RETURN: +* False for invalid size, true otherwise. +* +* CAUTION: PCI_functions must be implemented later To_do !!!!!!!!!!!!!!!!! +* +*******************************************************************************/ + +bool memoryMapBank (MEMORY_BANK bank, unsigned int bankBase, + unsigned int bankLength) +{ + unsigned int newBase, newSize, baseReg, sizeReg, temp, rShift; + +/* PCI_INTERNAL_BAR pciBAR; */ + + switch (bank) { + case BANK0: + baseReg = SCS_0_LOW_DECODE_ADDRESS; /*CS_0_BASE_ADDR; */ + sizeReg = SCS_0_HIGH_DECODE_ADDRESS; /*CS_0_SIZE; */ +/* pciBAR = PCI_CS0_BAR; */ + break; + case BANK1: + baseReg = SCS_1_LOW_DECODE_ADDRESS; /*CS_1_BASE_ADDR; */ + sizeReg = SCS_1_HIGH_DECODE_ADDRESS; /*CS_1_SIZE; */ + /* pciBAR = SCS_0_HIGH_DECODE_ADDRESS; */ /*PCI_CS1_BAR; */ + break; + case BANK2: + baseReg = SCS_2_LOW_DECODE_ADDRESS; /*CS_2_BASE_ADDR; */ + sizeReg = SCS_2_HIGH_DECODE_ADDRESS; /*CS_2_SIZE; */ +/* pciBAR = PCI_CS2_BAR;*/ + break; + case BANK3: + baseReg = SCS_3_LOW_DECODE_ADDRESS; /*CS_3_BASE_ADDR; */ + sizeReg = SCS_3_HIGH_DECODE_ADDRESS; /*CS_3_SIZE; */ +/* pciBAR = PCI_CS3_BAR; */ + break; + default: + return false; + } + /* If the size is 0, the window will be disabled */ + if (bankLength == 0) { + MemoryDisableWindow (CS_0_WINDOW << bank); + /* Disable the BAR from the PCI slave side */ +/* gtPci0DisableInternalBAR(pciBAR); */ +/* gtPci1DisableInternalBAR(pciBAR); */ + return true; + } + /* The base address must be aligned to the size */ + if ((bankBase % bankLength) != 0) { + return false; + } + if (bankLength >= MINIMUM_MEM_BANK_SIZE) { + newBase = bankBase >> 16; + newSize = bankLength >> 16; + /* Checking that the size is a sequence of '1' followed by a + sequence of '0' starting from LSB to MSB. */ + temp = newSize - 1; + for (rShift = 0; rShift < 16; rShift++) { + temp = temp >> rShift; + if ((temp & 0x1) == 0) { /* Either we got to the last '1' */ + /* or the size is not valid */ + if (temp > 0x0) + return false; + else + break; + } + } +#ifdef DEBUG + { + unsigned int oldBase, oldSize; + + GT_REG_READ (baseReg, &oldBase); + GT_REG_READ (sizeReg + 8, &oldSize); + + printf ("b%d Base:%x Size:%x -> Base:%x Size:%x\n", + bank, oldBase, oldSize, newBase, newSize); + } +#endif + /* writing the new values */ + GT_REG_WRITE (baseReg, newBase); + GT_REG_WRITE (sizeReg, newSize - 1); + /* Enable back the window */ + MemoryEnableWindow (CS_0_WINDOW << bank); + /* Enable the BAR from the PCI slave side */ +/* gtPci0EnableInternalBAR(pciBAR); */ +/* gtPci1EnableInternalBAR(pciBAR); */ + return true; + } + return false; +} + + +/******************************************************************************* +* memoryMapDeviceSpace - Set new base address and size for one of the device +* windows. +* +* DESCRIPTION: +* The CPU interface address decoding map consists of 21 address windows +* for the different devices (e.g. CS[3:0] ,PCI0 Mem 0/1/2/3...). Each +* window can have a minimum of 1Mbytes of address space, and up to 4Gbyte +* space. Each address window is defined by two registers - base and size. +* The CPU address is compared with the values in the various CPU windows +* until a match is found and the address is than targeted to that window. +* This function sets new base and size for one the device windows +* (DEV_CS0 - DEV_CS3). It is the programmer`s responsibility to make sure +* that there are no conflicts with other memory spaces. When two memory +* spaces overlap, the MV’s behavior is not defined .If a device window +* needs to be closed, set the 'deviceLength' parameter size to 0x0. +* +* INPUT: +* device - One of the device windows (DEV_CS0-DEV_CS3) as +* defined in gtMemory.h. +* deviceBase - The device window base address. +* deviceLength - The device window size. This function will decrement +* the 'deviceLength' parameter by one and then +* check if the size is valid. A valid size must be +* programed from LSB to MSB as sequence of ‘1’s +* followed by sequence of ‘0’s. +* To close a memory window simply set the size to 0. +* +* NOTE!!! +* The size must be in 64Kbyte granularity. +* The base address must be aligned to the size. +* +* OUTPUT: +* None. +* +* RETURN: +* False for invalid size, true otherwise. +* +* CAUTION: PCI_functions must be implemented later To_do !!!!!!!!!!!!!!!!! +* +*******************************************************************************/ + +bool memoryMapDeviceSpace (DEVICE device, unsigned int deviceBase, + unsigned int deviceLength) +{ + unsigned int newBase, newSize, baseReg, sizeReg, temp, rShift; + +/* PCI_INTERNAL_BAR pciBAR;*/ + + switch (device) { + case DEVICE0: + baseReg = CS_0_LOW_DECODE_ADDRESS; /*DEV_CS0_BASE_ADDR; */ + sizeReg = CS_0_HIGH_DECODE_ADDRESS; /*DEV_CS0_SIZE; */ +/* pciBAR = PCI_DEV_CS0_BAR; */ + break; + case DEVICE1: + baseReg = CS_1_LOW_DECODE_ADDRESS; /*DEV_CS1_BASE_ADDR; */ + sizeReg = CS_1_HIGH_DECODE_ADDRESS; /*DEV_CS1_SIZE; */ +/* pciBAR = PCI_DEV_CS1_BAR; */ + break; + case DEVICE2: + baseReg = CS_2_LOW_DECODE_ADDRESS; /*DEV_CS2_BASE_ADDR; */ + sizeReg = CS_2_HIGH_DECODE_ADDRESS; /*DEV_CS2_SIZE; */ +/* pciBAR = PCI_DEV_CS2_BAR; */ + break; + case DEVICE3: + baseReg = CS_3_LOW_DECODE_ADDRESS; /*DEV_CS3_BASE_ADDR; */ + sizeReg = CS_3_HIGH_DECODE_ADDRESS; /*DEV_CS3_SIZE; */ +/* pciBAR = PCI_DEV_CS3_BAR; */ + break; + case BOOT_DEVICE: + baseReg = BOOTCS_LOW_DECODE_ADDRESS; /*BOOTCS_BASE_ADDR; */ + sizeReg = BOOTCS_HIGH_DECODE_ADDRESS; /*BOOTCS_SIZE; */ +/* pciBAR = PCI_BOOT_CS_BAR; */ + break; + default: + return false; + } + if (deviceLength == 0) { + MemoryDisableWindow (DEVCS_0_WINDOW << device); + /* Disable the BAR from the PCI slave side */ +/* gtPci0DisableInternalBAR(pciBAR); */ +/* gtPci1DisableInternalBAR(pciBAR); */ + return true; + } + /* The base address must be aligned to the size */ + if ((deviceBase % deviceLength) != 0) { + return false; + } + if (deviceLength >= MINIMUM_DEVICE_WINDOW_SIZE) { + newBase = deviceBase >> 16; + newSize = deviceLength >> 16; + /* Checking that the size is a sequence of '1' followed by a + sequence of '0' starting from LSB to MSB. */ + temp = newSize - 1; + for (rShift = 0; rShift < 16; rShift++) { + temp = temp >> rShift; + if ((temp & 0x1) == 0) { /* Either we got to the last '1' */ + /* or the size is not valid */ + if (temp > 0x0) + return false; + else + break; + } + } + /* writing the new values */ + GT_REG_WRITE (baseReg, newBase); + GT_REG_WRITE (sizeReg, newSize - 1); + MemoryEnableWindow (DEVCS_0_WINDOW << device); + /* Enable the BAR from the PCI slave side */ +/* gtPci0EnableInternalBAR(pciBAR); */ +/* gtPci1EnableInternalBAR(pciBAR); */ + return true; + } + return false; +} + +/******************************************************************************* +* MemorySetPciWindow - Set new base address and size for one of the PCI +* windows. +* +* DESCRIPTION: +* The CPU interface address decoding map consists of 21 address windows +* for the different devices (e.g. CS[3:0] ,PCI0 Mem 0/1/2/3...). Each +* window can have a minimum of 1Mbytes of address space, and up to 4Gbyte +* space. Each address window is defined by two registers - base and size. +* The CPU address is compared with the values in the various CPU windows +* until a match is found and the address is than targeted to that window. +* This function sets new base and size for one the PCI windows +* (PCI memory0/1/2..). It is the programmer`s responsibility to make sure +* that there are no conflicts with other memory spaces. When two memory +* spaces overlap, the MV’s behavior is not defined .If a PCI window +* needs to be closed, set the 'pciWindowSize' parameter size to 0x0. +* +* INPUT: +* pciWindow - One of the PCI windows as defined in gtMemory.h. +* pciWindowBase - The PCI window base address. +* pciWindowSize - The PCI window size. This function will decrement the +* 'pciWindowSize' parameter by one and then check if the +* size is valid. A valid size must be programed from LSB +* to MSB as sequence of ‘1’s followed by sequence of ‘0’s. +* To close a memory window simply set the size to 0. +* +* NOTE!!! +* The size must be in 64Kbyte granularity. +* The base address must be aligned to the size. +* +* OUTPUT: +* None. +* +* RETURN: +* False for invalid size, true otherwise. +* +*******************************************************************************/ +bool memorySetPciWindow (PCI_MEM_WINDOW pciWindow, unsigned int pciWindowBase, + unsigned int pciWindowSize) +{ + unsigned int currentLow, baseAddrReg, sizeReg, temp, rShift; + + switch (pciWindow) { + case PCI_0_IO: + baseAddrReg = PCI_1I_O_LOW_DECODE_ADDRESS; /*PCI_0_IO_BASE_ADDR; */ + sizeReg = PCI_0I_O_HIGH_DECODE_ADDRESS; /*PCI_0_IO_SIZE; */ + break; + case PCI_0_MEM0: + baseAddrReg = PCI_0MEMORY0_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY0_BASE_ADDR; */ + sizeReg = PCI_0MEMORY0_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY0_SIZE; */ + break; + case PCI_0_MEM1: + baseAddrReg = PCI_0MEMORY1_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY1_BASE_ADDR; */ + sizeReg = PCI_0MEMORY1_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY1_SIZE; */ + break; + case PCI_0_MEM2: + baseAddrReg = PCI_0MEMORY2_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY2_BASE_ADDR; */ + sizeReg = PCI_0MEMORY2_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY2_SIZE; */ + break; + case PCI_0_MEM3: + baseAddrReg = PCI_0MEMORY3_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY3_BASE_ADDR; */ + sizeReg = PCI_0MEMORY3_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY3_SIZE; */ + break; +#ifdef INCLUDE_PCI_1 + case PCI_1_IO: + baseAddrReg = PCI_1I_O_LOW_DECODE_ADDRESS; /*PCI_1_IO_BASE_ADDR; */ + sizeReg = PCI_1I_O_HIGH_DECODE_ADDRESS; /*PCI_1_IO_SIZE; */ + break; + case PCI_1_MEM0: + baseAddrReg = PCI_1MEMORY0_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY0_BASE_ADDR; */ + sizeReg = PCI_1MEMORY0_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY0_SIZE; */ + break; + case PCI_1_MEM1: + baseAddrReg = PCI_1MEMORY1_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY1_BASE_ADDR; */ + sizeReg = PCI_1MEMORY1_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY1_SIZE; */ + break; + case PCI_1_MEM2: + baseAddrReg = PCI_1MEMORY2_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY2_BASE_ADDR; */ + sizeReg = PCI_1MEMORY2_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY2_SIZE; */ + break; + case PCI_1_MEM3: + baseAddrReg = PCI_1MEMORY3_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY3_BASE_ADDR; */ + sizeReg = PCI_1MEMORY3_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY3_SIZE; */ + break; +#endif /* INCLUDE_PCI_1 */ + default: + return false; + } + if (pciWindowSize == 0) { + MemoryDisableWindow (PCI_0_IO_WINDOW << pciWindow); + return true; + } + /* The base address must be aligned to the size */ + if ((pciWindowBase % pciWindowSize) != 0) { + return false; + } + if (pciWindowSize >= MINIMUM_PCI_WINDOW_SIZE) { + pciWindowBase >>= 16; + pciWindowSize >>= 16; + /* Checking that the size is a sequence of '1' followed by a + sequence of '0' starting from LSB to MSB. */ + temp = pciWindowSize - 1; + for (rShift = 0; rShift < 16; rShift++) { + temp = temp >> rShift; + if ((temp & 0x1) == 0) { /* Either we got to the last '1' */ + /* or the size is not valid */ + if (temp > 0x0) + return false; + else + break; + } + } + GT_REG_WRITE (sizeReg, pciWindowSize - 1); + GT_REG_READ (baseAddrReg, ¤tLow); + pciWindowBase = + (pciWindowBase & 0xfffff) | (currentLow & 0xfff00000); + GT_REG_WRITE (baseAddrReg, pciWindowBase); + MemoryEnableWindow (PCI_0_IO_WINDOW << pciWindow); + return true; + } + return false; +} + +/******************************************************************************* +* memoryMapInternalRegistersSpace - Sets new base address for the internal +* registers memory space. +* +* DESCRIPTION: +* This function set new base address for the internal register’s memory +* space (the size is fixed and cannot be modified). The function does not +* handle overlapping with other memory spaces, it is the programer's +* responsibility to ensure that overlapping does not occur. +* When two memory spaces overlap, the MV’s behavior is not defined. +* +* INPUT: +* internalRegBase - new base address for the internal register’s memory +* space. +* +* OUTPUT: +* None. +* +* RETURN: +* true on success, false on failure +* +*******************************************************************************/ +/******************************************************************** +* memoryMapInternalRegistersSpace - Sets new base address for the internals +* registers. +* +* INPUTS: unsigned int internalRegBase - The new base address. +* RETURNS: true on success, false on failure +*********************************************************************/ +bool memoryMapInternalRegistersSpace (unsigned int internalRegBase) +{ + unsigned int currentValue; + unsigned int internalValue = internalRegBase; + + internalRegBase = (internalRegBase >> 16); + GT_REG_READ (INTERNAL_SPACE_DECODE, ¤tValue); + internalRegBase = (currentValue & 0xff000000) | internalRegBase; + GT_REG_WRITE (INTERNAL_SPACE_DECODE, internalRegBase); + /* initializing also the global variable 'internalRegBaseAddr' */ +/* gtInternalRegBaseAddr = internalValue; */ + INTERNAL_REG_BASE_ADDR = internalValue; + return true; +} + +/******************************************************************************* +* memoryGetInternalRegistersSpace - Returns the internal registers Base +* address. +* +* DESCRIPTION: +* This function returns the base address of the internal register’s +* memory space . +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32 bit base address of the internal register’s memory space. +* +*******************************************************************************/ +unsigned int memoryGetInternalRegistersSpace (void) +{ + unsigned int currentValue = 0; + + GT_REG_READ (INTERNAL_SPACE_DECODE, ¤tValue); + return ((currentValue & 0x000fffff) << 16); +} + +/******************************************************************************* +* gtMemoryGetInternalSramBaseAddr - Returns the integrated SRAM base address. +* +* DESCRIPTION: +* The Atlantis incorporate integrated 2Mbit SRAM for general use. This +* funcnion return the SRAM's base address. +* INPUT: +* None. +* OUTPUT: +* None. +* RETURN: +* 32 bit SRAM's base address. +* +*******************************************************************************/ +unsigned int memoryGetInternalSramBaseAddr (void) +{ + return ((GTREGREAD (INTEGRATED_SRAM_BASE_ADDR) & 0xfffff) << 16); +} + +/******************************************************************************* +* gtMemorySetInternalSramBaseAddr - Set the integrated SRAM base address. +* +* DESCRIPTION: +* The Atlantis incorporate integrated 2Mbit SRAM for general use. This +* function sets a new base address to the SRAM . +* INPUT: +* sramBaseAddress - The SRAM's base address. +* OUTPUT: +* None. +* RETURN: +* None. +* +*******************************************************************************/ +void gtMemorySetInternalSramBaseAddr (unsigned int sramBaseAddress) +{ + GT_REG_WRITE (INTEGRATED_SRAM_BASE_ADDR, sramBaseAddress >> 16); +} + +/******************************************************************************* +* memorySetProtectRegion - Set protection mode for one of the 8 regions. +* +* DESCRIPTION: +* The CPU interface supports configurable access protection. This includes +* up to eight address ranges defined to a different protection type : +* whether the address range is cacheable or not, whether it is writable or +* not , and whether it is accessible or not. A Low and High registers +* define each window while the minimum address range of each window is +* 1Mbyte. An address driven by the CPU, in addition to the address +* decoding and remapping process, is compared against the eight Access +* Protection Low/High registers , if an address matches one of the windows +* , the MV device checks the transaction type against the protection bits +* defined in CPU Access Protection register, to determine if the access is +* allowed. This function set a protection mode to one of the 8 possible +* regions. +* NOTE: +* The CPU address windows are restricted to a size of 2 power n and the +* start address must be aligned to the window size. For example, if using +* a 16 MB window, the start address bits [23:0] must be 0.The MV's +* internal registers space is not protected, even if the access protection +* windows contain this space. +* +* INPUT: +* region - selects which region to be configured. The values defined in +* gtMemory.h: +* +* - MEM_REGION0 +* - MEM_REGION1 +* - etc. +* +* memAccess - Allows or forbids access (read or write ) to the region. The +* values defined in gtMemory.h: +* +* - MEM_ACCESS_ALLOWED +* - MEM_ACCESS_FORBIDEN +* +* memWrite - CPU write protection to the region. The values defined in +* gtMemory.h: +* +* - MEM_WRITE_ALLOWED +* - MEM_WRITE_FORBIDEN +* +* cacheProtection - Defines whether caching the region is allowed or not. +* The values defined in gtMemory.h: +* +* - MEM_CACHE_ALLOWED +* - MEM_CACHE_FORBIDEN +* +* baseAddress - the region's base Address. +* regionSize - The region's size. This function will decrement the +* 'regionSize' parameter by one and then check if the size +* is valid. A valid size must be programed from LSB to MSB +* as sequence of ‘1’s followed by sequence of ‘0’s. +* To close a memory window simply set the size to 0. +* +* NOTE!!! +* The size must be in 64Kbyte granularity. +* The base address must be aligned to the size. +* +* OUTPUT: +* None. +* +* RETURN: +* False for invalid size, true otherwise. +* +*******************************************************************************/ +bool memorySetProtectRegion (MEMORY_PROTECT_WINDOW window, + MEMORY_ACCESS memAccess, + MEMORY_ACCESS_WRITE memWrite, + MEMORY_CACHE_PROTECT cacheProtection, + unsigned int baseAddress, unsigned int size) +{ + unsigned int dataForReg, temp, rShift; + + if (size == 0) { + GT_REG_WRITE ((CPU_PROTECT_WINDOW_0_SIZE + 0x10 * window), + 0x0); + return true; + } + /* The base address must be aligned to the size. */ + if (baseAddress % size != 0) { + return false; + } + if (size >= MINIMUM_ACCESS_WIN_SIZE) { + baseAddress = ((baseAddress >> 16) & 0xfffff); + dataForReg = baseAddress | ((memAccess << 20) & BIT20) | + ((memWrite << 21) & BIT21) | ((cacheProtection << 22) + & BIT22) | BIT31; + GT_REG_WRITE (CPU_PROTECT_WINDOW_0_BASE_ADDR + 0x10 * window, + dataForReg); + size >>= 16; + /* Checking that the size is a sequence of '1' followed by a + sequence of '0' starting from LSB to MSB. */ + temp = size - 1; + for (rShift = 0; rShift < 16; rShift++) { + temp = temp >> rShift; + if ((temp & 0x1) == 0) { /* Either we got to the last '1' */ + /* or the size is not valid */ + if (temp > 0x0) + return false; + else + break; + } + } + GT_REG_WRITE ((CPU_PROTECT_WINDOW_0_SIZE + 0x10 * window), + size - 1); + return true; + } + return false; +} + +/******************************************************************************* +* gtMemoryDisableProtectRegion - Disable a protected window. +* +* DESCRIPTION: +* This function disable a protected window set by +* 'gtMemorySetProtectRegion' function. +* +* INPUT: +* window - one of the 4 windows ( defined in gtMemory.h ). +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +void memoryDisableProtectRegion (MEMORY_PROTECT_WINDOW window) +{ + RESET_REG_BITS (((CPU_PROTECT_WINDOW_0_BASE_ADDR) + (0x10 * window)), + BIT31); +} + +/******************************************************************************* +* memorySetPciRemapValue - Set a remap value to a PCI memory space target. +* +* DESCRIPTION: +* In addition to the address decoding mechanism, the CPU has an address +* remapping mechanism to be used by every PCI decoding window. Each PCI +* window can be remaped to a desired address target according to the remap +* value within the remap register. The address remapping is useful when a +* CPU address range must be reallocated to a different location on the +* PCI bus. Also, it enables CPU access to a PCI agent located above the +* 4Gbyte space. On system boot, each of the PCI memory spaces is maped to +* a defualt value (see CPU interface section in the MV spec for the +* default values). The remap mechanism does not always produce the desired +* address on the PCI bus because of the remap mechanism way of working +* (to fully understand why, please see the 'Address Remapping' section in +* the MV's spec). Therefor, this function sets a desired remap value to +* one of the PCI memory windows and return the effective address that +* should be used when exiting the PCI memory window. You should ALWAYS use +* the returned value by this function when remapping a PCI window and +* exiting it. If for example the base address of PCI0 memory 0 is +* 0x90000000, the size is 0x03ffffff and the remap value is 0x11000000, +* the function will return the value of 0x91000000 that MUST +* be used to exit this memory window in order to achive the deisred +* remapping. +* +* INPUT: +* memoryWindow - One of the PCI memory windows as defined in Memory.h +* remapValueLow - The low remap value. +* remapValueHigh - The high remap value. +* OUTPUT: +* None. +* +* RETURN: +* The effective base address to exit the PCI, or 0xffffffff if one of the +* parameters is erroneous or the effective base address is higher the top +* decode value. +* +*******************************************************************************/ +unsigned int memorySetPciRemapValue (PCI_MEM_WINDOW memoryWindow, + unsigned int remapValueHigh, + unsigned int remapValueLow) +{ + unsigned int pciMemWindowBaseAddrReg = 0, baseAddrValue = 0; + unsigned int pciMemWindowSizeReg = 0, windowSizeValue = 0; + unsigned int effectiveBaseAddress, remapRegLow, remapRegHigh; + + /* Initializing the base and size variables of the PCI + memory windows */ + switch (memoryWindow) { + case PCI_0_IO: + pciMemWindowBaseAddrReg = PCI_0_IO_BASE_ADDR; + pciMemWindowSizeReg = PCI_0_IO_SIZE; + remapRegLow = PCI_0_IO_ADDR_REMAP; + remapRegHigh = PCI_0_IO_ADDR_REMAP; + break; + case PCI_0_MEM0: + pciMemWindowBaseAddrReg = PCI_0_MEMORY0_BASE_ADDR; + pciMemWindowSizeReg = PCI_0_MEMORY0_SIZE; + remapRegLow = PCI_0_MEMORY0_LOW_ADDR_REMAP; + remapRegHigh = PCI_0_MEMORY0_HIGH_ADDR_REMAP; + break; + case PCI_0_MEM1: + pciMemWindowBaseAddrReg = PCI_0_MEMORY1_BASE_ADDR; + pciMemWindowSizeReg = PCI_0_MEMORY1_SIZE; + remapRegLow = PCI_0_MEMORY1_LOW_ADDR_REMAP; + remapRegHigh = PCI_0_MEMORY1_HIGH_ADDR_REMAP; + break; + case PCI_0_MEM2: + pciMemWindowBaseAddrReg = PCI_0_MEMORY2_BASE_ADDR; + pciMemWindowSizeReg = PCI_0_MEMORY2_SIZE; + remapRegLow = PCI_0_MEMORY2_LOW_ADDR_REMAP; + remapRegHigh = PCI_0_MEMORY2_HIGH_ADDR_REMAP; + break; + case PCI_0_MEM3: + pciMemWindowBaseAddrReg = PCI_0_MEMORY3_BASE_ADDR; + pciMemWindowSizeReg = PCI_0_MEMORY3_SIZE; + remapRegLow = PCI_0_MEMORY3_LOW_ADDR_REMAP; + remapRegHigh = PCI_0_MEMORY3_HIGH_ADDR_REMAP; + break; +#ifdef INCLUDE_PCI_1 + case PCI_1_IO: + pciMemWindowBaseAddrReg = PCI_1_IO_BASE_ADDR; + pciMemWindowSizeReg = PCI_1_IO_SIZE; + remapRegLow = PCI_1_IO_ADDR_REMAP; + remapRegHigh = PCI_1_IO_ADDR_REMAP; + break; + case PCI_1_MEM0: + pciMemWindowBaseAddrReg = PCI_1_MEMORY0_BASE_ADDR; + pciMemWindowSizeReg = PCI_1_MEMORY0_SIZE; + remapRegLow = PCI_1_MEMORY0_LOW_ADDR_REMAP; + remapRegHigh = PCI_1_MEMORY0_HIGH_ADDR_REMAP; + break; + case PCI_1_MEM1: + pciMemWindowBaseAddrReg = PCI_1_MEMORY1_BASE_ADDR; + pciMemWindowSizeReg = PCI_1_MEMORY1_SIZE; + remapRegLow = PCI_1_MEMORY1_LOW_ADDR_REMAP; + remapRegHigh = PCI_1_MEMORY1_HIGH_ADDR_REMAP; + break; + case PCI_1_MEM2: + pciMemWindowBaseAddrReg = PCI_1_MEMORY1_BASE_ADDR; + pciMemWindowSizeReg = PCI_1_MEMORY1_SIZE; + remapRegLow = PCI_1_MEMORY1_LOW_ADDR_REMAP; + remapRegHigh = PCI_1_MEMORY1_HIGH_ADDR_REMAP; + break; + case PCI_1_MEM3: + pciMemWindowBaseAddrReg = PCI_1_MEMORY3_BASE_ADDR; + pciMemWindowSizeReg = PCI_1_MEMORY3_SIZE; + remapRegLow = PCI_1_MEMORY3_LOW_ADDR_REMAP; + remapRegHigh = PCI_1_MEMORY3_HIGH_ADDR_REMAP; + break; +#endif /* INCLUDE_PCI_1 */ + default: + /* Retrun an invalid effective base address */ + return 0xffffffff; + } + /* Writing the remap value to the remap regisers */ + GT_REG_WRITE (remapRegHigh, remapValueHigh); + GT_REG_WRITE (remapRegLow, remapValueLow >> 16); + /* Reading the values from the base address and size registers */ + baseAddrValue = GTREGREAD (pciMemWindowBaseAddrReg) & 0xfffff; + windowSizeValue = GTREGREAD (pciMemWindowSizeReg) & 0xffff; + /* Start calculating the effective Base Address */ + effectiveBaseAddress = baseAddrValue << 16; + /* The effective base address will be combined from the chopped (if any) + remap value (according to the size value and remap mechanism) and the + window's base address */ + effectiveBaseAddress |= + (((windowSizeValue << 16) | 0xffff) & remapValueLow); + /* If the effectiveBaseAddress exceed the window boundaries return an + invalid value. */ + if (effectiveBaseAddress > + ((baseAddrValue << 16) + ((windowSizeValue << 16) | 0xffff))) + return 0xffffffff; + return effectiveBaseAddress; +} + +/******************************************************************** +* memorySetRegionSnoopMode - This function modifys one of the 4 regions which +* supports Cache Coherency. +* +* +* Inputs: SNOOP_REGION region - One of the four regions. +* SNOOP_TYPE 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. +* unsigned int baseAddress - Base Address of this region. +* unsigned int topAddress - Top Address of this region. +* Returns: false if one of the parameters is wrong and true else +*********************************************************************/ +/* evb6260 code */ +#if 0 +bool memorySetRegionSnoopMode(MEMORY_SNOOP_REGION region, + MEMORY_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 > MEM_SNOOP_REGION3) || (snoopType > MEM_SNOOP_WB) ) + return false; + snoopXbaseAddress = SNOOP_BASE_ADDRESS_0 + 0x10 * region; + snoopXtopAddress = SNOOP_TOP_ADDRESS_0 + 0x10 * region; + if(regionLength == 0) /* closing the region */ + { + GT_REG_WRITE(snoopXbaseAddress,0x0000ffff); + GT_REG_WRITE(snoopXtopAddress,0); + return true; + } + baseAddress = baseAddress & 0xffff0000; + data = (baseAddress >> 16) | snoopType << 16; + GT_REG_WRITE(snoopXbaseAddress,data); + snoopHigh = (snoopHigh & 0xfff00000) >> 20; + GT_REG_WRITE(snoopXtopAddress,snoopHigh - 1); + return true; +} +#endif + +/******************************************************************** +* memoryRemapAddress - This fubction used for address remapping. +* +* +* Inputs: regOffset: remap register +* remapValue : +* Returns: false if one of the parameters is erroneous,true otherwise. +* +* Not needed function To_do !!!! +*********************************************************************/ +bool memoryRemapAddress (unsigned int remapReg, unsigned int remapValue) +{ + unsigned int valueForReg; + + valueForReg = (remapValue & 0xfff00000) >> 20; + GT_REG_WRITE (remapReg, valueForReg); + return true; +} + +/******************************************************************************* +* memoryGetDeviceParam - Extract the device parameters from the device bank +* parameters register. +* +* DESCRIPTION: +* To allow interfacing with very slow devices and fast synchronous SRAMs, +* each device can be programed to different timing parameters. Each bank +* has its own parameters register. Bank width can be programmed to 8, 16, +* or 32-bits. Bank timing parameters can be programmed to support +* different device types (e.g. Sync Burst SRAM, Flash , ROM, I/O +* Controllers). The MV allows you to set timing parameters and width for +* each device through parameters register . +* This function extracts the parameters described from the Device Bank +* parameters register and fills the given 'deviceParam' (defined in +* gtMemory.h) structure with the read data. +* +* INPUT: +* deviceParam - pointer to a structure DEVICE_PARAM (defined in +* Memory.h).For details about each structure field please +* see the device timing parameter section in the MV +* datasheet. +* deviceNum - Select on of the five device banks (defined in +* Memory.h) : +* +* - DEVICE0 +* - DEVICE1 +* - DEVICE2 +* - etc. +* +* OUTPUT: +* None. +* +* RETURN: +* false if one of the parameters is erroneous,true otherwise. +* +*******************************************************************************/ +/******************************************************************** +* memoryGetDeviceParam - This function used for getting device parameters from +* DEVICE BANK PARAMETERS REGISTER +* +* +* Inputs: - deviceParam: STRUCT with paramiters for DEVICE BANK +* PARAMETERS REGISTER +* - deviceNum : number of device +* Returns: false if one of the parameters is erroneous,true otherwise. +*********************************************************************/ + +bool memoryGetDeviceParam (DEVICE_PARAM * deviceParam, DEVICE deviceNum) +{ + unsigned int valueOfReg; + unsigned int calcData; + + if (deviceNum > 4) + return false; + GT_REG_READ (DEVICE_BANK0PARAMETERS + 4 * deviceNum, &valueOfReg); + calcData = (0x7 & valueOfReg) + ((BIT22 & valueOfReg) >> 19); + deviceParam->turnOff = calcData; /* Turn Off */ + + calcData = ((0x78 & valueOfReg) >> 3) + ((BIT23 & valueOfReg) >> 19); + deviceParam->acc2First = calcData; /* Access To First */ + + calcData = ((0x780 & valueOfReg) >> 7) + ((BIT24 & valueOfReg) >> 20); + deviceParam->acc2Next = calcData; /* Access To Next */ + + calcData = + ((0x3800 & valueOfReg) >> 11) + ((BIT25 & valueOfReg) >> 22); + deviceParam->ale2Wr = calcData; /* Ale To Write */ + + calcData = ((0x1c000 & valueOfReg) >> 14) + + ((BIT26 & valueOfReg) >> 23); + deviceParam->wrLow = calcData; /* Write Active */ + + calcData = ((0xe0000 & valueOfReg) >> 17) + + ((BIT27 & valueOfReg) >> 24); + deviceParam->wrHigh = calcData; /* Write High */ + + calcData = ((0x300000 & valueOfReg) >> 20); + deviceParam->deviceWidth = (BIT0 << calcData); /* In bytes */ + calcData = ((0x30000000 & valueOfReg) >> 28); + deviceParam->badrSkew = calcData; /* Cycles gap between BAdr + toggle to read data sample. */ + calcData = ((0x40000000 & valueOfReg) >> 30); + deviceParam->DPEn = calcData; /* Data Parity enable */ + return true; +} + +/******************************************************************************* +* memorySetDeviceParam - Set new parameters for a device. +* +* +* DESCRIPTION: +* To allow interfacing with very slow devices and fast synchronous SRAMs, +* each device can be programed to different timing parameters. Each bank +* has its own parameters register. Bank width can be programmed to 8, 16, +* or 32-bits. Bank timing parameters can be programmed to support +* different device types (e.g. Sync Burst SRAM, Flash , ROM, I/O +* Controllers). The MV allows you to set timing parameters and width for +* each device through parameters register. This function set new +* parameters to a device Bank from the delivered structure 'deviceParam' +* (defined in gtMemory.h). The structure must be initialized with data +* prior to the use of these function. +* +* INPUT: +* deviceParam - pointer to a structure DEVICE_PARAM (defined in +* Memory.h).For details about each structure field please +* see the device timing parameter section in the MV +* datasheet. +* deviceNum - Select on of the five device banks (defined in +* Memory.h) : +* +* - DEVICE0 +* - DEVICE1 +* - DEVICE2 +* - etc. +* +* OUTPUT: +* None. +* +* RETURN: +* false if one of the parameters is erroneous,true otherwise. +* +*******************************************************************************/ +/******************************************************************** +* memorySetDeviceParam - This function used for setting device parameters to +* DEVICE BANK PARAMETERS REGISTER +* +* +* Inputs: - deviceParam: STRUCT for store paramiters from DEVICE BANK +* PARAMETERS REGISTER +* - deviceNum : number of device +* Returns: false if one of the parameters is erroneous,true otherwise. +*********************************************************************/ +bool memorySetDeviceParam (DEVICE_PARAM * deviceParam, DEVICE deviceNum) +{ + unsigned int valueForReg; + + if ((deviceParam->turnOff > 0x7) || (deviceParam->acc2First > 0xf) || + (deviceParam->acc2Next > 0xf) || (deviceParam->ale2Wr > 0x7) || + (deviceParam->wrLow > 0x7) || (deviceParam->wrHigh > 0x7) || + (deviceParam->badrSkew > 0x2) || (deviceParam->DPEn > 0x1)) { + return false; + } + valueForReg = (((deviceParam->turnOff) & 0x7) | + (((deviceParam->turnOff) & 0x8) << 19) | + (((deviceParam->acc2First) & 0xf) << 3) | + (((deviceParam->acc2First) & 0x10) << 19) | + (((deviceParam->acc2Next) & 0xf) << 7) | + (((deviceParam->acc2Next) & 0x10) << 20) | + (((deviceParam->ale2Wr) & 0x7) << 11) | + (((deviceParam->ale2Wr) & 0xf) << 22) | + (((deviceParam->wrLow) & 0x7) << 14) | + (((deviceParam->wrLow) & 0xf) << 23) | + (((deviceParam->wrHigh) & 0x7) << 17) | + (((deviceParam->wrHigh) & 0xf) << 24) | + (((deviceParam->badrSkew) & 0x3) << 28) | + (((deviceParam->DPEn) & 0x1) << 30)); + + /* insert the device width: */ + switch (deviceParam->deviceWidth) { + case 1: + valueForReg = valueForReg | _8BIT; + break; + case 2: + valueForReg = valueForReg | _16BIT; + break; + case 4: + valueForReg = valueForReg | _32BIT; + break; + default: + valueForReg = valueForReg | _8BIT; + break; + } + GT_REG_WRITE (DEVICE_BANK0PARAMETERS + 4 * deviceNum, valueForReg); + return true; +} + +/******************************************************************************* +* MemoryDisableWindow - Disable a memory space by the disable bit. +* DESCRIPTION: +* This function disables one of the 21 availiable windows dedicated for +* the CPU decoding mechanism. Its possible to combine several windows with +* the OR command. +* INPUT: +* window - One or more of the memory windows (defined in gtMemory.h). +* OUTPUT: +* None. +* RETURN: +* None. +*******************************************************************************/ +void MemoryDisableWindow (MEMORY_WINDOW window) +{ + SET_REG_BITS (BASE_ADDR_ENABLE, window); +} + +/******************************************************************************* +* MemoryEnableWindow - Enable a memory space that was disabled by +* 'MemoryDisableWindow'. +* DESCRIPTION: +* This function enables one of the 21 availiable windows dedicated for the +* CPU decoding mechanism. Its possible to combine several windows with the +* OR command. +* INPUT: +* window - One or more of the memory windows (defined in gtMemory.h). +* OUTPUT: +* None. +* RETURN: +* None. +*******************************************************************************/ +void MemoryEnableWindow (MEMORY_WINDOW window) +{ + RESET_REG_BITS (BASE_ADDR_ENABLE, window); +} + +/******************************************************************************* +* MemoryGetMemWindowStatus - This function check whether the memory window is +* disabled or not. +* DESCRIPTION: +* This function checks if the given memory window is closed . +* INPUT: +* window - One or more of the memory windows (defined in gtMemory.h). +* OUTPUT: +* None. +* RETURN: +* True for a closed window, false otherwise . +*******************************************************************************/ +MEMORY_WINDOW_STATUS MemoryGetMemWindowStatus (MEMORY_WINDOW window) +{ + if (GTREGREAD (BASE_ADDR_ENABLE) & window) + return MEM_WINDOW_DISABLED; + return MEM_WINDOW_ENABLED; +} diff --git a/board/Marvell/common/misc.S b/board/Marvell/common/misc.S new file mode 100644 index 0000000..41c3a95 --- /dev/null +++ b/board/Marvell/common/misc.S @@ -0,0 +1,235 @@ +#include <config.h> +#include <74xx_7xx.h> +#include "version.h" + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +#include "../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 + + /* 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) +/* stw r18, 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) +/* stw r18, 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/Marvell/common/ns16550.c b/board/Marvell/common/ns16550.c new file mode 100644 index 0000000..475445b --- /dev/null +++ b/board/Marvell/common/ns16550.c @@ -0,0 +1,66 @@ +/* + * COM1 NS16550 support + * originally from linux source (arch/ppc/boot/ns16550.c) + * modified to use CFG_ISA_MEM and new defines + * + * further modified by Josh Huber <huber@mclx.com> to support + * the DUART on the Galileo Eval board. (db64360) + */ + +#include <config.h> +#include "ns16550.h" + +#ifdef ZUMA_NTL +/* no 16550 device */ +#else +const NS16550_t COM_PORTS[] = { (NS16550_t) (CFG_DUART_IO + 0), + (NS16550_t) (CFG_DUART_IO + 0x20) +}; + +volatile struct NS16550 *NS16550_init (int chan, int baud_divisor) +{ + volatile struct NS16550 *com_port; + + com_port = (struct NS16550 *) COM_PORTS[chan]; + com_port->ier = 0x00; + com_port->lcr = LCR_BKSE; /* Access baud rate */ + com_port->dll = baud_divisor & 0xff; /* 9600 baud */ + com_port->dlm = (baud_divisor >> 8) & 0xff; + com_port->lcr = LCR_8N1; /* 8 data, 1 stop, no parity */ + com_port->mcr = MCR_DTR | MCR_RTS; /* RTS/DTR */ + + /* Clear & enable FIFOs */ + com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR; + return (com_port); +} + +void NS16550_reinit (volatile struct NS16550 *com_port, int baud_divisor) +{ + com_port->ier = 0x00; + com_port->lcr = LCR_BKSE; /* Access baud rate */ + com_port->dll = baud_divisor & 0xff; /* 9600 baud */ + com_port->dlm = (baud_divisor >> 8) & 0xff; + com_port->lcr = LCR_8N1; /* 8 data, 1 stop, no parity */ + com_port->mcr = MCR_DTR | MCR_RTS; /* RTS/DTR */ + + /* Clear & enable FIFOs */ + com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR; +} + +void NS16550_putc (volatile struct NS16550 *com_port, unsigned char c) +{ + while ((com_port->lsr & LSR_THRE) == 0); + com_port->thr = c; +} + +unsigned char NS16550_getc (volatile struct NS16550 *com_port) +{ + while ((com_port->lsr & LSR_DR) == 0); + return (com_port->rbr); +} + +int NS16550_tstc (volatile struct NS16550 *com_port) +{ + return ((com_port->lsr & LSR_DR) != 0); +} +#endif diff --git a/board/Marvell/common/ns16550.h b/board/Marvell/common/ns16550.h new file mode 100644 index 0000000..f2ed2ab --- /dev/null +++ b/board/Marvell/common/ns16550.h @@ -0,0 +1,102 @@ +/* + * NS16550 Serial Port + * originally from linux source (arch/ppc/boot/ns16550.h) + * modified slightly to + * have addresses as offsets from CFG_ISA_BASE + * added a few more definitions + * added prototypes for ns16550.c + * reduced no of com ports to 2 + * modifications (c) Rob Taylor, Flying Pig Systems. 2000. + * + * further modified to support the DUART in the Galileo eval board + * modifications (c) Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + */ + +#ifndef __NS16550_H__ +#define __NS16550_H__ + +/* the padding is necessary because on the galileo board the UART is + wired in with the 3 address lines shifted over by 2 bits */ +struct NS16550 +{ + unsigned char rbr; /* 0 = 0-3*/ + int pad1:24; + + unsigned char ier; /* 1 = 4-7*/ + int pad2:24; + + unsigned char fcr; /* 2 = 8-b*/ + int pad3:24; + + unsigned char lcr; /* 3 = c-f*/ + int pad4:24; + + unsigned char mcr; /* 4 = 10-13*/ + int pad5:24; + + unsigned char lsr; /* 5 = 14-17*/ + int pad6:24; + + unsigned char msr; /* 6 =18-1b*/ + int pad7:24; + + unsigned char scr; /* 7 =1c-1f*/ + int pad8:24; +} __attribute__ ((packed)); + +/* aliases */ +#define thr rbr +#define iir fcr +#define dll rbr +#define dlm ier + +#define FCR_FIFO_EN 0x01 /*fifo enable*/ +#define FCR_RXSR 0x02 /*reciever soft reset*/ +#define FCR_TXSR 0x04 /*transmitter soft reset*/ + + +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_DMA_EN 0x04 +#define MCR_TX_DFR 0x08 + + +#define LCR_WLS_MSK 0x03 /* character length slect mask*/ +#define LCR_WLS_5 0x00 /* 5 bit character length */ +#define LCR_WLS_6 0x01 /* 6 bit character length */ +#define LCR_WLS_7 0x02 /* 7 bit character length */ +#define LCR_WLS_8 0x03 /* 8 bit character length */ +#define LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */ +#define LCR_PEN 0x08 /* Parity eneble*/ +#define LCR_EPS 0x10 /* Even Parity Select*/ +#define LCR_STKP 0x20 /* Stick Parity*/ +#define LCR_SBRK 0x40 /* Set Break*/ +#define LCR_BKSE 0x80 /* Bank select enable*/ + +#define LSR_DR 0x01 /* Data ready */ +#define LSR_OE 0x02 /* Overrun */ +#define LSR_PE 0x04 /* Parity error */ +#define LSR_FE 0x08 /* Framing error */ +#define LSR_BI 0x10 /* Break */ +#define LSR_THRE 0x20 /* Xmit holding register empty */ +#define LSR_TEMT 0x40 /* Xmitter empty */ +#define LSR_ERR 0x80 /* Error */ + +/* useful defaults for LCR*/ +#define LCR_8N1 0x03 + + +#define COM1 0x03F8 +#define COM2 0x02F8 + +volatile struct NS16550 * NS16550_init(int chan, int baud_divisor); +void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c); +unsigned char NS16550_getc(volatile struct NS16550 *com_port); +int NS16550_tstc(volatile struct NS16550 *com_port); +void NS16550_reinit(volatile struct NS16550 *com_port, int baud_divisor); + +typedef struct NS16550 *NS16550_t; + +extern const NS16550_t COM_PORTS[]; + +#endif diff --git a/board/Marvell/common/ppc_error_no.h b/board/Marvell/common/ppc_error_no.h new file mode 100644 index 0000000..53687c8 --- /dev/null +++ b/board/Marvell/common/ppc_error_no.h @@ -0,0 +1,164 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * 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/Marvell/common/serial.c b/board/Marvell/common/serial.c new file mode 100644 index 0000000..9d0d213 --- /dev/null +++ b/board/Marvell/common/serial.c @@ -0,0 +1,178 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * modified for marvell db64360 eval board by + * Ingo Assmus <ingo.assmus@keymile.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * serial.c - serial support for the gal ev board + */ + +/* supports both the 16650 duart and the MPSC */ + +#include <common.h> +#include <command.h> +#include "../include/memory.h" +#include "serial.h" + +#ifdef CONFIG_DB64360 +#include "../db64360/mpsc.h" +#endif + +#ifdef CONFIG_DB64460 +#include "../db64460/mpsc.h" +#endif + +#include "ns16550.h" + +#ifdef CONFIG_MPSC + + +int serial_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + +#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2) + int clock_divisor = 230400 / gd->baudrate; +#endif + + mpsc_init (gd->baudrate); + + /* init the DUART chans so that KGDB in the kernel can use them */ +#ifdef CFG_INIT_CHAN1 + NS16550_reinit (COM_PORTS[0], clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + NS16550_reinit (COM_PORTS[1], clock_divisor); +#endif + 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) +{ + DECLARE_GLOBAL_DATA_PTR; + + galbrg_set_baudrate (CONFIG_MPSC_PORT, gd->baudrate); +} + +#else /* ! CONFIG_MPSC */ + +int serial_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = 230400 / gd->baudrate; + +#ifdef CFG_INIT_CHAN1 + (void) NS16550_init (0, clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + (void) NS16550_init (1, clock_divisor); +#endif + return (0); +} + +void serial_putc (const char c) +{ + if (c == '\n') + NS16550_putc (COM_PORTS[CFG_DUART_CHAN], '\r'); + + NS16550_putc (COM_PORTS[CFG_DUART_CHAN], c); +} + +int serial_getc (void) +{ + return NS16550_getc (COM_PORTS[CFG_DUART_CHAN]); +} + +int serial_tstc (void) +{ + return NS16550_tstc (COM_PORTS[CFG_DUART_CHAN]); +} + +void serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = 230400 / gd->baudrate; + +#ifdef CFG_INIT_CHAN1 + NS16550_reinit (COM_PORTS[0], clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + NS16550_reinit (COM_PORTS[1], clock_divisor); +#endif +} + +#endif /* CONFIG_MPSC */ + +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/Marvell/common/serial.h b/board/Marvell/common/serial.h new file mode 100644 index 0000000..c7fc8c1 --- /dev/null +++ b/board/Marvell/common/serial.h @@ -0,0 +1,89 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * modified for marvell db64360 eval board by + * Ingo Assmus <ingo.assmus@keymile.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* 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/Marvell/db64360/64360.h b/board/Marvell/db64360/64360.h new file mode 100644 index 0000000..a65e23b --- /dev/null +++ b/board/Marvell/db64360/64360.h @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * main board support/init for the Galileo Eval board DB64360. + */ + +#ifndef __64360_H__ +#define __64360_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 /* __64360_H__ */ diff --git a/board/Marvell/db64360/Makefile b/board/Marvell/db64360/Makefile new file mode 100644 index 0000000..768ccdd --- /dev/null +++ b/board/Marvell/db64360/Makefile @@ -0,0 +1,44 @@ +# +# (C) Copyright 2001 +# Josh Huber <huber@mclx.com>, 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 +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +SOBJS = ../common/misc.o + +OBJS = $(BOARD).o ../common/flash.o ../common/serial.o ../common/memory.o pci.o \ + mv_eth.o ../common/ns16550.o mpsc.o ../common/i2c.o \ + sdram_init.o ../common/intel_flash.o + +$(LIB): .depend $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) $(SOBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/Marvell/db64360/config.mk b/board/Marvell/db64360/config.mk new file mode 100644 index 0000000..0e42b48 --- /dev/null +++ b/board/Marvell/db64360/config.mk @@ -0,0 +1,28 @@ +# +# (C) Copyright 2001 +# Josh Huber <huber@mclx.com>, 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 +# + +# +# EVB64360 boards +# + +TEXT_BASE = 0xfff00000 diff --git a/board/Marvell/db64360/db64360.c b/board/Marvell/db64360/db64360.c new file mode 100644 index 0000000..438700a --- /dev/null +++ b/board/Marvell/db64360/db64360.c @@ -0,0 +1,936 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, 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 + */ + +/* + * db64360.c - main board support/init for the Galileo Eval board. + */ + +#include <common.h> +#include <74xx_7xx.h> +#include "../include/memory.h" +#include "../include/pci.h" +#include "../include/mv_gen_reg.h" +#include <net.h> + +#include "eth.h" +#include "mpsc.h" +#include "i2c.h" +#include "64360.h" +#include "mv_regs.h" + +#undef DEBUG +/*#define DEBUG */ + +#define MAP_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); + +/* ------------------------------------------------------------------------- */ + +/* 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_pre_init 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 */ + +/* original ppcboot 1.1.6 source + + temp = in_le32((u32 *)(new_loc + INTERNAL_SPACE_DECODE)); + if ((temp & 0xffff) == new_loc >> 20) + return; + + temp = (in_le32((u32 *)(cur_loc + INTERNAL_SPACE_DECODE)) & + 0xffff0000) | (new_loc >> 20); + + out_le32((u32 *)(cur_loc + INTERNAL_SPACE_DECODE), temp); + + while (GTREGREAD(INTERNAL_SPACE_DECODE) != temp); +original ppcboot 1.1.6 source end */ + + 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_BASE >> 16); + GT_REG_WRITE (PCI_0I_O_ADDRESS_REMAP, CFG_PCI0_IO_BASE >> 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_BASE >> 16); + GT_REG_WRITE (PCI_1I_O_ADDRESS_REMAP, CFG_PCI1_IO_BASE >> 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 MV64360 P.399 */ +#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_pre_init. + * + * set up gal. device mappings, etc. + */ +int board_pre_init (void) +{ + uchar sram_boot = 0; + + /* + * 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); + + /* No PCI in first release of Port To_do: enable it. */ +#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); + /* does not exist in MV6436x + GT_REG_WRITE(CPU_INT_0_MASK, 0); + GT_REG_WRITE(CPU_INT_1_MASK, 0); + GT_REG_WRITE(CPU_INT_2_MASK, 0); + GT_REG_WRITE(CPU_INT_3_MASK, 0); + --------------------- */ + + + /* ----- DEVICE BUS SETTINGS ------ */ + + /* + * EVB + * 0 - SRAM ???? + * 1 - RTC ???? + * 2 - UART ???? + * 3 - Flash checked 32Bit Intel Strata + * boot - BootCS checked 8Bit 29LV040B + * + * Zuma + * 0 - Flash + * boot - BootCS + */ + + /* + * the dual 7450 module requires burst access to the boot + * device, so the serial rom copies the boot device to the + * on-board sram on the eval board, and updates the correct + * registers to boot from the sram. (device0) + */ + if (memoryGetDeviceBaseAddress (DEVICE0) == CFG_DFL_BOOTCS_BASE) + sram_boot = 1; + if (!sram_boot) + memoryMapDeviceSpace (DEVICE0, CFG_DEV0_SPACE, CFG_DEV0_SIZE); + + memoryMapDeviceSpace (DEVICE1, CFG_DEV1_SPACE, CFG_DEV1_SIZE); + memoryMapDeviceSpace (DEVICE2, CFG_DEV2_SPACE, CFG_DEV2_SIZE); + memoryMapDeviceSpace (DEVICE3, CFG_DEV3_SPACE, CFG_DEV3_SIZE); + + + /* configure device timing */ +#ifdef CFG_DEV0_PAR /* set port parameters for SRAM device module access */ + if (!sram_boot) + GT_REG_WRITE (DEVICE_BANK0PARAMETERS, CFG_DEV0_PAR); +#endif + +#ifdef CFG_DEV1_PAR /* set port parameters for RTC device module access */ + GT_REG_WRITE (DEVICE_BANK1PARAMETERS, CFG_DEV1_PAR); +#endif +#ifdef CFG_DEV2_PAR /* set port parameters for DUART device module access */ + GT_REG_WRITE (DEVICE_BANK2PARAMETERS, CFG_DEV2_PAR); +#endif + +#ifdef CFG_32BIT_BOOT_PAR /* set port parameters for Flash device module access */ + /* detect if we are booting from the 32 bit flash */ + if (GTREGREAD (DEVICE_BOOT_BANK_PARAMETERS) & (0x3 << 20)) { + /* 32 bit boot flash */ + GT_REG_WRITE (DEVICE_BANK3PARAMETERS, CFG_8BIT_BOOT_PAR); + GT_REG_WRITE (DEVICE_BOOT_BANK_PARAMETERS, + CFG_32BIT_BOOT_PAR); + } else { + /* 8 bit boot flash */ + GT_REG_WRITE (DEVICE_BANK3PARAMETERS, CFG_32BIT_BOOT_PAR); + GT_REG_WRITE (DEVICE_BOOT_BANK_PARAMETERS, CFG_8BIT_BOOT_PAR); + } +#else + /* 8 bit boot flash only */ +/* GT_REG_WRITE(DEVICE_BOOT_BANK_PARAMETERS, CFG_8BIT_BOOT_PAR);*/ +#endif + + + 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); + DEBUG_LED0_ON (); + DEBUG_LED1_ON (); + DEBUG_LED2_ON (); + + return 0; +} + +/* various things to do after relocation */ + +int misc_init_r () +{ + icache_enable (); +#ifdef CFG_L2 + l2cache_enable (); +#endif +#ifdef CONFIG_MPSC + + mpsc_sdma_init (); + mpsc_init2 (); +#endif + +#if 0 + /* disable the dcache and MMU */ + dcache_lock (); +#endif + return 0; +} + +void after_reloc (ulong dest_addr, gd_t * gd) +{ + /* check to see if we booted from the sram. If so, move things + * back to the way they should be. (we're running from main + * memory at this point now */ + if (memoryGetDeviceBaseAddress (DEVICE0) == CFG_DFL_BOOTCS_BASE) { + memoryMapDeviceSpace (DEVICE0, CFG_DEV0_SPACE, CFG_DEV0_SIZE); + memoryMapDeviceSpace (BOOT_DEVICE, CFG_DFL_BOOTCS_BASE, _8M); + } + display_mem_map (); + /* now, jump to the main ppcboot 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) +{ + int l_type = 0; + + printf ("BOARD: %s\n", CFG_BOARD_NAME); + return (l_type); +} + +/* utility functions */ +void debug_led (int led, int mode) +{ + volatile int *addr = 0; + int dummy; + + if (mode == 1) { + switch (led) { + case 0: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x08000); + break; + + case 1: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x0c000); + break; + + case 2: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x10000); + break; + } + } else if (mode == 0) { + switch (led) { + case 0: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x14000); + break; + + case 1: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x18000); + break; + + case 2: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x1c000); + break; + } + } + + dummy = *addr; +} + +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); + } + } + + /* 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); + for (j = 0; + j <= + PCI_REGION0 + /*ronen currently only first PCI MEM is used 3 */ ; + j++) { + base = pciGetSpaceBase (i, j); + size = pciGetSpaceSize (i, j); + printf ("MEMORY %d: base - 0x%08x\tsize - %dM bytes\n", j, base, size >> 20); + } + } + + /* Devices */ + printf ("\nDEVICES\n"); + for (i = 0; i <= DEVICE3; i++) { + base = memoryGetDeviceBaseAddress (i); + size = memoryGetDeviceSize (i); + width = memoryGetDeviceWidth (i) * 8; + printf ("DEV %d: base - 0x%08x size - %dM bytes\twidth - %d bits", i, base, size >> 20, width); + if (i == 0) + printf ("\t- EXT SRAM (actual - 1M)\n"); + else if (i == 1) + printf ("\t- RTC\n"); + else if (i == 2) + printf ("\t- UART\n"); + else + printf ("\t- LARGE FLASH\n"); + } + + /* 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\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[] = { + 0xaaaaaaaaaaaaaaaa, + 0xcccccccccccccccc, + 0xf0f0f0f0f0f0f0f0, + 0xff00ff00ff00ff00, + 0xffff0000ffff0000, + 0xffffffff00000000, + 0x00000000ffffffff, + 0x0000ffff0000ffff, + 0x00ff00ff00ff00ff, + 0x0f0f0f0f0f0f0f0f, + 0x3333333333333333, + 0x5555555555555555 +}; + +/*********************************************************************/ +/* 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; + 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; + 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, runaddress, runwalk; + + s = getenv ("testdramdata"); + rundata = (s && (*s == 'y')) ? 1 : 0; + s = getenv ("testdramaddress"); + runaddress = (s && (*s == 'y')) ? 1 : 0; + s = getenv ("testdramwalk"); + runwalk = (s && (*s == 'y')) ? 1 : 0; + +/* rundata = 1; */ +/* runaddress = 0; */ +/* runwalk = 0; */ + + 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); + +} + +void board_prebootm_init () +{ + +/* change window size of PCI1 IO in order tp prevent overlaping with REG BASE. */ + GT_REG_WRITE (PCI_1_IO_SIZE, (_64K - 1) >> 16); + +/* Stop GigE Rx DMA engines */ + GT_REG_WRITE (MV64360_ETH_RECEIVE_QUEUE_COMMAND_REG (0), 0x0000ff00); + GT_REG_WRITE (MV64360_ETH_RECEIVE_QUEUE_COMMAND_REG (1), 0x0000ff00); +/* MV_REG_WRITE (MV64360_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0x0000ff00); */ + +/* Relocate MV64360 internal regs */ + my_remap_gt_regs_bootm (CFG_GT_REGS, BRIDGE_REG_BASE_BOOTM); + + icache_disable (); + invalidate_l1_instruction_cache (); + flush_data_cache (); + dcache_disable (); +} diff --git a/board/Marvell/db64360/eth.h b/board/Marvell/db64360/eth.h new file mode 100644 index 0000000..aab32d2 --- /dev/null +++ b/board/Marvell/db64360/eth.h @@ -0,0 +1,43 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, 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 <asm/types.h> +#include <asm/io.h> +#include <asm/byteorder.h> +#include <common.h> + + +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/Marvell/db64360/mpsc.c b/board/Marvell/db64360/mpsc.c new file mode 100644 index 0000000..ccb3adc --- /dev/null +++ b/board/Marvell/db64360/mpsc.c @@ -0,0 +1,1019 @@ +/* + * (C) Copyright 2001 + * John Clemens <clemens@mclx.com>, 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 <ingo.assmus@keymile.com> + * + ************************************************************************/ + +/* + * mpsc.c - driver for console over the MPSC. + */ + + +#include <common.h> +#include <config.h> +#include <asm/cache.h> + +#include <malloc.h> +#include "mpsc.h" + +#include "mv_regs.h" + +#include "../include/memory.h" + +/* 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_indent: Standard input:229: Warning:old style assignment ambiguity in "=&". Assuming "= &" + +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) +{ + DECLARE_GLOBAL_DATA_PTR; + 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 Bank0 */ + if (galsdma_set_mem_space (MV64360_CUNIT_BASE_ADDR_WIN_0_BIT, + MV64360_SDMA_DRAM_CS_0_TARGET, + 0, + memoryGetBankBaseAddress + (CS_0_LOW_DECODE_ADDRESS), + memoryGetBankSize (BANK0)) != true) + printf ("%s: SDMA_Window0 memory setup failed !!! \n", + __FUNCTION__); + + +/* Disable MPSC-Window1 */ + if (galsdma_set_mem_space (MV64360_CUNIT_BASE_ADDR_WIN_1_BIT, + MV64360_SDMA_DRAM_CS_0_TARGET, + 0, + memoryGetBankBaseAddress + (CS_1_LOW_DECODE_ADDRESS), + memoryGetBankSize (BANK3)) != true) + printf ("%s: SDMA_Window1 memory setup failed !!! \n", + __FUNCTION__); + + +/* Disable MPSC-Window2 */ + if (galsdma_set_mem_space (MV64360_CUNIT_BASE_ADDR_WIN_2_BIT, + MV64360_SDMA_DRAM_CS_0_TARGET, + 0, + memoryGetBankBaseAddress + (CS_2_LOW_DECODE_ADDRESS), + memoryGetBankSize (BANK3)) != true) + printf ("%s: SDMA_Window2 memory setup failed !!! \n", + __FUNCTION__); + + +/* Disable MPSC-Window3 */ + if (galsdma_set_mem_space (MV64360_CUNIT_BASE_ADDR_WIN_3_BIT, + MV64360_SDMA_DRAM_CS_0_TARGET, + 0, + memoryGetBankBaseAddress + (CS_3_LOW_DECODE_ADDRESS), + memoryGetBankSize (BANK3)) != 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, + (MV64360_SDMA_WIN_ACCESS_FULL << + (MV64360_CUNIT_BASE_ADDR_WIN_0_BIT * 2))); + +/* Setup MPSC1 access mode Window1 full access */ + GT_SET_REG_BITS (MPSC1_ACCESS_PROTECTION_REG, + (MV64360_SDMA_WIN_ACCESS_FULL << + (MV64360_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) +{ + DECLARE_GLOBAL_DATA_PTR; + 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 MV64360 IDMA memory decoding map. +* +* DESCRIPTION: +* the MV64360 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 (MV64360_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 (MV64360_CUNIT_BASE_ADDR_REG0 + memSpace * 8, + (baseAddress | memSpaceTarget | memSpaceAttr)); + GT_REG_WRITE ((MV64360_CUNIT_SIZE0 + memSpace * 8), + (size - 1) & 0xffff0000); + GT_RESET_REG_BITS (MV64360_CUNIT_BASE_ADDR_ENABLE_REG, + 1 << memSpace); + } else { + /* An invalid size was specified */ + return false; + } + return true; +} diff --git a/board/Marvell/db64360/mpsc.h b/board/Marvell/db64360/mpsc.h new file mode 100644 index 0000000..f95f8c0 --- /dev/null +++ b/board/Marvell/db64360/mpsc.h @@ -0,0 +1,156 @@ +/* + * (C) Copyright 2001 + * John Clemens <clemens@mclx.com>, 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 <ingo.assmus@keymile.com> + * + ************************************************************************/ + + +/* + * mpsc.h - header file for MPSC in uart mode (console driver) + */ + +#ifndef __MPSC_H__ +#define __MPSC_H__ + +/* include actual Galileo defines */ +#include "../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/Marvell/db64360/mv_eth.c b/board/Marvell/db64360/mv_eth.c new file mode 100644 index 0000000..e2719b9 --- /dev/null +++ b/board/Marvell/db64360/mv_eth.c @@ -0,0 +1,3182 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * based on - Driver for MV64360X 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.c - header file for the polled mode GT ethernet driver + */ +#include <common.h> +#include <net.h> +#include <malloc.h> + +#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 + +#undef MV64360_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 MV64360_RX_QUEUE_FILL_ON_TASK + + +/* Constants */ +#define MAGIC_ETH_RUNNING 8031971 +#define MV64360_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 MV64360_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 MV64360 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))) + +/* Static function declarations */ +static int mv64360_eth_real_open (struct eth_device *eth); +static int mv64360_eth_real_stop (struct eth_device *eth); +static struct net_device_stats *mv64360_eth_get_stats (struct eth_device + *dev); +static void eth_port_init_mac_tables (ETH_PORT eth_port_num); +static void mv64360_eth_update_stat (struct eth_device *dev); +bool db64360_eth_start (struct eth_device *eth); +unsigned int eth_read_mib_counter (ETH_PORT eth_port_num, + unsigned int mib_offset); +int mv64360_eth_receive (struct eth_device *dev); + +int mv64360_eth_xmit (struct eth_device *, volatile void *packet, int length); + +#ifndef UPDATE_STATS_BY_SOFTWARE +static void mv64360_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; + +/************************************************* + *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 mv64360_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], MV64360_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], MV64360_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], + (MV64360_RX_QUEUE_SIZE * MV64360_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], + (MV64360_TX_QUEUE_SIZE * MV64360_TX_BUFFER_SIZE) + 32); +} +#endif + +#define my_cpu_to_le32(x) my_le32_to_cpu((x)) + +unsigned long my_le32_to_cpu (unsigned long x) +{ + return (((x & 0x000000ffU) << 24) | + ((x & 0x0000ff00U) << 8) | + ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24)); +} + + +/********************************************************************** + * mv64360_eth_print_phy_status + * + * Prints gigabit ethenret phy status + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + **********************************************************************/ + +static void mv64360_eth_print_phy_status (struct eth_device *dev) +{ + struct mv64360_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 mv64360_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 (MV64360_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 mv64360_eth + * + **********************************************************************/ +int db64360_eth_probe (struct eth_device *dev) +{ + return ((int) db64360_eth_start (dev)); +} + +int db64360_eth_poll (struct eth_device *dev) +{ + return mv64360_eth_receive (dev); +} + +int db64360_eth_transmit (struct eth_device *dev, volatile void *packet, + int length) +{ + mv64360_eth_xmit (dev, packet, length); + return 0; +} + +void db64360_eth_disable (struct eth_device *dev) +{ + mv64360_eth_stop (dev); +} + + +void mv6436x_eth_initialize (bd_t * bis) +{ + struct eth_device *dev; + ETH_PORT_INFO *ethernet_private; + struct mv64360_eth_priv *port_private; + int devnum, x, temp; + char *s, *e, buf[64]; + + 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 *) db64360_eth_probe; + dev->halt = (void *) ethernet_phy_reset; + dev->send = (void *) db64360_eth_transmit; + dev->recv = (void *) db64360_eth_poll; + + dev->priv = (void *) ethernet_private = + calloc (sizeof (*ethernet_private), 1); + 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... */ + ethernet_private->port_private = (void *) port_private = + calloc (sizeof (*ethernet_private), 1); + 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 mv64360_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 + */ + mv64360_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 * + MV64360_RX_QUEUE_SIZE + 1); + ethernet_private->p_tx_desc_area_base[0] = + (ETH_TX_DESC *) memalign (16, + TX_DESC_ALIGNED_SIZE * + MV64360_TX_QUEUE_SIZE + 1); + + ethernet_private->p_rx_buffer_base[0] = + (char *) memalign (16, + MV64360_RX_QUEUE_SIZE * + MV64360_TX_BUFFER_SIZE + 1); + ethernet_private->p_tx_buffer_base[0] = + (char *) memalign (16, + MV64360_RX_QUEUE_SIZE * + MV64360_TX_BUFFER_SIZE + 1); + +#ifdef DEBUG_MV_ETH + /* DEBUG OUTPUT prints adresses of globals */ + print_globals (dev); +#endif + eth_register (dev); + + } + DP (printf ("%s: exit\n", __FUNCTION__)); + +} + +/********************************************************************** + * mv64360_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 mv64360_eth_open (struct eth_device *dev) +{ + return (mv64360_eth_real_open (dev)); +} + +/* Helper function for mv64360_eth_open */ +static int mv64360_eth_real_open (struct eth_device *dev) +{ + + unsigned int queue; + ETH_PORT_INFO *ethernet_private; + struct mv64360_eth_priv *port_private; + unsigned int port_num; + u32 port_status, phy_reg_data; + + 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 mv64360_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Stop RX Queues */ + MV_REG_WRITE (MV64360_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num), + 0x0000ff00); + + /* Clear the ethernet port interrupts */ + MV_REG_WRITE (MV64360_ETH_INTERRUPT_CAUSE_REG (port_num), 0); + MV_REG_WRITE (MV64360_ETH_INTERRUPT_CAUSE_EXTEND_REG (port_num), 0); + + /* Unmask RX buffer and TX end interrupt */ + MV_REG_WRITE (MV64360_ETH_INTERRUPT_MASK_REG (port_num), + INT_CAUSE_UNMASK_ALL); + + /* Unmask phy and link status changes interrupts */ + MV_REG_WRITE (MV64360_ETH_INTERRUPT_EXTEND_MASK_REG (port_num), + INT_CAUSE_UNMASK_ALL_EXT); + + /* Set phy address of the port */ + ethernet_private->port_phy_addr = 0x8 + port_num; + + /* Activate the DMA channels etc */ + eth_port_init (ethernet_private); + + + /* "Allocate" setup TX rings */ + + for (queue = 0; queue < MV64360_TX_QUEUE_NUM; queue++) { + unsigned int size; + + port_private->tx_ring_size[queue] = MV64360_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], + MV64360_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 < MV64360_RX_QUEUE_NUM; queue++) { + unsigned int size; + + /* Meantime RX Ring are fixed - but must be configurable by user */ + port_private->rx_ring_size[queue] = MV64360_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], + MV64360_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 (MV64360_ETH_PORT_SERIAL_CONTROL_REG (port_num), + (0x5 << 17) | + (MV_REG_READ + (MV64360_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 (MV64360_ETH_MAXIMUM_TRANSMIT_UNIT (port_num), 0); + port_status = MV_REG_READ (MV64360_ETH_PORT_STATUS_REG (port_num)); + + /* Check Link status on phy */ + eth_port_read_smi_reg (port_num, 1, &phy_reg_data); + if (!(phy_reg_data & 0x20)) { + /* Reset PHY */ + if ((ethernet_phy_reset (port_num)) != true) { + printf ("$$ Warnning: No link on port %d \n", + port_num); + return 0; + } else { + eth_port_read_smi_reg (port_num, 1, &phy_reg_data); + if (!(phy_reg_data & 0x20)) { + printf ("### Error: Phy is not active\n"); + return 0; + } + } + } else { + mv64360_eth_print_phy_status (dev); + } + port_private->eth_running = MAGIC_ETH_RUNNING; + return 1; +} + + +static int mv64360_eth_free_tx_rings (struct eth_device *dev) +{ + unsigned int queue; + ETH_PORT_INFO *ethernet_private; + struct mv64360_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 mv64360_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Stop Tx Queues */ + MV_REG_WRITE (MV64360_ETH_TRANSMIT_QUEUE_COMMAND_REG (port_num), + 0x0000ff00); + + /* Free TX rings */ + DP (printf ("Clearing previously allocated TX queues... ")); + for (queue = 0; queue < MV64360_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 mv64360_eth_free_rx_rings (struct eth_device *dev) +{ + unsigned int queue; + ETH_PORT_INFO *ethernet_private; + struct mv64360_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 mv64360_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + + /* Stop RX Queues */ + MV_REG_WRITE (MV64360_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num), + 0x0000ff00); + + /* Free RX rings */ + DP (printf ("Clearing previously allocated RX queues... ")); + for (queue = 0; queue < MV64360_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; +} + +/********************************************************************** + * mv64360_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 mv64360_eth_stop (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64360_eth_priv *port_private; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64360_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Disable all gigE address decoder */ + MV_REG_WRITE (MV64360_ETH_BASE_ADDR_ENABLE_REG, 0x3f); + DP (printf ("%s Ethernet stop called ... \n", __FUNCTION__)); + mv64360_eth_real_stop (dev); + + return 0; +}; + +/* Helper function for mv64360_eth_stop */ + +static int mv64360_eth_real_stop (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64360_eth_priv *port_private; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64360_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + + mv64360_eth_free_tx_rings (dev); + mv64360_eth_free_rx_rings (dev); + + eth_port_reset (ethernet_private->port_num); + /* Disable ethernet port interrupts */ + MV_REG_WRITE (MV64360_ETH_INTERRUPT_CAUSE_REG (port_num), 0); + MV_REG_WRITE (MV64360_ETH_INTERRUPT_CAUSE_EXTEND_REG (port_num), 0); + /* Mask RX buffer and TX end interrupt */ + MV_REG_WRITE (MV64360_ETH_INTERRUPT_MASK_REG (port_num), 0); + /* Mask phy and link status changes interrupts */ + MV_REG_WRITE (MV64360_ETH_INTERRUPT_EXTEND_MASK_REG (port_num), 0); + MV_RESET_REG_BITS (MV64360_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; + mv64360_eth_print_stat (dev); + } + memset (port_private->stats, 0, sizeof (struct net_device_stats)); +#endif + DP (printf ("\nEthernet stopped ... \n")); + return 0; +} + + +/********************************************************************** + * mv64360_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 mv64360_eth_xmit (struct eth_device *dev, volatile void *dataPtr, + int dataSize) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64360_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 mv64360_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; + + 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 */ +} + +/********************************************************************** + * mv64360_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 mv64360_eth_receive (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64360_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 mv64360_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); + } +#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")); + } + +/* **************************************************************** */ + + } + } + mv64360_eth_get_stats (dev); /* update statistics */ + return 1; +} + +/********************************************************************** + * mv64360_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 *mv64360_eth_get_stats (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64360_eth_priv *port_private; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64360_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + mv64360_eth_update_stat (dev); + + return port_private->stats; +} + + +/********************************************************************** + * mv64360_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 mv64360_eth_update_stat (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64360_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 mv64360_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 +/********************************************************************** + * mv64360_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 mv64360_eth_print_stat (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64360_eth_priv *port_private; + struct net_device_stats *stats; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64360_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 db64360_eth_start (struct eth_device *dev) +{ + return (mv64360_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/EVB64360/mv64360_eth.c - Driver for MV64360X 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(MV64360_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), (1 << tx_queue)) + +#define ETH_DISABLE_TX_QUEUE(tx_queue, eth_port) \ + MV_REG_WRITE(MV64360_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port),\ + (1 << (8 + tx_queue))) + +#define ETH_ENABLE_RX_QUEUE(rx_queue, eth_port) \ +MV_REG_WRITE(MV64360_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port), (1 << rx_queue)) + +#define ETH_DISABLE_RX_QUEUE(rx_queue, eth_port) \ +MV_REG_WRITE(MV64360_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 (MV64360_BASE_ADDR_ENABLE); + + if (enable & (1 << bank)) + return 0; + if (bank == BANK0) + result = MV_REG_READ (MV64360_CS_0_BASE_ADDR); + if (bank == BANK1) + result = MV_REG_READ (MV64360_CS_1_BASE_ADDR); + if (bank == BANK2) + result = MV_REG_READ (MV64360_CS_2_BASE_ADDR); + if (bank == BANK3) + result = MV_REG_READ (MV64360_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 (MV64360_BASE_ADDR_ENABLE); + + if (enable & (1 << bank)) + return 0; + if (bank == BANK0) + result = MV_REG_READ (MV64360_CS_0_SIZE); + if (bank == BANK1) + result = MV_REG_READ (MV64360_CS_1_SIZE); + if (bank == BANK2) + result = MV_REG_READ (MV64360_CS_2_SIZE); + if (bank == BANK3) + result = MV_REG_READ (MV64360_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 (MV64360_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 = MV64360_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 ((MV64360_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 ((MV64360_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 (MV64360_ETH_PORT_CONFIG_REG (eth_port_num), + p_eth_port_ctrl->port_config); + + MV_REG_WRITE (MV64360_ETH_PORT_CONFIG_EXTEND_REG (eth_port_num), + p_eth_port_ctrl->port_config_extend); + + MV_REG_WRITE (MV64360_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num), + p_eth_port_ctrl->port_serial_control); + + MV_SET_REG_BITS (MV64360_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num), + ETH_SERIAL_PORT_ENABLE); + + /* Assign port SDMA configuration */ + MV_REG_WRITE (MV64360_ETH_SDMA_CONFIG_REG (eth_port_num), + p_eth_port_ctrl->port_sdma_config); + + MV_REG_WRITE (MV64360_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT + (eth_port_num), 0x3fffffff); + MV_REG_WRITE (MV64360_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG + (eth_port_num), 0x03fffcff); + /* Turn off the port/queue bandwidth limitation */ + MV_REG_WRITE (MV64360_ETH_MAXIMUM_TRANSMIT_UNIT (eth_port_num), 0x0); + + /* Enable port Rx. */ + MV_REG_WRITE (MV64360_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 (MV64360_ETH_MAC_ADDR_LOW (eth_port_num), mac_l); + MV_REG_WRITE (MV64360_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 ((MV64360_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset)); + + unicast_reg &= (0x0E << (8 * reg_offset)); + + MV_REG_WRITE ((MV64360_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 ((MV64360_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset)); + + unicast_reg |= ((0x01 | queue) << (8 * reg_offset)); + + MV_REG_WRITE ((MV64360_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 ((MV64360_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + smc_table_reg &= (0x0E << (8 * reg_offset)); + + MV_REG_WRITE ((MV64360_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 ((MV64360_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + smc_table_reg |= ((0x01 | queue) << (8 * reg_offset)); + + MV_REG_WRITE ((MV64360_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 ((MV64360_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + omc_table_reg &= (0x0E << (8 * reg_offset)); + + MV_REG_WRITE ((MV64360_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 ((MV64360_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + omc_table_reg |= ((0x01 | queue) << (8 * reg_offset)); + + MV_REG_WRITE ((MV64360_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 ((MV64360_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 ((MV64360_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + table_index), 0); + /* Clear DA filter other multicast table (Ex_dFOMT) */ + MV_REG_WRITE ((MV64360_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 ((MV64360_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 (MV64360_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 (MV64360_ETH_PHY_ADDR_REG); + + reg_data &= ~(0x1F << (5 * eth_port_num)); + reg_data |= (phy_addr << (5 * eth_port_num)); + + MV_REG_WRITE (MV64360_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 (MV64360_ETH_PHY_ADDR_REG); + + return ((reg_data >> (5 * eth_port_num)) & 0x1f); +} + +/******************************************************************************* + * 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; + + /* 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 (MV64360_ETH_TRANSMIT_QUEUE_COMMAND_REG + (eth_port_num)); + + if (reg_data & 0xFF) { + /* Issue stop command for active channels only */ + MV_REG_WRITE (MV64360_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 + (MV64360_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 (MV64360_ETH_RECEIVE_QUEUE_COMMAND_REG + (eth_port_num)); + + if (reg_data & 0xFF) { + /* Issue stop command for active channels only */ + MV_REG_WRITE (MV64360_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 + (MV64360_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 (MV64360_ETH_PORT_SERIAL_CONTROL_REG + (eth_port_num)); + reg_data &= ~ETH_SERIAL_PORT_ENABLE; + MV_REG_WRITE (MV64360_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 (MV64360_ETH_PORT_CONFIG_REG (eth_port_num)); + eth_config_reg |= value; + MV_REG_WRITE (MV64360_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 (MV64360_ETH_PORT_CONFIG_EXTEND_REG + (eth_port_num)); + eth_config_reg &= ~value; + MV_REG_WRITE (MV64360_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 (MV64360_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); +/* printf(" Phy-Port %d has addess %d \n",eth_port_num, phy_addr );*/ + + /* first check that it is not busy */ + do { + reg_value = MV_REG_READ (MV64360_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while (reg_value & ETH_SMI_BUSY); + + /* not busy */ + + MV_REG_WRITE (MV64360_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 (MV64360_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 (MV64360_ETH_SMI_REG); + + *value = reg_value & 0xffff; + + return true; +} + +/******************************************************************************* + * 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 (MV64360_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while (reg_value & ETH_SMI_BUSY); + + /* not busy */ + MV_REG_WRITE (MV64360_ETH_SMI_REG, + (phy_addr << 16) | (phy_reg << 21) | + ETH_SMI_OPCODE_WRITE | (value & 0xffff)); + return true; +} + +/******************************************************************************* + * 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 (MV64360_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 (MV64360_ETH_ACCESS_PROTECTION_REG (eth_port_num), + access_prot_reg); + + /* Set window Size reg (SR) */ + MV_REG_WRITE ((MV64360_ETH_SIZE_REG_0 + + (ETH_SIZE_REG_GAP * param->win)), + (((param->size / 0x10000) - 1) << 16)); + + /* Set window Base address reg (BA) */ + MV_REG_WRITE ((MV64360_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 ((MV64360_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 (MV64360_ETH_BASE_ADDR_ENABLE_REG, + (1 << param->win)); + else + MV_SET_REG_BITS (MV64360_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 = MV64360_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 (MV64360_ETH_SDMA_CONFIG_REG (eth_port_num), + ((coal & 0x3fff) << 8) | + (MV_REG_READ + (MV64360_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 (MV64360_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/Marvell/db64360/mv_eth.h b/board/Marvell/db64360/mv_eth.h new file mode 100644 index 0000000..943d30b --- /dev/null +++ b/board/Marvell/db64360/mv_eth.h @@ -0,0 +1,844 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * based on - Driver for MV64360X 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 __DB64360_ETH_H__ +#define __DB64360_ETH_H__ + +#include <asm/types.h> +#include <asm/io.h> +#include <asm/byteorder.h> +#include <common.h> +#include <net.h> +#include "mv_regs.h" +#include "../common/ppc_error_no.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 MV64360_TX_QUEUE_NUM 1 +#define MV64360_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_MV64360_ETH_TXQUEUE_SIZE +#define MV64360_TX_QUEUE_SIZE CONFIG_MV64360_ETH_TXQUEUE_SIZE +#else +#define MV64360_TX_QUEUE_SIZE 4 +#endif + +/* Default RX ring size is 4 descriptors */ +#ifdef CONFIG_MV64360_ETH_RXQUEUE_SIZE +#define MV64360_RX_QUEUE_SIZE CONFIG_MV64360_ETH_RXQUEUE_SIZE +#else +#define MV64360_RX_QUEUE_SIZE 4 +#endif + +#ifdef CONFIG_RX_BUFFER_SIZE +#define MV64360_RX_BUFFER_SIZE CONFIG_RX_BUFFER_SIZE +#else +#define MV64360_RX_BUFFER_SIZE 1600 +#endif + +#ifdef CONFIG_TX_BUFFER_SIZE +#define MV64360_TX_BUFFER_SIZE CONFIG_TX_BUFFER_SIZE +#else +#define MV64360_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 mv64360_eth_priv { + unsigned int port_num; + struct net_device_stats *stats; + +/* to buffer area aligned */ + char * p_eth_tx_buffer[MV64360_TX_QUEUE_SIZE+1]; /*pointers to alligned tx buffs in memory space */ + char * p_eth_rx_buffer[MV64360_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 mv64360_eth_init (struct eth_device *dev); +int mv64360_eth_stop (struct eth_device *dev); +int mv64360_eth_start_xmit (struct eth_device*, volatile void* packet, int length); +/* return db64360_eth0_poll(); */ + +int mv64360_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_MV64360_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 /* MV64360_ETH_ */ diff --git a/board/Marvell/db64360/mv_regs.h b/board/Marvell/db64360/mv_regs.h new file mode 100644 index 0000000..0d6370b --- /dev/null +++ b/board/Marvell/db64360/mv_regs.h @@ -0,0 +1,1124 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * based on - Driver for MV64360X 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 + */ + +/******************************************************************************** +* gt64360r.h - GT-64360 Internal registers definition file. +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv_regsh +#define __INCmv_regsh + +#define MV64360 + +/* Supported by the Atlantis */ +#define MV64360_INCLUDE_PCI_1 +#define MV64360_INCLUDE_PCI_0_ARBITER +#define MV64360_INCLUDE_PCI_1_ARBITER +#define MV64360_INCLUDE_SNOOP_SUPPORT +#define MV64360_INCLUDE_P2P +#define MV64360_INCLUDE_ETH_PORT_2 +#define MV64360_INCLUDE_CPU_MAPPING +#define MV64360_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 MV64360_CS_0_BASE_ADDR 0x008 +#define MV64360_CS_0_SIZE 0x010 +#define MV64360_CS_1_BASE_ADDR 0x208 +#define MV64360_CS_1_SIZE 0x210 +#define MV64360_CS_2_BASE_ADDR 0x018 +#define MV64360_CS_2_SIZE 0x020 +#define MV64360_CS_3_BASE_ADDR 0x218 +#define MV64360_CS_3_SIZE 0x220 + +/* Devices BAR and size registers */ + +#define MV64360_DEV_CS0_BASE_ADDR 0x028 +#define MV64360_DEV_CS0_SIZE 0x030 +#define MV64360_DEV_CS1_BASE_ADDR 0x228 +#define MV64360_DEV_CS1_SIZE 0x230 +#define MV64360_DEV_CS2_BASE_ADDR 0x248 +#define MV64360_DEV_CS2_SIZE 0x250 +#define MV64360_DEV_CS3_BASE_ADDR 0x038 +#define MV64360_DEV_CS3_SIZE 0x040 +#define MV64360_BOOTCS_BASE_ADDR 0x238 +#define MV64360_BOOTCS_SIZE 0x240 + +/* PCI 0 BAR and size registers */ + +#define MV64360_PCI_0_IO_BASE_ADDR 0x048 +#define MV64360_PCI_0_IO_SIZE 0x050 +#define MV64360_PCI_0_MEMORY0_BASE_ADDR 0x058 +#define MV64360_PCI_0_MEMORY0_SIZE 0x060 +#define MV64360_PCI_0_MEMORY1_BASE_ADDR 0x080 +#define MV64360_PCI_0_MEMORY1_SIZE 0x088 +#define MV64360_PCI_0_MEMORY2_BASE_ADDR 0x258 +#define MV64360_PCI_0_MEMORY2_SIZE 0x260 +#define MV64360_PCI_0_MEMORY3_BASE_ADDR 0x280 +#define MV64360_PCI_0_MEMORY3_SIZE 0x288 + +/* PCI 1 BAR and size registers */ +#define MV64360_PCI_1_IO_BASE_ADDR 0x090 +#define MV64360_PCI_1_IO_SIZE 0x098 +#define MV64360_PCI_1_MEMORY0_BASE_ADDR 0x0a0 +#define MV64360_PCI_1_MEMORY0_SIZE 0x0a8 +#define MV64360_PCI_1_MEMORY1_BASE_ADDR 0x0b0 +#define MV64360_PCI_1_MEMORY1_SIZE 0x0b8 +#define MV64360_PCI_1_MEMORY2_BASE_ADDR 0x2a0 +#define MV64360_PCI_1_MEMORY2_SIZE 0x2a8 +#define MV64360_PCI_1_MEMORY3_BASE_ADDR 0x2b0 +#define MV64360_PCI_1_MEMORY3_SIZE 0x2b8 + +/* SRAM base address */ +#define MV64360_INTEGRATED_SRAM_BASE_ADDR 0x268 + +/* internal registers space base address */ +#define MV64360_INTERNAL_SPACE_BASE_ADDR 0x068 + +/* Enables the CS , DEV_CS , PCI 0 and PCI 1 + windows above */ +#define MV64360_BASE_ADDR_ENABLE 0x278 + +/****************************************/ +/* PCI remap registers */ +/****************************************/ + /* PCI 0 */ +#define MV64360_PCI_0_IO_ADDR_REMAP 0x0f0 +#define MV64360_PCI_0_MEMORY0_LOW_ADDR_REMAP 0x0f8 +#define MV64360_PCI_0_MEMORY0_HIGH_ADDR_REMAP 0x320 +#define MV64360_PCI_0_MEMORY1_LOW_ADDR_REMAP 0x100 +#define MV64360_PCI_0_MEMORY1_HIGH_ADDR_REMAP 0x328 +#define MV64360_PCI_0_MEMORY2_LOW_ADDR_REMAP 0x2f8 +#define MV64360_PCI_0_MEMORY2_HIGH_ADDR_REMAP 0x330 +#define MV64360_PCI_0_MEMORY3_LOW_ADDR_REMAP 0x300 +#define MV64360_PCI_0_MEMORY3_HIGH_ADDR_REMAP 0x338 + /* PCI 1 */ +#define MV64360_PCI_1_IO_ADDR_REMAP 0x108 +#define MV64360_PCI_1_MEMORY0_LOW_ADDR_REMAP 0x110 +#define MV64360_PCI_1_MEMORY0_HIGH_ADDR_REMAP 0x340 +#define MV64360_PCI_1_MEMORY1_LOW_ADDR_REMAP 0x118 +#define MV64360_PCI_1_MEMORY1_HIGH_ADDR_REMAP 0x348 +#define MV64360_PCI_1_MEMORY2_LOW_ADDR_REMAP 0x310 +#define MV64360_PCI_1_MEMORY2_HIGH_ADDR_REMAP 0x350 +#define MV64360_PCI_1_MEMORY3_LOW_ADDR_REMAP 0x318 +#define MV64360_PCI_1_MEMORY3_HIGH_ADDR_REMAP 0x358 + +#define MV64360_CPU_PCI_0_HEADERS_RETARGET_CONTROL 0x3b0 +#define MV64360_CPU_PCI_0_HEADERS_RETARGET_BASE 0x3b8 +#define MV64360_CPU_PCI_1_HEADERS_RETARGET_CONTROL 0x3c0 +#define MV64360_CPU_PCI_1_HEADERS_RETARGET_BASE 0x3c8 +#define MV64360_CPU_GE_HEADERS_RETARGET_CONTROL 0x3d0 +#define MV64360_CPU_GE_HEADERS_RETARGET_BASE 0x3d8 +#define MV64360_CPU_IDMA_HEADERS_RETARGET_CONTROL 0x3e0 +#define MV64360_CPU_IDMA_HEADERS_RETARGET_BASE 0x3e8 + +/****************************************/ +/* CPU Control Registers */ +/****************************************/ + +#define MV64360_CPU_CONFIG 0x000 +#define MV64360_CPU_MODE 0x120 +#define MV64360_CPU_MASTER_CONTROL 0x160 +#define MV64360_CPU_CROSS_BAR_CONTROL_LOW 0x150 +#define MV64360_CPU_CROSS_BAR_CONTROL_HIGH 0x158 +#define MV64360_CPU_CROSS_BAR_TIMEOUT 0x168 + +/****************************************/ +/* SMP RegisterS */ +/****************************************/ + +#define MV64360_SMP_WHO_AM_I 0x200 +#define MV64360_SMP_CPU0_DOORBELL 0x214 +#define MV64360_SMP_CPU0_DOORBELL_CLEAR 0x21C +#define MV64360_SMP_CPU1_DOORBELL 0x224 +#define MV64360_SMP_CPU1_DOORBELL_CLEAR 0x22C +#define MV64360_SMP_CPU0_DOORBELL_MASK 0x234 +#define MV64360_SMP_CPU1_DOORBELL_MASK 0x23C +#define MV64360_SMP_SEMAPHOR0 0x244 +#define MV64360_SMP_SEMAPHOR1 0x24c +#define MV64360_SMP_SEMAPHOR2 0x254 +#define MV64360_SMP_SEMAPHOR3 0x25c +#define MV64360_SMP_SEMAPHOR4 0x264 +#define MV64360_SMP_SEMAPHOR5 0x26c +#define MV64360_SMP_SEMAPHOR6 0x274 +#define MV64360_SMP_SEMAPHOR7 0x27c + +/****************************************/ +/* CPU Sync Barrier Register */ +/****************************************/ + +#define MV64360_CPU_0_SYNC_BARRIER_TRIGGER 0x0c0 +#define MV64360_CPU_0_SYNC_BARRIER_VIRTUAL 0x0c8 +#define MV64360_CPU_1_SYNC_BARRIER_TRIGGER 0x0d0 +#define MV64360_CPU_1_SYNC_BARRIER_VIRTUAL 0x0d8 + +/****************************************/ +/* CPU Access Protect */ +/****************************************/ + +#define MV64360_CPU_PROTECT_WINDOW_0_BASE_ADDR 0x180 +#define MV64360_CPU_PROTECT_WINDOW_0_SIZE 0x188 +#define MV64360_CPU_PROTECT_WINDOW_1_BASE_ADDR 0x190 +#define MV64360_CPU_PROTECT_WINDOW_1_SIZE 0x198 +#define MV64360_CPU_PROTECT_WINDOW_2_BASE_ADDR 0x1a0 +#define MV64360_CPU_PROTECT_WINDOW_2_SIZE 0x1a8 +#define MV64360_CPU_PROTECT_WINDOW_3_BASE_ADDR 0x1b0 +#define MV64360_CPU_PROTECT_WINDOW_3_SIZE 0x1b8 + + +/****************************************/ +/* CPU Error Report */ +/****************************************/ + +#define MV64360_CPU_ERROR_ADDR_LOW 0x070 +#define MV64360_CPU_ERROR_ADDR_HIGH 0x078 +#define MV64360_CPU_ERROR_DATA_LOW 0x128 +#define MV64360_CPU_ERROR_DATA_HIGH 0x130 +#define MV64360_CPU_ERROR_PARITY 0x138 +#define MV64360_CPU_ERROR_CAUSE 0x140 +#define MV64360_CPU_ERROR_MASK 0x148 + +/****************************************/ +/* CPU Interface Debug Registers */ +/****************************************/ + +#define MV64360_PUNIT_SLAVE_DEBUG_LOW 0x360 +#define MV64360_PUNIT_SLAVE_DEBUG_HIGH 0x368 +#define MV64360_PUNIT_MASTER_DEBUG_LOW 0x370 +#define MV64360_PUNIT_MASTER_DEBUG_HIGH 0x378 +#define MV64360_PUNIT_MMASK 0x3e4 + +/****************************************/ +/* Integrated SRAM Registers */ +/****************************************/ + +#define MV64360_SRAM_CONFIG 0x380 +#define MV64360_SRAM_TEST_MODE 0X3F4 +#define MV64360_SRAM_ERROR_CAUSE 0x388 +#define MV64360_SRAM_ERROR_ADDR 0x390 +#define MV64360_SRAM_ERROR_ADDR_HIGH 0X3F8 +#define MV64360_SRAM_ERROR_DATA_LOW 0x398 +#define MV64360_SRAM_ERROR_DATA_HIGH 0x3a0 +#define MV64360_SRAM_ERROR_DATA_PARITY 0x3a8 + +/****************************************/ +/* SDRAM Configuration */ +/****************************************/ + +#define MV64360_SDRAM_CONFIG 0x1400 +#define MV64360_D_UNIT_CONTROL_LOW 0x1404 +#define MV64360_D_UNIT_CONTROL_HIGH 0x1424 +#define MV64360_SDRAM_TIMING_CONTROL_LOW 0x1408 +#define MV64360_SDRAM_TIMING_CONTROL_HIGH 0x140c +#define MV64360_SDRAM_ADDR_CONTROL 0x1410 +#define MV64360_SDRAM_OPEN_PAGES_CONTROL 0x1414 +#define MV64360_SDRAM_OPERATION 0x1418 +#define MV64360_SDRAM_MODE 0x141c +#define MV64360_EXTENDED_DRAM_MODE 0x1420 +#define MV64360_SDRAM_CROSS_BAR_CONTROL_LOW 0x1430 +#define MV64360_SDRAM_CROSS_BAR_CONTROL_HIGH 0x1434 +#define MV64360_SDRAM_CROSS_BAR_TIMEOUT 0x1438 +#define MV64360_SDRAM_ADDR_CTRL_PADS_CALIBRATION 0x14c0 +#define MV64360_SDRAM_DATA_PADS_CALIBRATION 0x14c4 + +/****************************************/ +/* SDRAM Error Report */ +/****************************************/ + +#define MV64360_SDRAM_ERROR_DATA_LOW 0x1444 +#define MV64360_SDRAM_ERROR_DATA_HIGH 0x1440 +#define MV64360_SDRAM_ERROR_ADDR 0x1450 +#define MV64360_SDRAM_RECEIVED_ECC 0x1448 +#define MV64360_SDRAM_CALCULATED_ECC 0x144c +#define MV64360_SDRAM_ECC_CONTROL 0x1454 +#define MV64360_SDRAM_ECC_ERROR_COUNTER 0x1458 + +/******************************************/ +/* Controlled Delay Line (CDL) Registers */ +/******************************************/ + +#define MV64360_DFCDL_CONFIG0 0x1480 +#define MV64360_DFCDL_CONFIG1 0x1484 +#define MV64360_DLL_WRITE 0x1488 +#define MV64360_DLL_READ 0x148c +#define MV64360_SRAM_ADDR 0x1490 +#define MV64360_SRAM_DATA0 0x1494 +#define MV64360_SRAM_DATA1 0x1498 +#define MV64360_SRAM_DATA2 0x149c +#define MV64360_DFCL_PROBE 0x14a0 + +/******************************************/ +/* Debug Registers */ +/******************************************/ + +#define MV64360_DUNIT_DEBUG_LOW 0x1460 +#define MV64360_DUNIT_DEBUG_HIGH 0x1464 +#define MV64360_DUNIT_MMASK 0X1b40 + +/****************************************/ +/* Device Parameters */ +/****************************************/ + +#define MV64360_DEVICE_BANK0_PARAMETERS 0x45c +#define MV64360_DEVICE_BANK1_PARAMETERS 0x460 +#define MV64360_DEVICE_BANK2_PARAMETERS 0x464 +#define MV64360_DEVICE_BANK3_PARAMETERS 0x468 +#define MV64360_DEVICE_BOOT_BANK_PARAMETERS 0x46c +#define MV64360_DEVICE_INTERFACE_CONTROL 0x4c0 +#define MV64360_DEVICE_INTERFACE_CROSS_BAR_CONTROL_LOW 0x4c8 +#define MV64360_DEVICE_INTERFACE_CROSS_BAR_CONTROL_HIGH 0x4cc +#define MV64360_DEVICE_INTERFACE_CROSS_BAR_TIMEOUT 0x4c4 + +/****************************************/ +/* Device interrupt registers */ +/****************************************/ + +#define MV64360_DEVICE_INTERRUPT_CAUSE 0x4d0 +#define MV64360_DEVICE_INTERRUPT_MASK 0x4d4 +#define MV64360_DEVICE_ERROR_ADDR 0x4d8 +#define MV64360_DEVICE_ERROR_DATA 0x4dc +#define MV64360_DEVICE_ERROR_PARITY 0x4e0 + +/****************************************/ +/* Device debug registers */ +/****************************************/ + +#define MV64360_DEVICE_DEBUG_LOW 0x4e4 +#define MV64360_DEVICE_DEBUG_HIGH 0x4e8 +#define MV64360_RUNIT_MMASK 0x4f0 + +/****************************************/ +/* PCI Slave Address Decoding registers */ +/****************************************/ + +#define MV64360_PCI_0_CS_0_BANK_SIZE 0xc08 +#define MV64360_PCI_1_CS_0_BANK_SIZE 0xc88 +#define MV64360_PCI_0_CS_1_BANK_SIZE 0xd08 +#define MV64360_PCI_1_CS_1_BANK_SIZE 0xd88 +#define MV64360_PCI_0_CS_2_BANK_SIZE 0xc0c +#define MV64360_PCI_1_CS_2_BANK_SIZE 0xc8c +#define MV64360_PCI_0_CS_3_BANK_SIZE 0xd0c +#define MV64360_PCI_1_CS_3_BANK_SIZE 0xd8c +#define MV64360_PCI_0_DEVCS_0_BANK_SIZE 0xc10 +#define MV64360_PCI_1_DEVCS_0_BANK_SIZE 0xc90 +#define MV64360_PCI_0_DEVCS_1_BANK_SIZE 0xd10 +#define MV64360_PCI_1_DEVCS_1_BANK_SIZE 0xd90 +#define MV64360_PCI_0_DEVCS_2_BANK_SIZE 0xd18 +#define MV64360_PCI_1_DEVCS_2_BANK_SIZE 0xd98 +#define MV64360_PCI_0_DEVCS_3_BANK_SIZE 0xc14 +#define MV64360_PCI_1_DEVCS_3_BANK_SIZE 0xc94 +#define MV64360_PCI_0_DEVCS_BOOT_BANK_SIZE 0xd14 +#define MV64360_PCI_1_DEVCS_BOOT_BANK_SIZE 0xd94 +#define MV64360_PCI_0_P2P_MEM0_BAR_SIZE 0xd1c +#define MV64360_PCI_1_P2P_MEM0_BAR_SIZE 0xd9c +#define MV64360_PCI_0_P2P_MEM1_BAR_SIZE 0xd20 +#define MV64360_PCI_1_P2P_MEM1_BAR_SIZE 0xda0 +#define MV64360_PCI_0_P2P_I_O_BAR_SIZE 0xd24 +#define MV64360_PCI_1_P2P_I_O_BAR_SIZE 0xda4 +#define MV64360_PCI_0_CPU_BAR_SIZE 0xd28 +#define MV64360_PCI_1_CPU_BAR_SIZE 0xda8 +#define MV64360_PCI_0_INTERNAL_SRAM_BAR_SIZE 0xe00 +#define MV64360_PCI_1_INTERNAL_SRAM_BAR_SIZE 0xe80 +#define MV64360_PCI_0_EXPANSION_ROM_BAR_SIZE 0xd2c +#define MV64360_PCI_1_EXPANSION_ROM_BAR_SIZE 0xd9c +#define MV64360_PCI_0_BASE_ADDR_REG_ENABLE 0xc3c +#define MV64360_PCI_1_BASE_ADDR_REG_ENABLE 0xcbc +#define MV64360_PCI_0_CS_0_BASE_ADDR_REMAP 0xc48 +#define MV64360_PCI_1_CS_0_BASE_ADDR_REMAP 0xcc8 +#define MV64360_PCI_0_CS_1_BASE_ADDR_REMAP 0xd48 +#define MV64360_PCI_1_CS_1_BASE_ADDR_REMAP 0xdc8 +#define MV64360_PCI_0_CS_2_BASE_ADDR_REMAP 0xc4c +#define MV64360_PCI_1_CS_2_BASE_ADDR_REMAP 0xccc +#define MV64360_PCI_0_CS_3_BASE_ADDR_REMAP 0xd4c +#define MV64360_PCI_1_CS_3_BASE_ADDR_REMAP 0xdcc +#define MV64360_PCI_0_CS_0_BASE_HIGH_ADDR_REMAP 0xF04 +#define MV64360_PCI_1_CS_0_BASE_HIGH_ADDR_REMAP 0xF84 +#define MV64360_PCI_0_CS_1_BASE_HIGH_ADDR_REMAP 0xF08 +#define MV64360_PCI_1_CS_1_BASE_HIGH_ADDR_REMAP 0xF88 +#define MV64360_PCI_0_CS_2_BASE_HIGH_ADDR_REMAP 0xF0C +#define MV64360_PCI_1_CS_2_BASE_HIGH_ADDR_REMAP 0xF8C +#define MV64360_PCI_0_CS_3_BASE_HIGH_ADDR_REMAP 0xF10 +#define MV64360_PCI_1_CS_3_BASE_HIGH_ADDR_REMAP 0xF90 +#define MV64360_PCI_0_DEVCS_0_BASE_ADDR_REMAP 0xc50 +#define MV64360_PCI_1_DEVCS_0_BASE_ADDR_REMAP 0xcd0 +#define MV64360_PCI_0_DEVCS_1_BASE_ADDR_REMAP 0xd50 +#define MV64360_PCI_1_DEVCS_1_BASE_ADDR_REMAP 0xdd0 +#define MV64360_PCI_0_DEVCS_2_BASE_ADDR_REMAP 0xd58 +#define MV64360_PCI_1_DEVCS_2_BASE_ADDR_REMAP 0xdd8 +#define MV64360_PCI_0_DEVCS_3_BASE_ADDR_REMAP 0xc54 +#define MV64360_PCI_1_DEVCS_3_BASE_ADDR_REMAP 0xcd4 +#define MV64360_PCI_0_DEVCS_BOOTCS_BASE_ADDR_REMAP 0xd54 +#define MV64360_PCI_1_DEVCS_BOOTCS_BASE_ADDR_REMAP 0xdd4 +#define MV64360_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_LOW 0xd5c +#define MV64360_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_LOW 0xddc +#define MV64360_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_HIGH 0xd60 +#define MV64360_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_HIGH 0xde0 +#define MV64360_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_LOW 0xd64 +#define MV64360_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_LOW 0xde4 +#define MV64360_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_HIGH 0xd68 +#define MV64360_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_HIGH 0xde8 +#define MV64360_PCI_0_P2P_I_O_BASE_ADDR_REMAP 0xd6c +#define MV64360_PCI_1_P2P_I_O_BASE_ADDR_REMAP 0xdec +#define MV64360_PCI_0_CPU_BASE_ADDR_REMAP_LOW 0xd70 +#define MV64360_PCI_1_CPU_BASE_ADDR_REMAP_LOW 0xdf0 +#define MV64360_PCI_0_CPU_BASE_ADDR_REMAP_HIGH 0xd74 +#define MV64360_PCI_1_CPU_BASE_ADDR_REMAP_HIGH 0xdf4 +#define MV64360_PCI_0_INTEGRATED_SRAM_BASE_ADDR_REMAP 0xf00 +#define MV64360_PCI_1_INTEGRATED_SRAM_BASE_ADDR_REMAP 0xf80 +#define MV64360_PCI_0_EXPANSION_ROM_BASE_ADDR_REMAP 0xf38 +#define MV64360_PCI_1_EXPANSION_ROM_BASE_ADDR_REMAP 0xfb8 +#define MV64360_PCI_0_ADDR_DECODE_CONTROL 0xd3c +#define MV64360_PCI_1_ADDR_DECODE_CONTROL 0xdbc +#define MV64360_PCI_0_HEADERS_RETARGET_CONTROL 0xF40 +#define MV64360_PCI_1_HEADERS_RETARGET_CONTROL 0xFc0 +#define MV64360_PCI_0_HEADERS_RETARGET_BASE 0xF44 +#define MV64360_PCI_1_HEADERS_RETARGET_BASE 0xFc4 +#define MV64360_PCI_0_HEADERS_RETARGET_HIGH 0xF48 +#define MV64360_PCI_1_HEADERS_RETARGET_HIGH 0xFc8 + +/***********************************/ +/* PCI Control Register Map */ +/***********************************/ + +#define MV64360_PCI_0_DLL_STATUS_AND_COMMAND 0x1d20 +#define MV64360_PCI_1_DLL_STATUS_AND_COMMAND 0x1da0 +#define MV64360_PCI_0_MPP_PADS_DRIVE_CONTROL 0x1d1C +#define MV64360_PCI_1_MPP_PADS_DRIVE_CONTROL 0x1d9C +#define MV64360_PCI_0_COMMAND 0xc00 +#define MV64360_PCI_1_COMMAND 0xc80 +#define MV64360_PCI_0_MODE 0xd00 +#define MV64360_PCI_1_MODE 0xd80 +#define MV64360_PCI_0_RETRY 0xc04 +#define MV64360_PCI_1_RETRY 0xc84 +#define MV64360_PCI_0_READ_BUFFER_DISCARD_TIMER 0xd04 +#define MV64360_PCI_1_READ_BUFFER_DISCARD_TIMER 0xd84 +#define MV64360_PCI_0_MSI_TRIGGER_TIMER 0xc38 +#define MV64360_PCI_1_MSI_TRIGGER_TIMER 0xcb8 +#define MV64360_PCI_0_ARBITER_CONTROL 0x1d00 +#define MV64360_PCI_1_ARBITER_CONTROL 0x1d80 +#define MV64360_PCI_0_CROSS_BAR_CONTROL_LOW 0x1d08 +#define MV64360_PCI_1_CROSS_BAR_CONTROL_LOW 0x1d88 +#define MV64360_PCI_0_CROSS_BAR_CONTROL_HIGH 0x1d0c +#define MV64360_PCI_1_CROSS_BAR_CONTROL_HIGH 0x1d8c +#define MV64360_PCI_0_CROSS_BAR_TIMEOUT 0x1d04 +#define MV64360_PCI_1_CROSS_BAR_TIMEOUT 0x1d84 +#define MV64360_PCI_0_SYNC_BARRIER_TRIGGER_REG 0x1D18 +#define MV64360_PCI_1_SYNC_BARRIER_TRIGGER_REG 0x1D98 +#define MV64360_PCI_0_SYNC_BARRIER_VIRTUAL_REG 0x1d10 +#define MV64360_PCI_1_SYNC_BARRIER_VIRTUAL_REG 0x1d90 +#define MV64360_PCI_0_P2P_CONFIG 0x1d14 +#define MV64360_PCI_1_P2P_CONFIG 0x1d94 + +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_0_LOW 0x1e00 +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_0_HIGH 0x1e04 +#define MV64360_PCI_0_ACCESS_CONTROL_SIZE_0 0x1e08 +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_1_LOW 0x1e10 +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_1_HIGH 0x1e14 +#define MV64360_PCI_0_ACCESS_CONTROL_SIZE_1 0x1e18 +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_2_LOW 0x1e20 +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_2_HIGH 0x1e24 +#define MV64360_PCI_0_ACCESS_CONTROL_SIZE_2 0x1e28 +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_3_LOW 0x1e30 +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_3_HIGH 0x1e34 +#define MV64360_PCI_0_ACCESS_CONTROL_SIZE_3 0x1e38 +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_4_LOW 0x1e40 +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_4_HIGH 0x1e44 +#define MV64360_PCI_0_ACCESS_CONTROL_SIZE_4 0x1e48 +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_5_LOW 0x1e50 +#define MV64360_PCI_0_ACCESS_CONTROL_BASE_5_HIGH 0x1e54 +#define MV64360_PCI_0_ACCESS_CONTROL_SIZE_5 0x1e58 + +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_0_LOW 0x1e80 +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_0_HIGH 0x1e84 +#define MV64360_PCI_1_ACCESS_CONTROL_SIZE_0 0x1e88 +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_1_LOW 0x1e90 +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_1_HIGH 0x1e94 +#define MV64360_PCI_1_ACCESS_CONTROL_SIZE_1 0x1e98 +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_2_LOW 0x1ea0 +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_2_HIGH 0x1ea4 +#define MV64360_PCI_1_ACCESS_CONTROL_SIZE_2 0x1ea8 +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_3_LOW 0x1eb0 +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_3_HIGH 0x1eb4 +#define MV64360_PCI_1_ACCESS_CONTROL_SIZE_3 0x1eb8 +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_4_LOW 0x1ec0 +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_4_HIGH 0x1ec4 +#define MV64360_PCI_1_ACCESS_CONTROL_SIZE_4 0x1ec8 +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_5_LOW 0x1ed0 +#define MV64360_PCI_1_ACCESS_CONTROL_BASE_5_HIGH 0x1ed4 +#define MV64360_PCI_1_ACCESS_CONTROL_SIZE_5 0x1ed8 + +/****************************************/ +/* PCI Configuration Access Registers */ +/****************************************/ + +#define MV64360_PCI_0_CONFIG_ADDR 0xcf8 +#define MV64360_PCI_0_CONFIG_DATA_VIRTUAL_REG 0xcfc +#define MV64360_PCI_1_CONFIG_ADDR 0xc78 +#define MV64360_PCI_1_CONFIG_DATA_VIRTUAL_REG 0xc7c +#define MV64360_PCI_0_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG 0xc34 +#define MV64360_PCI_1_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG 0xcb4 + +/****************************************/ +/* PCI Error Report Registers */ +/****************************************/ + +#define MV64360_PCI_0_SERR_MASK 0xc28 +#define MV64360_PCI_1_SERR_MASK 0xca8 +#define MV64360_PCI_0_ERROR_ADDR_LOW 0x1d40 +#define MV64360_PCI_1_ERROR_ADDR_LOW 0x1dc0 +#define MV64360_PCI_0_ERROR_ADDR_HIGH 0x1d44 +#define MV64360_PCI_1_ERROR_ADDR_HIGH 0x1dc4 +#define MV64360_PCI_0_ERROR_ATTRIBUTE 0x1d48 +#define MV64360_PCI_1_ERROR_ATTRIBUTE 0x1dc8 +#define MV64360_PCI_0_ERROR_COMMAND 0x1d50 +#define MV64360_PCI_1_ERROR_COMMAND 0x1dd0 +#define MV64360_PCI_0_ERROR_CAUSE 0x1d58 +#define MV64360_PCI_1_ERROR_CAUSE 0x1dd8 +#define MV64360_PCI_0_ERROR_MASK 0x1d5c +#define MV64360_PCI_1_ERROR_MASK 0x1ddc + +/****************************************/ +/* PCI Debug Registers */ +/****************************************/ + +#define MV64360_PCI_0_MMASK 0X1D24 +#define MV64360_PCI_1_MMASK 0X1DA4 + +/*********************************************/ +/* PCI Configuration, Function 0, Registers */ +/*********************************************/ + +#define MV64360_PCI_DEVICE_AND_VENDOR_ID 0x000 +#define MV64360_PCI_STATUS_AND_COMMAND 0x004 +#define MV64360_PCI_CLASS_CODE_AND_REVISION_ID 0x008 +#define MV64360_PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE 0x00C + +#define MV64360_PCI_SCS_0_BASE_ADDR_LOW 0x010 +#define MV64360_PCI_SCS_0_BASE_ADDR_HIGH 0x014 +#define MV64360_PCI_SCS_1_BASE_ADDR_LOW 0x018 +#define MV64360_PCI_SCS_1_BASE_ADDR_HIGH 0x01C +#define MV64360_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_LOW 0x020 +#define MV64360_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_HIGH 0x024 +#define MV64360_PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID 0x02c +#define MV64360_PCI_EXPANSION_ROM_BASE_ADDR_REG 0x030 +#define MV64360_PCI_CAPABILTY_LIST_POINTER 0x034 +#define MV64360_PCI_INTERRUPT_PIN_AND_LINE 0x03C + /* capability list */ +#define MV64360_PCI_POWER_MANAGEMENT_CAPABILITY 0x040 +#define MV64360_PCI_POWER_MANAGEMENT_STATUS_AND_CONTROL 0x044 +#define MV64360_PCI_VPD_ADDR 0x048 +#define MV64360_PCI_VPD_DATA 0x04c +#define MV64360_PCI_MSI_MESSAGE_CONTROL 0x050 +#define MV64360_PCI_MSI_MESSAGE_ADDR 0x054 +#define MV64360_PCI_MSI_MESSAGE_UPPER_ADDR 0x058 +#define MV64360_PCI_MSI_MESSAGE_DATA 0x05c +#define MV64360_PCI_X_COMMAND 0x060 +#define MV64360_PCI_X_STATUS 0x064 +#define MV64360_PCI_COMPACT_PCI_HOT_SWAP 0x068 + +/***********************************************/ +/* PCI Configuration, Function 1, Registers */ +/***********************************************/ + +#define MV64360_PCI_SCS_2_BASE_ADDR_LOW 0x110 +#define MV64360_PCI_SCS_2_BASE_ADDR_HIGH 0x114 +#define MV64360_PCI_SCS_3_BASE_ADDR_LOW 0x118 +#define MV64360_PCI_SCS_3_BASE_ADDR_HIGH 0x11c +#define MV64360_PCI_INTERNAL_SRAM_BASE_ADDR_LOW 0x120 +#define MV64360_PCI_INTERNAL_SRAM_BASE_ADDR_HIGH 0x124 + +/***********************************************/ +/* PCI Configuration, Function 2, Registers */ +/***********************************************/ + +#define MV64360_PCI_DEVCS_0_BASE_ADDR_LOW 0x210 +#define MV64360_PCI_DEVCS_0_BASE_ADDR_HIGH 0x214 +#define MV64360_PCI_DEVCS_1_BASE_ADDR_LOW 0x218 +#define MV64360_PCI_DEVCS_1_BASE_ADDR_HIGH 0x21c +#define MV64360_PCI_DEVCS_2_BASE_ADDR_LOW 0x220 +#define MV64360_PCI_DEVCS_2_BASE_ADDR_HIGH 0x224 + +/***********************************************/ +/* PCI Configuration, Function 3, Registers */ +/***********************************************/ + +#define MV64360_PCI_DEVCS_3_BASE_ADDR_LOW 0x310 +#define MV64360_PCI_DEVCS_3_BASE_ADDR_HIGH 0x314 +#define MV64360_PCI_BOOT_CS_BASE_ADDR_LOW 0x318 +#define MV64360_PCI_BOOT_CS_BASE_ADDR_HIGH 0x31c +#define MV64360_PCI_CPU_BASE_ADDR_LOW 0x220 +#define MV64360_PCI_CPU_BASE_ADDR_HIGH 0x224 + +/***********************************************/ +/* PCI Configuration, Function 4, Registers */ +/***********************************************/ + +#define MV64360_PCI_P2P_MEM0_BASE_ADDR_LOW 0x410 +#define MV64360_PCI_P2P_MEM0_BASE_ADDR_HIGH 0x414 +#define MV64360_PCI_P2P_MEM1_BASE_ADDR_LOW 0x418 +#define MV64360_PCI_P2P_MEM1_BASE_ADDR_HIGH 0x41c +#define MV64360_PCI_P2P_I_O_BASE_ADDR 0x420 +#define MV64360_PCI_INTERNAL_REGS_I_O_MAPPED_BASE_ADDR 0x424 + +/****************************************/ +/* Messaging Unit Registers (I20) */ +/****************************************/ + +#define MV64360_I2O_INBOUND_MESSAGE_REG0_PCI_0_SIDE 0x010 +#define MV64360_I2O_INBOUND_MESSAGE_REG1_PCI_0_SIDE 0x014 +#define MV64360_I2O_OUTBOUND_MESSAGE_REG0_PCI_0_SIDE 0x018 +#define MV64360_I2O_OUTBOUND_MESSAGE_REG1_PCI_0_SIDE 0x01C +#define MV64360_I2O_INBOUND_DOORBELL_REG_PCI_0_SIDE 0x020 +#define MV64360_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE 0x024 +#define MV64360_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE 0x028 +#define MV64360_I2O_OUTBOUND_DOORBELL_REG_PCI_0_SIDE 0x02C +#define MV64360_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE 0x030 +#define MV64360_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE 0x034 +#define MV64360_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE 0x040 +#define MV64360_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE 0x044 +#define MV64360_I2O_QUEUE_CONTROL_REG_PCI_0_SIDE 0x050 +#define MV64360_I2O_QUEUE_BASE_ADDR_REG_PCI_0_SIDE 0x054 +#define MV64360_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE 0x060 +#define MV64360_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE 0x064 +#define MV64360_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE 0x068 +#define MV64360_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE 0x06C +#define MV64360_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE 0x070 +#define MV64360_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE 0x074 +#define MV64360_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE 0x0F8 +#define MV64360_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE 0x0FC + +#define MV64360_I2O_INBOUND_MESSAGE_REG0_PCI_1_SIDE 0x090 +#define MV64360_I2O_INBOUND_MESSAGE_REG1_PCI_1_SIDE 0x094 +#define MV64360_I2O_OUTBOUND_MESSAGE_REG0_PCI_1_SIDE 0x098 +#define MV64360_I2O_OUTBOUND_MESSAGE_REG1_PCI_1_SIDE 0x09C +#define MV64360_I2O_INBOUND_DOORBELL_REG_PCI_1_SIDE 0x0A0 +#define MV64360_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE 0x0A4 +#define MV64360_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE 0x0A8 +#define MV64360_I2O_OUTBOUND_DOORBELL_REG_PCI_1_SIDE 0x0AC +#define MV64360_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE 0x0B0 +#define MV64360_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE 0x0B4 +#define MV64360_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE 0x0C0 +#define MV64360_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE 0x0C4 +#define MV64360_I2O_QUEUE_CONTROL_REG_PCI_1_SIDE 0x0D0 +#define MV64360_I2O_QUEUE_BASE_ADDR_REG_PCI_1_SIDE 0x0D4 +#define MV64360_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE 0x0E0 +#define MV64360_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE 0x0E4 +#define MV64360_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE 0x0E8 +#define MV64360_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE 0x0EC +#define MV64360_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE 0x0F0 +#define MV64360_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE 0x0F4 +#define MV64360_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE 0x078 +#define MV64360_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE 0x07C + +#define MV64360_I2O_INBOUND_MESSAGE_REG0_CPU0_SIDE 0x1C10 +#define MV64360_I2O_INBOUND_MESSAGE_REG1_CPU0_SIDE 0x1C14 +#define MV64360_I2O_OUTBOUND_MESSAGE_REG0_CPU0_SIDE 0x1C18 +#define MV64360_I2O_OUTBOUND_MESSAGE_REG1_CPU0_SIDE 0x1C1C +#define MV64360_I2O_INBOUND_DOORBELL_REG_CPU0_SIDE 0x1C20 +#define MV64360_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE 0x1C24 +#define MV64360_I2O_INBOUND_INTERRUPT_MASK_REG_CPU0_SIDE 0x1C28 +#define MV64360_I2O_OUTBOUND_DOORBELL_REG_CPU0_SIDE 0x1C2C +#define MV64360_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE 0x1C30 +#define MV64360_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU0_SIDE 0x1C34 +#define MV64360_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE 0x1C40 +#define MV64360_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE 0x1C44 +#define MV64360_I2O_QUEUE_CONTROL_REG_CPU0_SIDE 0x1C50 +#define MV64360_I2O_QUEUE_BASE_ADDR_REG_CPU0_SIDE 0x1C54 +#define MV64360_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE 0x1C60 +#define MV64360_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE 0x1C64 +#define MV64360_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE 0x1C68 +#define MV64360_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE 0x1C6C +#define MV64360_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE 0x1C70 +#define MV64360_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE 0x1C74 +#define MV64360_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE 0x1CF8 +#define MV64360_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE 0x1CFC +#define MV64360_I2O_INBOUND_MESSAGE_REG0_CPU1_SIDE 0x1C90 +#define MV64360_I2O_INBOUND_MESSAGE_REG1_CPU1_SIDE 0x1C94 +#define MV64360_I2O_OUTBOUND_MESSAGE_REG0_CPU1_SIDE 0x1C98 +#define MV64360_I2O_OUTBOUND_MESSAGE_REG1_CPU1_SIDE 0x1C9C +#define MV64360_I2O_INBOUND_DOORBELL_REG_CPU1_SIDE 0x1CA0 +#define MV64360_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE 0x1CA4 +#define MV64360_I2O_INBOUND_INTERRUPT_MASK_REG_CPU1_SIDE 0x1CA8 +#define MV64360_I2O_OUTBOUND_DOORBELL_REG_CPU1_SIDE 0x1CAC +#define MV64360_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE 0x1CB0 +#define MV64360_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU1_SIDE 0x1CB4 +#define MV64360_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE 0x1CC0 +#define MV64360_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE 0x1CC4 +#define MV64360_I2O_QUEUE_CONTROL_REG_CPU1_SIDE 0x1CD0 +#define MV64360_I2O_QUEUE_BASE_ADDR_REG_CPU1_SIDE 0x1CD4 +#define MV64360_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE 0x1CE0 +#define MV64360_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE 0x1CE4 +#define MV64360_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE 0x1CE8 +#define MV64360_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE 0x1CEC +#define MV64360_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE 0x1CF0 +#define MV64360_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE 0x1CF4 +#define MV64360_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE 0x1C78 +#define MV64360_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE 0x1C7C + +/****************************************/ +/* Ethernet Unit Registers */ +/****************************************/ + +#define MV64360_ETH_PHY_ADDR_REG 0x2000 +#define MV64360_ETH_SMI_REG 0x2004 +#define MV64360_ETH_UNIT_DEFAULT_ADDR_REG 0x2008 +#define MV64360_ETH_UNIT_DEFAULTID_REG 0x200c +#define MV64360_ETH_UNIT_INTERRUPT_CAUSE_REG 0x2080 +#define MV64360_ETH_UNIT_INTERRUPT_MASK_REG 0x2084 +#define MV64360_ETH_UNIT_INTERNAL_USE_REG 0x24fc +#define MV64360_ETH_UNIT_ERROR_ADDR_REG 0x2094 +#define MV64360_ETH_BAR_0 0x2200 +#define MV64360_ETH_BAR_1 0x2208 +#define MV64360_ETH_BAR_2 0x2210 +#define MV64360_ETH_BAR_3 0x2218 +#define MV64360_ETH_BAR_4 0x2220 +#define MV64360_ETH_BAR_5 0x2228 +#define MV64360_ETH_SIZE_REG_0 0x2204 +#define MV64360_ETH_SIZE_REG_1 0x220c +#define MV64360_ETH_SIZE_REG_2 0x2214 +#define MV64360_ETH_SIZE_REG_3 0x221c +#define MV64360_ETH_SIZE_REG_4 0x2224 +#define MV64360_ETH_SIZE_REG_5 0x222c +#define MV64360_ETH_HEADERS_RETARGET_BASE_REG 0x2230 +#define MV64360_ETH_HEADERS_RETARGET_CONTROL_REG 0x2234 +#define MV64360_ETH_HIGH_ADDR_REMAP_REG_0 0x2280 +#define MV64360_ETH_HIGH_ADDR_REMAP_REG_1 0x2284 +#define MV64360_ETH_HIGH_ADDR_REMAP_REG_2 0x2288 +#define MV64360_ETH_HIGH_ADDR_REMAP_REG_3 0x228c +#define MV64360_ETH_BASE_ADDR_ENABLE_REG 0x2290 +#define MV64360_ETH_ACCESS_PROTECTION_REG(port) (0x2294 + (port<<2)) +#define MV64360_ETH_MIB_COUNTERS_BASE(port) (0x3000 + (port<<7)) +#define MV64360_ETH_PORT_CONFIG_REG(port) (0x2400 + (port<<10)) +#define MV64360_ETH_PORT_CONFIG_EXTEND_REG(port) (0x2404 + (port<<10)) +#define MV64360_ETH_MII_SERIAL_PARAMETRS_REG(port) (0x2408 + (port<<10)) +#define MV64360_ETH_GMII_SERIAL_PARAMETRS_REG(port) (0x240c + (port<<10)) +#define MV64360_ETH_VLAN_ETHERTYPE_REG(port) (0x2410 + (port<<10)) +#define MV64360_ETH_MAC_ADDR_LOW(port) (0x2414 + (port<<10)) +#define MV64360_ETH_MAC_ADDR_HIGH(port) (0x2418 + (port<<10)) +#define MV64360_ETH_SDMA_CONFIG_REG(port) (0x241c + (port<<10)) +#define MV64360_ETH_DSCP_0(port) (0x2420 + (port<<10)) +#define MV64360_ETH_DSCP_1(port) (0x2424 + (port<<10)) +#define MV64360_ETH_DSCP_2(port) (0x2428 + (port<<10)) +#define MV64360_ETH_DSCP_3(port) (0x242c + (port<<10)) +#define MV64360_ETH_DSCP_4(port) (0x2430 + (port<<10)) +#define MV64360_ETH_DSCP_5(port) (0x2434 + (port<<10)) +#define MV64360_ETH_DSCP_6(port) (0x2438 + (port<<10)) +#define MV64360_ETH_PORT_SERIAL_CONTROL_REG(port) (0x243c + (port<<10)) +#define MV64360_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port) (0x2440 + (port<<10)) +#define MV64360_ETH_PORT_STATUS_REG(port) (0x2444 + (port<<10)) +#define MV64360_ETH_TRANSMIT_QUEUE_COMMAND_REG(port) (0x2448 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_FIXED_PRIORITY(port) (0x244c + (port<<10)) +#define MV64360_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port) (0x2450 + (port<<10)) +#define MV64360_ETH_MAXIMUM_TRANSMIT_UNIT(port) (0x2458 + (port<<10)) +#define MV64360_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port) (0x245c + (port<<10)) +#define MV64360_ETH_INTERRUPT_CAUSE_REG(port) (0x2460 + (port<<10)) +#define MV64360_ETH_INTERRUPT_CAUSE_EXTEND_REG(port) (0x2464 + (port<<10)) +#define MV64360_ETH_INTERRUPT_MASK_REG(port) (0x2468 + (port<<10)) +#define MV64360_ETH_INTERRUPT_EXTEND_MASK_REG(port) (0x246c + (port<<10)) +#define MV64360_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port) (0x2470 + (port<<10)) +#define MV64360_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port) (0x2474 + (port<<10)) +#define MV64360_ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (0x247c + (port<<10)) +#define MV64360_ETH_RX_DISCARDED_FRAMES_COUNTER(port) (0x2484 + (port<<10) +#define MV64360_ETH_PORT_DEBUG_0_REG(port) (0x248c + (port<<10)) +#define MV64360_ETH_PORT_DEBUG_1_REG(port) (0x2490 + (port<<10)) +#define MV64360_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port) (0x2494 + (port<<10)) +#define MV64360_ETH_INTERNAL_USE_REG(port) (0x24fc + (port<<10)) +#define MV64360_ETH_RECEIVE_QUEUE_COMMAND_REG(port) (0x2680 + (port<<10)) +#define MV64360_ETH_CURRENT_SERVED_TX_DESC_PTR(port) (0x2684 + (port<<10)) +#define MV64360_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port) (0x260c + (port<<10)) +#define MV64360_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port) (0x261c + (port<<10)) +#define MV64360_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port) (0x262c + (port<<10)) +#define MV64360_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port) (0x263c + (port<<10)) +#define MV64360_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port) (0x264c + (port<<10)) +#define MV64360_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port) (0x265c + (port<<10)) +#define MV64360_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port) (0x266c + (port<<10)) +#define MV64360_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port) (0x267c + (port<<10)) +#define MV64360_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port) (0x26c0 + (port<<10)) +#define MV64360_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port) (0x26c4 + (port<<10)) +#define MV64360_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port) (0x26c8 + (port<<10)) +#define MV64360_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port) (0x26cc + (port<<10)) +#define MV64360_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port) (0x26d0 + (port<<10)) +#define MV64360_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port) (0x26d4 + (port<<10)) +#define MV64360_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port) (0x26d8 + (port<<10)) +#define MV64360_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port) (0x26dc + (port<<10)) +#define MV64360_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port) (0x2700 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port) (0x2710 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port) (0x2720 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port) (0x2730 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port) (0x2740 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port) (0x2750 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port) (0x2760 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port) (0x2770 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port) (0x2704 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port) (0x2714 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port) (0x2724 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port) (0x2734 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port) (0x2744 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port) (0x2754 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port) (0x2764 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port) (0x2774 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_0_ARBITER_CONFIG(port) (0x2708 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_1_ARBITER_CONFIG(port) (0x2718 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_2_ARBITER_CONFIG(port) (0x2728 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_3_ARBITER_CONFIG(port) (0x2738 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_4_ARBITER_CONFIG(port) (0x2748 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_5_ARBITER_CONFIG(port) (0x2758 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_6_ARBITER_CONFIG(port) (0x2768 + (port<<10)) +#define MV64360_ETH_TX_QUEUE_7_ARBITER_CONFIG(port) (0x2778 + (port<<10)) +#define MV64360_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port) (0x2780 + (port<<10)) +#define MV64360_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port) (0x3400 + (port<<10)) +#define MV64360_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port) (0x3500 + (port<<10)) +#define MV64360_ETH_DA_FILTER_UNICAST_TABLE_BASE(port) (0x3600 + (port<<10)) + +/*******************************************/ +/* CUNIT Registers */ +/*******************************************/ + + /* Address Decoding Register Map */ + +#define MV64360_CUNIT_BASE_ADDR_REG0 0xf200 +#define MV64360_CUNIT_BASE_ADDR_REG1 0xf208 +#define MV64360_CUNIT_BASE_ADDR_REG2 0xf210 +#define MV64360_CUNIT_BASE_ADDR_REG3 0xf218 +#define MV64360_CUNIT_SIZE0 0xf204 +#define MV64360_CUNIT_SIZE1 0xf20c +#define MV64360_CUNIT_SIZE2 0xf214 +#define MV64360_CUNIT_SIZE3 0xf21c +#define MV64360_CUNIT_HIGH_ADDR_REMAP_REG0 0xf240 +#define MV64360_CUNIT_HIGH_ADDR_REMAP_REG1 0xf244 +#define MV64360_CUNIT_BASE_ADDR_ENABLE_REG 0xf250 +#define MV64360_MPSC0_ACCESS_PROTECTION_REG 0xf254 +#define MV64360_MPSC1_ACCESS_PROTECTION_REG 0xf258 +#define MV64360_CUNIT_INTERNAL_SPACE_BASE_ADDR_REG 0xf25C + + /* Error Report Registers */ + +#define MV64360_CUNIT_INTERRUPT_CAUSE_REG 0xf310 +#define MV64360_CUNIT_INTERRUPT_MASK_REG 0xf314 +#define MV64360_CUNIT_ERROR_ADDR 0xf318 + + /* Cunit Control Registers */ + +#define MV64360_CUNIT_ARBITER_CONTROL_REG 0xf300 +#define MV64360_CUNIT_CONFIG_REG 0xb40c +#define MV64360_CUNIT_CRROSBAR_TIMEOUT_REG 0xf304 + + /* Cunit Debug Registers */ + +#define MV64360_CUNIT_DEBUG_LOW 0xf340 +#define MV64360_CUNIT_DEBUG_HIGH 0xf344 +#define MV64360_CUNIT_MMASK 0xf380 + + /* Cunit Base Address Enable Window Bits*/ +#define MV64360_CUNIT_BASE_ADDR_WIN_0_BIT 0x0 +#define MV64360_CUNIT_BASE_ADDR_WIN_1_BIT 0x1 +#define MV64360_CUNIT_BASE_ADDR_WIN_2_BIT 0x2 +#define MV64360_CUNIT_BASE_ADDR_WIN_3_BIT 0x3 + + /* MPSCs Clocks Routing Registers */ + +#define MV64360_MPSC_ROUTING_REG 0xb400 +#define MV64360_MPSC_RX_CLOCK_ROUTING_REG 0xb404 +#define MV64360_MPSC_TX_CLOCK_ROUTING_REG 0xb408 + + /* MPSCs Interrupts Registers */ + +#define MV64360_MPSC_CAUSE_REG(port) (0xb804 + (port<<3)) +#define MV64360_MPSC_MASK_REG(port) (0xb884 + (port<<3)) + +#define MV64360_MPSC_MAIN_CONFIG_LOW(port) (0x8000 + (port<<12)) +#define MV64360_MPSC_MAIN_CONFIG_HIGH(port) (0x8004 + (port<<12)) +#define MV64360_MPSC_PROTOCOL_CONFIG(port) (0x8008 + (port<<12)) +#define MV64360_MPSC_CHANNEL_REG1(port) (0x800c + (port<<12)) +#define MV64360_MPSC_CHANNEL_REG2(port) (0x8010 + (port<<12)) +#define MV64360_MPSC_CHANNEL_REG3(port) (0x8014 + (port<<12)) +#define MV64360_MPSC_CHANNEL_REG4(port) (0x8018 + (port<<12)) +#define MV64360_MPSC_CHANNEL_REG5(port) (0x801c + (port<<12)) +#define MV64360_MPSC_CHANNEL_REG6(port) (0x8020 + (port<<12)) +#define MV64360_MPSC_CHANNEL_REG7(port) (0x8024 + (port<<12)) +#define MV64360_MPSC_CHANNEL_REG8(port) (0x8028 + (port<<12)) +#define MV64360_MPSC_CHANNEL_REG9(port) (0x802c + (port<<12)) +#define MV64360_MPSC_CHANNEL_REG10(port) (0x8030 + (port<<12)) + + /* MPSC0 Registers */ + + +/***************************************/ +/* SDMA Registers */ +/***************************************/ + +#define MV64360_SDMA_CONFIG_REG(channel) (0x4000 + (channel<<13)) +#define MV64360_SDMA_COMMAND_REG(channel) (0x4008 + (channel<<13)) +#define MV64360_SDMA_CURRENT_RX_DESCRIPTOR_POINTER(channel) (0x4810 + (channel<<13)) +#define MV64360_SDMA_CURRENT_TX_DESCRIPTOR_POINTER(channel) (0x4c10 + (channel<<13)) +#define MV64360_SDMA_FIRST_TX_DESCRIPTOR_POINTER(channel) (0x4c14 + (channel<<13)) + +#define MV64360_SDMA_CAUSE_REG 0xb800 +#define MV64360_SDMA_MASK_REG 0xb880 + + +/****************************************/ +/* SDMA Address Space Targets */ +/****************************************/ + +#define MV64360_SDMA_DRAM_CS_0_TARGET 0x0e00 +#define MV64360_SDMA_DRAM_CS_1_TARGET 0x0d00 +#define MV64360_SDMA_DRAM_CS_2_TARGET 0x0b00 +#define MV64360_SDMA_DRAM_CS_3_TARGET 0x0700 + +#define MV64360_SDMA_DEV_CS_0_TARGET 0x1e01 +#define MV64360_SDMA_DEV_CS_1_TARGET 0x1d01 +#define MV64360_SDMA_DEV_CS_2_TARGET 0x1b01 +#define MV64360_SDMA_DEV_CS_3_TARGET 0x1701 + +#define MV64360_SDMA_BOOT_CS_TARGET 0x0f00 + +#define MV64360_SDMA_SRAM_TARGET 0x0003 +#define MV64360_SDMA_60X_BUS_TARGET 0x4003 + +#define MV64360_PCI_0_TARGET 0x0003 +#define MV64360_PCI_1_TARGET 0x0004 + + +/* Devices BAR and size registers */ + +#define MV64360_DEV_CS0_BASE_ADDR 0x028 +#define MV64360_DEV_CS0_SIZE 0x030 +#define MV64360_DEV_CS1_BASE_ADDR 0x228 +#define MV64360_DEV_CS1_SIZE 0x230 +#define MV64360_DEV_CS2_BASE_ADDR 0x248 +#define MV64360_DEV_CS2_SIZE 0x250 +#define MV64360_DEV_CS3_BASE_ADDR 0x038 +#define MV64360_DEV_CS3_SIZE 0x040 +#define MV64360_BOOTCS_BASE_ADDR 0x238 +#define MV64360_BOOTCS_SIZE 0x240 + +/* SDMA Window access protection */ +#define MV64360_SDMA_WIN_ACCESS_NOT_ALLOWED 0 +#define MV64360_SDMA_WIN_ACCESS_READ_ONLY 1 +#define MV64360_SDMA_WIN_ACCESS_FULL 2 + +/* BRG Interrupts */ + +#define MV64360_BRG_CONFIG_REG(brg) (0xb200 + (brg<<3)) +#define MV64360_BRG_BAUDE_TUNING_REG(brg) (0xb204 + (brg<<3)) +#define MV64360_BRG_CAUSE_REG 0xb834 +#define MV64360_BRG_MASK_REG 0xb8b4 + +/****************************************/ +/* DMA Channel Control */ +/****************************************/ + +#define MV64360_DMA_CHANNEL0_CONTROL 0x840 +#define MV64360_DMA_CHANNEL0_CONTROL_HIGH 0x880 +#define MV64360_DMA_CHANNEL1_CONTROL 0x844 +#define MV64360_DMA_CHANNEL1_CONTROL_HIGH 0x884 +#define MV64360_DMA_CHANNEL2_CONTROL 0x848 +#define MV64360_DMA_CHANNEL2_CONTROL_HIGH 0x888 +#define MV64360_DMA_CHANNEL3_CONTROL 0x84C +#define MV64360_DMA_CHANNEL3_CONTROL_HIGH 0x88C + + +/****************************************/ +/* IDMA Registers */ +/****************************************/ + +#define MV64360_DMA_CHANNEL0_BYTE_COUNT 0x800 +#define MV64360_DMA_CHANNEL1_BYTE_COUNT 0x804 +#define MV64360_DMA_CHANNEL2_BYTE_COUNT 0x808 +#define MV64360_DMA_CHANNEL3_BYTE_COUNT 0x80C +#define MV64360_DMA_CHANNEL0_SOURCE_ADDR 0x810 +#define MV64360_DMA_CHANNEL1_SOURCE_ADDR 0x814 +#define MV64360_DMA_CHANNEL2_SOURCE_ADDR 0x818 +#define MV64360_DMA_CHANNEL3_SOURCE_ADDR 0x81c +#define MV64360_DMA_CHANNEL0_DESTINATION_ADDR 0x820 +#define MV64360_DMA_CHANNEL1_DESTINATION_ADDR 0x824 +#define MV64360_DMA_CHANNEL2_DESTINATION_ADDR 0x828 +#define MV64360_DMA_CHANNEL3_DESTINATION_ADDR 0x82C +#define MV64360_DMA_CHANNEL0_NEXT_DESCRIPTOR_POINTER 0x830 +#define MV64360_DMA_CHANNEL1_NEXT_DESCRIPTOR_POINTER 0x834 +#define MV64360_DMA_CHANNEL2_NEXT_DESCRIPTOR_POINTER 0x838 +#define MV64360_DMA_CHANNEL3_NEXT_DESCRIPTOR_POINTER 0x83C +#define MV64360_DMA_CHANNEL0_CURRENT_DESCRIPTOR_POINTER 0x870 +#define MV64360_DMA_CHANNEL1_CURRENT_DESCRIPTOR_POINTER 0x874 +#define MV64360_DMA_CHANNEL2_CURRENT_DESCRIPTOR_POINTER 0x878 +#define MV64360_DMA_CHANNEL3_CURRENT_DESCRIPTOR_POINTER 0x87C + + /* IDMA Address Decoding Base Address Registers */ + +#define MV64360_DMA_BASE_ADDR_REG0 0xa00 +#define MV64360_DMA_BASE_ADDR_REG1 0xa08 +#define MV64360_DMA_BASE_ADDR_REG2 0xa10 +#define MV64360_DMA_BASE_ADDR_REG3 0xa18 +#define MV64360_DMA_BASE_ADDR_REG4 0xa20 +#define MV64360_DMA_BASE_ADDR_REG5 0xa28 +#define MV64360_DMA_BASE_ADDR_REG6 0xa30 +#define MV64360_DMA_BASE_ADDR_REG7 0xa38 + + /* IDMA Address Decoding Size Address Register */ + +#define MV64360_DMA_SIZE_REG0 0xa04 +#define MV64360_DMA_SIZE_REG1 0xa0c +#define MV64360_DMA_SIZE_REG2 0xa14 +#define MV64360_DMA_SIZE_REG3 0xa1c +#define MV64360_DMA_SIZE_REG4 0xa24 +#define MV64360_DMA_SIZE_REG5 0xa2c +#define MV64360_DMA_SIZE_REG6 0xa34 +#define MV64360_DMA_SIZE_REG7 0xa3C + + /* IDMA Address Decoding High Address Remap and Access + Protection Registers */ + +#define MV64360_DMA_HIGH_ADDR_REMAP_REG0 0xa60 +#define MV64360_DMA_HIGH_ADDR_REMAP_REG1 0xa64 +#define MV64360_DMA_HIGH_ADDR_REMAP_REG2 0xa68 +#define MV64360_DMA_HIGH_ADDR_REMAP_REG3 0xa6C +#define MV64360_DMA_BASE_ADDR_ENABLE_REG 0xa80 +#define MV64360_DMA_CHANNEL0_ACCESS_PROTECTION_REG 0xa70 +#define MV64360_DMA_CHANNEL1_ACCESS_PROTECTION_REG 0xa74 +#define MV64360_DMA_CHANNEL2_ACCESS_PROTECTION_REG 0xa78 +#define MV64360_DMA_CHANNEL3_ACCESS_PROTECTION_REG 0xa7c +#define MV64360_DMA_ARBITER_CONTROL 0x860 +#define MV64360_DMA_CROSS_BAR_TIMEOUT 0x8d0 + + /* IDMA Headers Retarget Registers */ + +#define MV64360_DMA_HEADERS_RETARGET_CONTROL 0xa84 +#define MV64360_DMA_HEADERS_RETARGET_BASE 0xa88 + + /* IDMA Interrupt Register */ + +#define MV64360_DMA_INTERRUPT_CAUSE_REG 0x8c0 +#define MV64360_DMA_INTERRUPT_CAUSE_MASK 0x8c4 +#define MV64360_DMA_ERROR_ADDR 0x8c8 +#define MV64360_DMA_ERROR_SELECT 0x8cc + + /* IDMA Debug Register ( for internal use ) */ + +#define MV64360_DMA_DEBUG_LOW 0x8e0 +#define MV64360_DMA_DEBUG_HIGH 0x8e4 +#define MV64360_DMA_SPARE 0xA8C + +/****************************************/ +/* Timer_Counter */ +/****************************************/ + +#define MV64360_TIMER_COUNTER0 0x850 +#define MV64360_TIMER_COUNTER1 0x854 +#define MV64360_TIMER_COUNTER2 0x858 +#define MV64360_TIMER_COUNTER3 0x85C +#define MV64360_TIMER_COUNTER_0_3_CONTROL 0x864 +#define MV64360_TIMER_COUNTER_0_3_INTERRUPT_CAUSE 0x868 +#define MV64360_TIMER_COUNTER_0_3_INTERRUPT_MASK 0x86c + +/****************************************/ +/* Watchdog registers */ +/****************************************/ + +#define MV64360_WATCHDOG_CONFIG_REG 0xb410 +#define MV64360_WATCHDOG_VALUE_REG 0xb414 + +/****************************************/ +/* I2C Registers */ +/****************************************/ + +#define MV64360_I2C_SLAVE_ADDR 0xc000 +#define MV64360_I2C_EXTENDED_SLAVE_ADDR 0xc010 +#define MV64360_I2C_DATA 0xc004 +#define MV64360_I2C_CONTROL 0xc008 +#define MV64360_I2C_STATUS_BAUDE_RATE 0xc00C +#define MV64360_I2C_SOFT_RESET 0xc01c + +/****************************************/ +/* GPP Interface Registers */ +/****************************************/ + +#define MV64360_GPP_IO_CONTROL 0xf100 +#define MV64360_GPP_LEVEL_CONTROL 0xf110 +#define MV64360_GPP_VALUE 0xf104 +#define MV64360_GPP_INTERRUPT_CAUSE 0xf108 +#define MV64360_GPP_INTERRUPT_MASK0 0xf10c +#define MV64360_GPP_INTERRUPT_MASK1 0xf114 +#define MV64360_GPP_VALUE_SET 0xf118 +#define MV64360_GPP_VALUE_CLEAR 0xf11c + +/****************************************/ +/* Interrupt Controller Registers */ +/****************************************/ + +/****************************************/ +/* Interrupts */ +/****************************************/ + +#define MV64360_MAIN_INTERRUPT_CAUSE_LOW 0x004 +#define MV64360_MAIN_INTERRUPT_CAUSE_HIGH 0x00c +#define MV64360_CPU_INTERRUPT0_MASK_LOW 0x014 +#define MV64360_CPU_INTERRUPT0_MASK_HIGH 0x01c +#define MV64360_CPU_INTERRUPT0_SELECT_CAUSE 0x024 +#define MV64360_CPU_INTERRUPT1_MASK_LOW 0x034 +#define MV64360_CPU_INTERRUPT1_MASK_HIGH 0x03c +#define MV64360_CPU_INTERRUPT1_SELECT_CAUSE 0x044 +#define MV64360_INTERRUPT0_MASK_0_LOW 0x054 +#define MV64360_INTERRUPT0_MASK_0_HIGH 0x05c +#define MV64360_INTERRUPT0_SELECT_CAUSE 0x064 +#define MV64360_INTERRUPT1_MASK_0_LOW 0x074 +#define MV64360_INTERRUPT1_MASK_0_HIGH 0x07c +#define MV64360_INTERRUPT1_SELECT_CAUSE 0x084 + +/****************************************/ +/* MPP Interface Registers */ +/****************************************/ + +#define MV64360_MPP_CONTROL0 0xf000 +#define MV64360_MPP_CONTROL1 0xf004 +#define MV64360_MPP_CONTROL2 0xf008 +#define MV64360_MPP_CONTROL3 0xf00c + +/****************************************/ +/* Serial Initialization registers */ +/****************************************/ + +#define MV64360_SERIAL_INIT_LAST_DATA 0xf324 +#define MV64360_SERIAL_INIT_CONTROL 0xf328 +#define MV64360_SERIAL_INIT_STATUS 0xf32c + + +#endif /* __INCgt64360rh */ diff --git a/board/Marvell/db64360/pci.c b/board/Marvell/db64360/pci.c new file mode 100644 index 0000000..5637284 --- /dev/null +++ b/board/Marvell/db64360/pci.c @@ -0,0 +1,940 @@ +/* + * (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 <common.h> +#include <pci.h> + +#include "../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 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_write_config_dword (dev, PCI_BASE_ADDRESS_0 + offset, + 0x0); + pci_read_config_dword (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_write_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4, + bar_value); + } +} + + +/* 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[] = { + {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 DEBUG + gt_pci_bus_mode_display (PCI_HOST0); +#endif + + 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); + pciArbiterEnable (PCI_HOST0); + 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); + + pci0_hose.last_busno = pci_hose_scan (&pci0_hose); + +#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); + + pci1_hose.last_busno = pci_hose_scan (&pci1_hose); + + command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MEMORY; + pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); + +} diff --git a/board/Marvell/db64360/sdram_init.c b/board/Marvell/db64360/sdram_init.c new file mode 100644 index 0000000..d2635f8 --- /dev/null +++ b/board/Marvell/db64360/sdram_init.c @@ -0,0 +1,1984 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, 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 DB64360 Board + * Ingo Assmus (ingo.assmus@keymile.com) + ************************************************************************/ + + +/* sdram_init.c - automatic memory sizing */ + +#include <common.h> +#include <74xx_7xx.h> +#include "../include/memory.h" +#include "../include/pci.h" +#include "../include/mv_gen_reg.h" +#include <net.h> + +#include "eth.h" +#include "mpsc.h" +#include "../common/i2c.h" +#include "64360.h" +#include "mv_regs.h" + +#undef DEBUG +#define MAP_PCI + +#ifdef DEBUG +#define DP(x) x +#else +#define DP(x) +#endif + +int set_dfcdlInit (void); /* setup delay line of Mv64360 */ +int mvDmaIsChannelActive (int); +int mvDmaSetMemorySpace (ulong, ulong, ulong, ulong, ulong); +int mvDmaTransfer (int, ulong, ulong, ulong, ulong); + +/* ------------------------------------------------------------------------- */ + +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; +} + +#define GB (1 << 30) + +/* much of this code is based on (or is) the code in the pip405 port */ +/* thanks go to the authors of said port - Josh */ + +/* structure to store the relevant information about an sdram bank */ +typedef struct sdram_info { + uchar drb_size; + uchar registered, ecc; + uchar tpar; + uchar tras_clocks; + uchar burst_len; + uchar banks, slot; +} sdram_info_t; + +/* Typedefs for 'gtAuxilGetDIMMinfo' function */ + +typedef enum _memoryType { SDRAM, DDR } MEMORY_TYPE; + +typedef enum _voltageInterface { TTL_5V_TOLERANT, LVTTL, HSTL_1_5V, + SSTL_3_3V, SSTL_2_5V, VOLTAGE_UNKNOWN, +} VOLTAGE_INTERFACE; + +typedef enum _max_CL_supported_DDR { DDR_CL_1 = 1, DDR_CL_1_5 = 2, DDR_CL_2 = + 4, DDR_CL_2_5 = 8, DDR_CL_3 = 16, DDR_CL_3_5 = + 32, DDR_CL_FAULT } MAX_CL_SUPPORTED_DDR; +typedef enum _max_CL_supported_SD { SD_CL_1 = + 1, SD_CL_2, SD_CL_3, SD_CL_4, SD_CL_5, SD_CL_6, SD_CL_7, + SD_FAULT } MAX_CL_SUPPORTED_SD; + + +/* SDRAM/DDR information struct */ +typedef struct _gtMemoryDimmInfo { + MEMORY_TYPE memoryType; + unsigned int numOfRowAddresses; + unsigned int numOfColAddresses; + unsigned int numOfModuleBanks; + unsigned int dataWidth; + VOLTAGE_INTERFACE voltageInterface; + unsigned int errorCheckType; /* ECC , PARITY.. */ + unsigned int sdramWidth; /* 4,8,16 or 32 */ ; + unsigned int errorCheckDataWidth; /* 0 - no, 1 - Yes */ + unsigned int minClkDelay; + unsigned int burstLengthSupported; + unsigned int numOfBanksOnEachDevice; + unsigned int suportedCasLatencies; + unsigned int RefreshInterval; + unsigned int maxCASlatencySupported_LoP; /* LoP left of point (measured in ns) */ + unsigned int maxCASlatencySupported_RoP; /* RoP right of point (measured in ns) */ + MAX_CL_SUPPORTED_DDR maxClSupported_DDR; + MAX_CL_SUPPORTED_SD maxClSupported_SD; + unsigned int moduleBankDensity; + /* module attributes (true for yes) */ + bool bufferedAddrAndControlInputs; + bool registeredAddrAndControlInputs; + bool onCardPLL; + bool bufferedDQMBinputs; + bool registeredDQMBinputs; + bool differentialClockInput; + bool redundantRowAddressing; + + /* module general attributes */ + bool suportedAutoPreCharge; + bool suportedPreChargeAll; + bool suportedEarlyRasPreCharge; + bool suportedWrite1ReadBurst; + bool suported5PercentLowVCC; + bool suported5PercentUpperVCC; + /* module timing parameters */ + unsigned int minRasToCasDelay; + unsigned int minRowActiveRowActiveDelay; + unsigned int minRasPulseWidth; + unsigned int minRowPrechargeTime; /* measured in ns */ + + int addrAndCommandHoldTime; /* LoP left of point (measured in ns) */ + int addrAndCommandSetupTime; /* (measured in ns/100) */ + int dataInputSetupTime; /* LoP left of point (measured in ns) */ + int dataInputHoldTime; /* LoP left of point (measured in ns) */ +/* tAC times for highest 2nd and 3rd highest CAS Latency values */ + unsigned int clockToDataOut_LoP; /* LoP left of point (measured in ns) */ + unsigned int clockToDataOut_RoP; /* RoP right of point (measured in ns) */ + unsigned int clockToDataOutMinus1_LoP; /* LoP left of point (measured in ns) */ + unsigned int clockToDataOutMinus1_RoP; /* RoP right of point (measured in ns) */ + unsigned int clockToDataOutMinus2_LoP; /* LoP left of point (measured in ns) */ + unsigned int clockToDataOutMinus2_RoP; /* RoP right of point (measured in ns) */ + + unsigned int minimumCycleTimeAtMaxCasLatancy_LoP; /* LoP left of point (measured in ns) */ + unsigned int minimumCycleTimeAtMaxCasLatancy_RoP; /* RoP right of point (measured in ns) */ + + unsigned int minimumCycleTimeAtMaxCasLatancyMinus1_LoP; /* LoP left of point (measured in ns) */ + unsigned int minimumCycleTimeAtMaxCasLatancyMinus1_RoP; /* RoP right of point (measured in ns) */ + + unsigned int minimumCycleTimeAtMaxCasLatancyMinus2_LoP; /* LoP left of point (measured in ns) */ + unsigned int minimumCycleTimeAtMaxCasLatancyMinus2_RoP; /* RoP right of point (measured in ns) */ + + /* Parameters calculated from + the extracted DIMM information */ + unsigned int size; + unsigned int deviceDensity; /* 16,64,128,256 or 512 Mbit */ + unsigned int numberOfDevices; + uchar drb_size; /* DRAM size in n*64Mbit */ + uchar slot; /* Slot Number this module is inserted in */ + uchar spd_raw_data[128]; /* Content of SPD-EEPROM copied 1:1 */ +#ifdef DEBUG + uchar manufactura[8]; /* Content of SPD-EEPROM Byte 64-71 */ + uchar modul_id[18]; /* Content of SPD-EEPROM Byte 73-90 */ + uchar vendor_data[27]; /* Content of SPD-EEPROM Byte 99-125 */ + unsigned long modul_serial_no; /* Content of SPD-EEPROM Byte 95-98 */ + unsigned int manufac_date; /* Content of SPD-EEPROM Byte 93-94 */ + unsigned int modul_revision; /* Content of SPD-EEPROM Byte 91-92 */ + uchar manufac_place; /* Content of SPD-EEPROM Byte 72 */ + +#endif +} AUX_MEM_DIMM_INFO; + + +/* + * translate ns.ns/10 coding of SPD timing values + * into 10 ps unit values + */ +static inline unsigned short NS10to10PS (unsigned char spd_byte) +{ + unsigned short ns, ns10; + + /* isolate upper nibble */ + ns = (spd_byte >> 4) & 0x0F; + /* isolate lower nibble */ + ns10 = (spd_byte & 0x0F); + + return (ns * 100 + ns10 * 10); +} + +/* + * translate ns coding of SPD timing values + * into 10 ps unit values + */ +static inline unsigned short NSto10PS (unsigned char spd_byte) +{ + return (spd_byte * 100); +} + +/* This code reads the SPD chip on the sdram and populates + * the array which is passed in with the relevant information */ +/* static int check_dimm(uchar slot, AUX_MEM_DIMM_INFO *info) */ +static int check_dimm (uchar slot, AUX_MEM_DIMM_INFO * dimmInfo) +{ + DECLARE_GLOBAL_DATA_PTR; + + unsigned long spd_checksum; + +#ifdef ZUMA_NTL + /* zero all the values */ + memset (info, 0, sizeof (*info)); + +/* + if (!slot) { + info->slot = 0; + info->banks = 1; + info->registered = 0; + info->drb_size = 16;*/ /* 16 - 256MBit, 32 - 512MBit */ +/* info->tpar = 3; + info->tras_clocks = 5; + info->burst_len = 4; +*/ +#ifdef CONFIG_MV64360_ECC + /* check for ECC/parity [0 = none, 1 = parity, 2 = ecc] */ + dimmInfo->errorCheckType = 2; +/* info->ecc = 2;*/ +#endif +} + +return 0; + +#else + uchar addr = slot == 0 ? DIMM0_I2C_ADDR : DIMM1_I2C_ADDR; + int ret; + unsigned int i, j, density = 1, devicesForErrCheck = 0; + +#ifdef DEBUG + unsigned int k; +#endif + unsigned int rightOfPoint = 0, leftOfPoint = 0, mult, div, time_tmp; + int sign = 1, shift, maskLeftOfPoint, maskRightOfPoint; + uchar supp_cal, cal_val; + ulong memclk, tmemclk; + ulong tmp; + uchar trp_clocks = 0, trcd_clocks, tras_clocks, trrd_clocks; + uchar data[128]; + + memclk = gd->bus_clk; + tmemclk = 1000000000 / (memclk / 100); /* in 10 ps units */ + + DP (puts ("before i2c read\n")); + + ret = i2c_read (addr, 0, 1, data, 128); + + DP (puts ("after i2c read\n")); + + /* zero all the values */ + memset (dimmInfo, 0, sizeof (*dimmInfo)); + + /* copy the SPD content 1:1 into the dimmInfo structure */ + for (i = 0; i <= 127; i++) { + dimmInfo->spd_raw_data[i] = data[i]; + } + + if (ret) { + DP (printf ("No DIMM in slot %d [err = %x]\n", slot, ret)); + return 0; + } else + dimmInfo->slot = slot; /* start to fill up dimminfo for this "slot" */ + +#ifdef CFG_DISPLAY_DIMM_SPD_CONTENT + + for (i = 0; i <= 127; i++) { + printf ("SPD-EEPROM Byte %3d = %3x (%3d)\n", i, data[i], + data[i]); + } + +#endif +#ifdef DEBUG +/* find Manufactura of Dimm Module */ + for (i = 0; i < sizeof (dimmInfo->manufactura); i++) { + dimmInfo->manufactura[i] = data[64 + i]; + } + printf ("\nThis RAM-Module is produced by: %s\n", + dimmInfo->manufactura); + +/* find Manul-ID of Dimm Module */ + for (i = 0; i < sizeof (dimmInfo->modul_id); i++) { + dimmInfo->modul_id[i] = data[73 + i]; + } + printf ("The Module-ID of this RAM-Module is: %s\n", + dimmInfo->modul_id); + +/* find Vendor-Data of Dimm Module */ + for (i = 0; i < sizeof (dimmInfo->vendor_data); i++) { + dimmInfo->vendor_data[i] = data[99 + i]; + } + printf ("Vendor Data of this RAM-Module is: %s\n", + dimmInfo->vendor_data); + +/* find modul_serial_no of Dimm Module */ + dimmInfo->modul_serial_no = (*((unsigned long *) (&data[95]))); + printf ("Serial No. of this RAM-Module is: %ld (%lx)\n", + dimmInfo->modul_serial_no, dimmInfo->modul_serial_no); + +/* find Manufac-Data of Dimm Module */ + dimmInfo->manufac_date = (*((unsigned int *) (&data[93]))); + printf ("Manufactoring Date of this RAM-Module is: %d.%d\n", data[93], data[94]); /*dimmInfo->manufac_date */ + +/* find modul_revision of Dimm Module */ + dimmInfo->modul_revision = (*((unsigned int *) (&data[91]))); + printf ("Module Revision of this RAM-Module is: %d.%d\n", data[91], data[92]); /* dimmInfo->modul_revision */ + +/* find manufac_place of Dimm Module */ + dimmInfo->manufac_place = (*((unsigned char *) (&data[72]))); + printf ("manufac_place of this RAM-Module is: %d\n", + dimmInfo->manufac_place); + +#endif + +/*------------------------------------------------------------------------------------------------------------------------------*/ +/* calculate SPD checksum */ +/*------------------------------------------------------------------------------------------------------------------------------*/ + spd_checksum = 0; + + for (i = 0; i <= 62; i++) { + spd_checksum += data[i]; + } + + if ((spd_checksum & 0xff) != data[63]) { + printf ("### Error in SPD Checksum !!! Is_value: %2x should value %2x\n", (unsigned int) (spd_checksum & 0xff), data[63]); + hang (); + } + + else + printf ("SPD Checksum ok!\n"); + + +/*------------------------------------------------------------------------------------------------------------------------------*/ + for (i = 2; i <= 35; i++) { + switch (i) { + case 2: /* Memory type (DDR / SDRAM) */ + dimmInfo->memoryType = (data[i] == 0x7) ? DDR : SDRAM; +#ifdef DEBUG + if (dimmInfo->memoryType == 0) + DP (printf + ("Dram_type in slot %d is: SDRAM\n", + dimmInfo->slot)); + if (dimmInfo->memoryType == 1) + DP (printf + ("Dram_type in slot %d is: DDRAM\n", + dimmInfo->slot)); +#endif + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 3: /* Number Of Row Addresses */ + dimmInfo->numOfRowAddresses = data[i]; + DP (printf + ("Module Number of row addresses: %d\n", + dimmInfo->numOfRowAddresses)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 4: /* Number Of Column Addresses */ + dimmInfo->numOfColAddresses = data[i]; + DP (printf + ("Module Number of col addresses: %d\n", + dimmInfo->numOfColAddresses)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 5: /* Number Of Module Banks */ + dimmInfo->numOfModuleBanks = data[i]; + DP (printf + ("Number of Banks on Mod. : %d\n", + dimmInfo->numOfModuleBanks)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 6: /* Data Width */ + dimmInfo->dataWidth = data[i]; + DP (printf + ("Module Data Width: %d\n", + dimmInfo->dataWidth)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 8: /* Voltage Interface */ + switch (data[i]) { + case 0x0: + dimmInfo->voltageInterface = TTL_5V_TOLERANT; + DP (printf + ("Module is TTL_5V_TOLERANT\n")); + break; + case 0x1: + dimmInfo->voltageInterface = LVTTL; + DP (printf + ("Module is LVTTL\n")); + break; + case 0x2: + dimmInfo->voltageInterface = HSTL_1_5V; + DP (printf + ("Module is TTL_5V_TOLERANT\n")); + break; + case 0x3: + dimmInfo->voltageInterface = SSTL_3_3V; + DP (printf + ("Module is HSTL_1_5V\n")); + break; + case 0x4: + dimmInfo->voltageInterface = SSTL_2_5V; + DP (printf + ("Module is SSTL_2_5V\n")); + break; + default: + dimmInfo->voltageInterface = VOLTAGE_UNKNOWN; + DP (printf + ("Module is VOLTAGE_UNKNOWN\n")); + break; + } + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 9: /* Minimum Cycle Time At Max CasLatancy */ + shift = (dimmInfo->memoryType == DDR) ? 4 : 2; + mult = (dimmInfo->memoryType == DDR) ? 10 : 25; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf0 : 0xfc; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf : 0x03; + leftOfPoint = (data[i] & maskLeftOfPoint) >> shift; + rightOfPoint = (data[i] & maskRightOfPoint) * mult; + dimmInfo->minimumCycleTimeAtMaxCasLatancy_LoP = + leftOfPoint; + dimmInfo->minimumCycleTimeAtMaxCasLatancy_RoP = + rightOfPoint; + DP (printf + ("Minimum Cycle Time At Max CasLatancy: %d.%d [ns]\n", + leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 10: /* Clock To Data Out */ + div = (dimmInfo->memoryType == DDR) ? 100 : 10; + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / div; + rightOfPoint = time_tmp % div; + dimmInfo->clockToDataOut_LoP = leftOfPoint; + dimmInfo->clockToDataOut_RoP = rightOfPoint; + DP (printf ("Clock To Data Out: %d.%2d [ns]\n", leftOfPoint, rightOfPoint)); /*dimmInfo->clockToDataOut */ + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + +/*#ifdef CONFIG_ECC */ + case 11: /* Error Check Type */ + dimmInfo->errorCheckType = data[i]; + DP (printf + ("Error Check Type (0=NONE): %d\n", + dimmInfo->errorCheckType)); + break; +/* #endif */ +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 12: /* Refresh Interval */ + dimmInfo->RefreshInterval = data[i]; + DP (printf + ("RefreshInterval (80= Self refresh Normal, 15.625us) : %x\n", + dimmInfo->RefreshInterval)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 13: /* Sdram Width */ + dimmInfo->sdramWidth = data[i]; + DP (printf + ("Sdram Width: %d\n", + dimmInfo->sdramWidth)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 14: /* Error Check Data Width */ + dimmInfo->errorCheckDataWidth = data[i]; + DP (printf + ("Error Check Data Width: %d\n", + dimmInfo->errorCheckDataWidth)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 15: /* Minimum Clock Delay */ + dimmInfo->minClkDelay = data[i]; + DP (printf + ("Minimum Clock Delay: %d\n", + dimmInfo->minClkDelay)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 16: /* Burst Length Supported */ + /******-******-******-******* + * bit3 | bit2 | bit1 | bit0 * + *******-******-******-******* + burst length = * 8 | 4 | 2 | 1 * + ***************************** + + If for example bit0 and bit2 are set, the burst + length supported are 1 and 4. */ + + dimmInfo->burstLengthSupported = data[i]; +#ifdef DEBUG + DP (printf + ("Burst Length Supported: ")); + if (dimmInfo->burstLengthSupported & 0x01) + DP (printf ("1, ")); + if (dimmInfo->burstLengthSupported & 0x02) + DP (printf ("2, ")); + if (dimmInfo->burstLengthSupported & 0x04) + DP (printf ("4, ")); + if (dimmInfo->burstLengthSupported & 0x08) + DP (printf ("8, ")); + DP (printf (" Bit \n")); +#endif + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 17: /* Number Of Banks On Each Device */ + dimmInfo->numOfBanksOnEachDevice = data[i]; + DP (printf + ("Number Of Banks On Each Chip: %d\n", + dimmInfo->numOfBanksOnEachDevice)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 18: /* Suported Cas Latencies */ + + /* DDR: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | TBD | 3.5 | 3 | 2.5 | 2 | 1.5 | 1 * + ********************************************************* + SDRAM: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | 7 | 6 | 5 | 4 | 3 | 2 | 1 * + ********************************************************/ + dimmInfo->suportedCasLatencies = data[i]; +#ifdef DEBUG + DP (printf + ("Suported Cas Latencies: (CL) ")); + if (dimmInfo->memoryType == 0) { /* SDRAM */ + for (k = 0; k <= 7; k++) { + if (dimmInfo-> + suportedCasLatencies & (1 << k)) + DP (printf + ("%d, ", + k + 1)); + } + + } else { /* DDR-RAM */ + + if (dimmInfo->suportedCasLatencies & 1) + DP (printf ("1, ")); + if (dimmInfo->suportedCasLatencies & 2) + DP (printf ("1.5, ")); + if (dimmInfo->suportedCasLatencies & 4) + DP (printf ("2, ")); + if (dimmInfo->suportedCasLatencies & 8) + DP (printf ("2.5, ")); + if (dimmInfo->suportedCasLatencies & 16) + DP (printf ("3, ")); + if (dimmInfo->suportedCasLatencies & 32) + DP (printf ("3.5, ")); + + } + DP (printf ("\n")); +#endif + /* Calculating MAX CAS latency */ + for (j = 7; j > 0; j--) { + if (((dimmInfo-> + suportedCasLatencies >> j) & 0x1) == + 1) { + switch (dimmInfo->memoryType) { + case DDR: + /* CAS latency 1, 1.5, 2, 2.5, 3, 3.5 */ + switch (j) { + case 7: + DP (printf + ("Max. Cas Latencies (DDR): ERROR !!!\n")); + dimmInfo-> + maxClSupported_DDR + = + DDR_CL_FAULT; + hang (); + break; + case 6: + DP (printf + ("Max. Cas Latencies (DDR): ERROR !!!\n")); + dimmInfo-> + maxClSupported_DDR + = + DDR_CL_FAULT; + hang (); + break; + case 5: + DP (printf + ("Max. Cas Latencies (DDR): 3.5 clk's\n")); + dimmInfo-> + maxClSupported_DDR + = DDR_CL_3_5; + break; + case 4: + DP (printf + ("Max. Cas Latencies (DDR): 3 clk's \n")); + dimmInfo-> + maxClSupported_DDR + = DDR_CL_3; + break; + case 3: + DP (printf + ("Max. Cas Latencies (DDR): 2.5 clk's \n")); + dimmInfo-> + maxClSupported_DDR + = DDR_CL_2_5; + break; + case 2: + DP (printf + ("Max. Cas Latencies (DDR): 2 clk's \n")); + dimmInfo-> + maxClSupported_DDR + = DDR_CL_2; + break; + case 1: + DP (printf + ("Max. Cas Latencies (DDR): 1.5 clk's \n")); + dimmInfo-> + maxClSupported_DDR + = DDR_CL_1_5; + break; + } + + /* ronen - in case we have a DIMM with minimumCycleTimeAtMaxCasLatancy + lower then our SDRAM cycle count, we won't be able to support this CAL + and we will have to use lower CAL. (minus - means from 3.0 to 2.5) */ + if ((dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_LoP + < + CFG_DDR_SDRAM_CYCLE_COUNT_LOP) + || + ((dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_LoP + == + CFG_DDR_SDRAM_CYCLE_COUNT_LOP) + && (dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_RoP + < + CFG_DDR_SDRAM_CYCLE_COUNT_ROP))) + { + dimmInfo-> + maxClSupported_DDR + = + dimmInfo-> + maxClSupported_DDR + >> 1; + DP (printf + ("*** Change actual Cas Latencies cause of minimumCycleTime n")); + } + /* ronen - checkif the Dimm frequency compared to the Sysclock. */ + if ((dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_LoP + > + CFG_DDR_SDRAM_CYCLE_COUNT_LOP) + || + ((dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_LoP + == + CFG_DDR_SDRAM_CYCLE_COUNT_LOP) + && (dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_RoP + > + CFG_DDR_SDRAM_CYCLE_COUNT_ROP))) + { + printf ("*********************************************************\n"); + printf ("*** sysClock is higher than SDRAM's allowed frequency ***\n"); + printf ("*********************************************************\n"); + hang (); + } + + dimmInfo-> + maxCASlatencySupported_LoP + = + 1 + + (int) (5 * j / 10); + if (((5 * j) % 10) != 0) + dimmInfo-> + maxCASlatencySupported_RoP + = 5; + else + dimmInfo-> + maxCASlatencySupported_RoP + = 0; + DP (printf + ("Max. Cas Latencies (DDR LoP.RoP Notation): %d.%d \n", + dimmInfo-> + maxCASlatencySupported_LoP, + dimmInfo-> + maxCASlatencySupported_RoP)); + break; + case SDRAM: + /* CAS latency 1, 2, 3, 4, 5, 6, 7 */ + dimmInfo->maxClSupported_SD = j; /* Cas Latency DDR-RAM Coded */ + DP (printf + ("Max. Cas Latencies (SD): %d\n", + dimmInfo-> + maxClSupported_SD)); + dimmInfo-> + maxCASlatencySupported_LoP + = j; + dimmInfo-> + maxCASlatencySupported_RoP + = 0; + DP (printf + ("Max. Cas Latencies (DDR LoP.RoP Notation): %d.%d \n", + dimmInfo-> + maxCASlatencySupported_LoP, + dimmInfo-> + maxCASlatencySupported_RoP)); + break; + } + break; + } + } + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 21: /* Buffered Address And Control Inputs */ + DP (printf ("\nModul Attributes (SPD Byte 21): \n")); + dimmInfo->bufferedAddrAndControlInputs = + data[i] & BIT0; + dimmInfo->registeredAddrAndControlInputs = + (data[i] & BIT1) >> 1; + dimmInfo->onCardPLL = (data[i] & BIT2) >> 2; + dimmInfo->bufferedDQMBinputs = (data[i] & BIT3) >> 3; + dimmInfo->registeredDQMBinputs = + (data[i] & BIT4) >> 4; + dimmInfo->differentialClockInput = + (data[i] & BIT5) >> 5; + dimmInfo->redundantRowAddressing = + (data[i] & BIT6) >> 6; +#ifdef DEBUG + if (dimmInfo->bufferedAddrAndControlInputs == 1) + DP (printf + (" - Buffered Address/Control Input: Yes \n")); + else + DP (printf + (" - Buffered Address/Control Input: No \n")); + + if (dimmInfo->registeredAddrAndControlInputs == 1) + DP (printf + (" - Registered Address/Control Input: Yes \n")); + else + DP (printf + (" - Registered Address/Control Input: No \n")); + + if (dimmInfo->onCardPLL == 1) + DP (printf + (" - On-Card PLL (clock): Yes \n")); + else + DP (printf + (" - On-Card PLL (clock): No \n")); + + if (dimmInfo->bufferedDQMBinputs == 1) + DP (printf + (" - Bufferd DQMB Inputs: Yes \n")); + else + DP (printf + (" - Bufferd DQMB Inputs: No \n")); + + if (dimmInfo->registeredDQMBinputs == 1) + DP (printf + (" - Registered DQMB Inputs: Yes \n")); + else + DP (printf + (" - Registered DQMB Inputs: No \n")); + + if (dimmInfo->differentialClockInput == 1) + DP (printf + (" - Differential Clock Input: Yes \n")); + else + DP (printf + (" - Differential Clock Input: No \n")); + + if (dimmInfo->redundantRowAddressing == 1) + DP (printf + (" - redundant Row Addressing: Yes \n")); + else + DP (printf + (" - redundant Row Addressing: No \n")); + +#endif + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 22: /* Suported AutoPreCharge */ + DP (printf ("\nModul Attributes (SPD Byte 22): \n")); + dimmInfo->suportedEarlyRasPreCharge = data[i] & BIT0; + dimmInfo->suportedAutoPreCharge = + (data[i] & BIT1) >> 1; + dimmInfo->suportedPreChargeAll = + (data[i] & BIT2) >> 2; + dimmInfo->suportedWrite1ReadBurst = + (data[i] & BIT3) >> 3; + dimmInfo->suported5PercentLowVCC = + (data[i] & BIT4) >> 4; + dimmInfo->suported5PercentUpperVCC = + (data[i] & BIT5) >> 5; +#ifdef DEBUG + if (dimmInfo->suportedEarlyRasPreCharge == 1) + DP (printf + (" - Early Ras Precharge: Yes \n")); + else + DP (printf + (" - Early Ras Precharge: No \n")); + + if (dimmInfo->suportedAutoPreCharge == 1) + DP (printf + (" - AutoPreCharge: Yes \n")); + else + DP (printf + (" - AutoPreCharge: No \n")); + + if (dimmInfo->suportedPreChargeAll == 1) + DP (printf + (" - Precharge All: Yes \n")); + else + DP (printf + (" - Precharge All: No \n")); + + if (dimmInfo->suportedWrite1ReadBurst == 1) + DP (printf + (" - Write 1/ReadBurst: Yes \n")); + else + DP (printf + (" - Write 1/ReadBurst: No \n")); + + if (dimmInfo->suported5PercentLowVCC == 1) + DP (printf + (" - lower VCC tolerance: 5 Percent \n")); + else + DP (printf + (" - lower VCC tolerance: 10 Percent \n")); + + if (dimmInfo->suported5PercentUpperVCC == 1) + DP (printf + (" - upper VCC tolerance: 5 Percent \n")); + else + DP (printf + (" - upper VCC tolerance: 10 Percent \n")); + +#endif + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 23: /* Minimum Cycle Time At Maximum Cas Latancy Minus 1 (2nd highest CL) */ + shift = (dimmInfo->memoryType == DDR) ? 4 : 2; + mult = (dimmInfo->memoryType == DDR) ? 10 : 25; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf0 : 0xfc; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf : 0x03; + leftOfPoint = (data[i] & maskLeftOfPoint) >> shift; + rightOfPoint = (data[i] & maskRightOfPoint) * mult; + dimmInfo->minimumCycleTimeAtMaxCasLatancyMinus1_LoP = + leftOfPoint; + dimmInfo->minimumCycleTimeAtMaxCasLatancyMinus1_RoP = + rightOfPoint; + DP (printf ("Minimum Cycle Time At 2nd highest CasLatancy (0 = Not supported): %d.%d [ns]\n", leftOfPoint, rightOfPoint)); /*dimmInfo->minimumCycleTimeAtMaxCasLatancy */ + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 24: /* Clock To Data Out 2nd highest Cas Latency Value */ + div = (dimmInfo->memoryType == DDR) ? 100 : 10; + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / div; + rightOfPoint = time_tmp % div; + dimmInfo->clockToDataOutMinus1_LoP = leftOfPoint; + dimmInfo->clockToDataOutMinus1_RoP = rightOfPoint; + DP (printf + ("Clock To Data Out (2nd CL value): %d.%2d [ns]\n", + leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 25: /* Minimum Cycle Time At Maximum Cas Latancy Minus 2 (3rd highest CL) */ + shift = (dimmInfo->memoryType == DDR) ? 4 : 2; + mult = (dimmInfo->memoryType == DDR) ? 10 : 25; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf0 : 0xfc; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf : 0x03; + leftOfPoint = (data[i] & maskLeftOfPoint) >> shift; + rightOfPoint = (data[i] & maskRightOfPoint) * mult; + dimmInfo->minimumCycleTimeAtMaxCasLatancyMinus2_LoP = + leftOfPoint; + dimmInfo->minimumCycleTimeAtMaxCasLatancyMinus2_RoP = + rightOfPoint; + DP (printf ("Minimum Cycle Time At 3rd highest CasLatancy (0 = Not supported): %d.%d [ns]\n", leftOfPoint, rightOfPoint)); /*dimmInfo->minimumCycleTimeAtMaxCasLatancy */ + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 26: /* Clock To Data Out 3rd highest Cas Latency Value */ + div = (dimmInfo->memoryType == DDR) ? 100 : 10; + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / div; + rightOfPoint = time_tmp % div; + dimmInfo->clockToDataOutMinus2_LoP = leftOfPoint; + dimmInfo->clockToDataOutMinus2_RoP = rightOfPoint; + DP (printf + ("Clock To Data Out (3rd CL value): %d.%2d [ns]\n", + leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 27: /* Minimum Row Precharge Time */ + shift = (dimmInfo->memoryType == DDR) ? 2 : 0; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xfc : 0xff; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0x03 : 0x00; + leftOfPoint = ((data[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (data[i] & maskRightOfPoint) * 25; + + dimmInfo->minRowPrechargeTime = ((leftOfPoint * 100) + rightOfPoint); /* measured in n times 10ps Intervals */ + trp_clocks = + (dimmInfo->minRowPrechargeTime + + (tmemclk - 1)) / tmemclk; + DP (printf + ("*** 1 clock cycle = %ld 10ps intervalls = %ld.%ld ns****\n", + tmemclk, tmemclk / 100, tmemclk % 100)); + DP (printf + ("Minimum Row Precharge Time [ns]: %d.%2d = in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 28: /* Minimum Row Active to Row Active Time */ + shift = (dimmInfo->memoryType == DDR) ? 2 : 0; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xfc : 0xff; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0x03 : 0x00; + leftOfPoint = ((data[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (data[i] & maskRightOfPoint) * 25; + + dimmInfo->minRowActiveRowActiveDelay = ((leftOfPoint * 100) + rightOfPoint); /* measured in 100ns Intervals */ + trrd_clocks = + (dimmInfo->minRowActiveRowActiveDelay + + (tmemclk - 1)) / tmemclk; + DP (printf + ("Minimum Row Active -To- Row Active Delay [ns]: %d.%2d = in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 29: /* Minimum Ras-To-Cas Delay */ + shift = (dimmInfo->memoryType == DDR) ? 2 : 0; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xfc : 0xff; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0x03 : 0x00; + leftOfPoint = ((data[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (data[i] & maskRightOfPoint) * 25; + + dimmInfo->minRowActiveRowActiveDelay = ((leftOfPoint * 100) + rightOfPoint); /* measured in 100ns Intervals */ + trcd_clocks = + (dimmInfo->minRowActiveRowActiveDelay + + (tmemclk - 1)) / tmemclk; + DP (printf + ("Minimum Ras-To-Cas Delay [ns]: %d.%2d = in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 30: /* Minimum Ras Pulse Width */ + dimmInfo->minRasPulseWidth = data[i]; + tras_clocks = + (NSto10PS (data[i]) + + (tmemclk - 1)) / tmemclk; + DP (printf + ("Minimum Ras Pulse Width [ns]: %d = in Clk cycles %d\n", + dimmInfo->minRasPulseWidth, tras_clocks)); + + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 31: /* Module Bank Density */ + dimmInfo->moduleBankDensity = data[i]; + DP (printf + ("Module Bank Density: %d\n", + dimmInfo->moduleBankDensity)); +#ifdef DEBUG + DP (printf + ("*** Offered Densities (more than 1 = Multisize-Module): ")); + { + if (dimmInfo->moduleBankDensity & 1) + DP (printf ("4MB, ")); + if (dimmInfo->moduleBankDensity & 2) + DP (printf ("8MB, ")); + if (dimmInfo->moduleBankDensity & 4) + DP (printf ("16MB, ")); + if (dimmInfo->moduleBankDensity & 8) + DP (printf ("32MB, ")); + if (dimmInfo->moduleBankDensity & 16) + DP (printf ("64MB, ")); + if (dimmInfo->moduleBankDensity & 32) + DP (printf ("128MB, ")); + if ((dimmInfo->moduleBankDensity & 64) + || (dimmInfo->moduleBankDensity & 128)) { + DP (printf ("ERROR, ")); + hang (); + } + } + DP (printf ("\n")); +#endif + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 32: /* Address And Command Setup Time (measured in ns/1000) */ + sign = 1; + switch (dimmInfo->memoryType) { + case DDR: + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + break; + case SDRAM: + leftOfPoint = (data[i] & 0xf0) >> 4; + if (leftOfPoint > 7) { + leftOfPoint = data[i] & 0x70 >> 4; + sign = -1; + } + rightOfPoint = (data[i] & 0x0f); + break; + } + dimmInfo->addrAndCommandSetupTime = + (leftOfPoint * 100 + rightOfPoint) * sign; + DP (printf + ("Address And Command Setup Time [ns]: %d.%d\n", + sign * leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 33: /* Address And Command Hold Time */ + sign = 1; + switch (dimmInfo->memoryType) { + case DDR: + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + break; + case SDRAM: + leftOfPoint = (data[i] & 0xf0) >> 4; + if (leftOfPoint > 7) { + leftOfPoint = data[i] & 0x70 >> 4; + sign = -1; + } + rightOfPoint = (data[i] & 0x0f); + break; + } + dimmInfo->addrAndCommandHoldTime = + (leftOfPoint * 100 + rightOfPoint) * sign; + DP (printf + ("Address And Command Hold Time [ns]: %d.%d\n", + sign * leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 34: /* Data Input Setup Time */ + sign = 1; + switch (dimmInfo->memoryType) { + case DDR: + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + break; + case SDRAM: + leftOfPoint = (data[i] & 0xf0) >> 4; + if (leftOfPoint > 7) { + leftOfPoint = data[i] & 0x70 >> 4; + sign = -1; + } + rightOfPoint = (data[i] & 0x0f); + break; + } + dimmInfo->dataInputSetupTime = + (leftOfPoint * 100 + rightOfPoint) * sign; + DP (printf + ("Data Input Setup Time [ns]: %d.%d\n", + sign * leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 35: /* Data Input Hold Time */ + sign = 1; + switch (dimmInfo->memoryType) { + case DDR: + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + break; + case SDRAM: + leftOfPoint = (data[i] & 0xf0) >> 4; + if (leftOfPoint > 7) { + leftOfPoint = data[i] & 0x70 >> 4; + sign = -1; + } + rightOfPoint = (data[i] & 0x0f); + break; + } + dimmInfo->dataInputHoldTime = + (leftOfPoint * 100 + rightOfPoint) * sign; + DP (printf + ("Data Input Hold Time [ns]: %d.%d\n\n", + sign * leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + } + } + /* calculating the sdram density */ + for (i = 0; + i < dimmInfo->numOfRowAddresses + dimmInfo->numOfColAddresses; + i++) { + density = density * 2; + } + dimmInfo->deviceDensity = density * dimmInfo->numOfBanksOnEachDevice * + dimmInfo->sdramWidth; + dimmInfo->numberOfDevices = + (dimmInfo->dataWidth / dimmInfo->sdramWidth) * + dimmInfo->numOfModuleBanks; + devicesForErrCheck = + (dimmInfo->dataWidth - 64) / dimmInfo->sdramWidth; + if ((dimmInfo->errorCheckType == 0x1) + || (dimmInfo->errorCheckType == 0x2) + || (dimmInfo->errorCheckType == 0x3)) { + dimmInfo->size = + (dimmInfo->deviceDensity / 8) * + (dimmInfo->numberOfDevices - + /* ronen on the 1G dimm we get wrong value. (was devicesForErrCheck) */ + dimmInfo->numberOfDevices / 8); + } else { + dimmInfo->size = + (dimmInfo->deviceDensity / 8) * + dimmInfo->numberOfDevices; + } + + /* compute the module DRB size */ + tmp = (1 << + (dimmInfo->numOfRowAddresses + dimmInfo->numOfColAddresses)); + tmp *= dimmInfo->numOfModuleBanks; + tmp *= dimmInfo->sdramWidth; + tmp = tmp >> 24; /* div by 0x4000000 (64M) */ + dimmInfo->drb_size = (uchar) tmp; + DP (printf ("Module DRB size (n*64Mbit): %d\n", dimmInfo->drb_size)); + + /* try a CAS latency of 3 first... */ + + /* bit 1 is CL2, bit 2 is CL3 */ + supp_cal = (dimmInfo->suportedCasLatencies & 0x6) >> 1; + + cal_val = 0; + if (supp_cal & 3) { + if (NS10to10PS (data[9]) <= tmemclk) + cal_val = 3; + } + + /* then 2... */ + if (supp_cal & 2) { + if (NS10to10PS (data[23]) <= tmemclk) + cal_val = 2; + } + + DP (printf ("cal_val = %d\n", cal_val)); + + /* bummer, did't work... */ + if (cal_val == 0) { + DP (printf ("Couldn't find a good CAS latency\n")); + hang (); + return 0; + } + + return true; + +#endif +} + +/* sets up the GT properly with information passed in */ +int setup_sdram (AUX_MEM_DIMM_INFO * info) +{ + ulong tmp, check; + ulong tmp_sdram_mode = 0; /* 0x141c */ + ulong tmp_dunit_control_low = 0; /* 0x1404 */ + int i; + + /* added 8/21/2003 P. Marchese */ + unsigned int sdram_config_reg; + + /* added 10/10/2003 P. Marchese */ + ulong sdram_chip_size; + + /* sanity checking */ + if (!info->numOfModuleBanks) { + printf ("setup_sdram called with 0 banks\n"); + return 1; + } + + /* delay line */ + set_dfcdlInit (); /* may be its not needed */ + DP (printf ("Delay line set done\n")); + + /* set SDRAM mode NOP */ /* To_do check it */ + GT_REG_WRITE (SDRAM_OPERATION, 0x5); + while (GTREGREAD (SDRAM_OPERATION) != 0) { + DP (printf + ("\n*** SDRAM_OPERATION 1418: Module still busy ... please wait... ***\n")); + } + + /* SDRAM configuration */ +/* added 8/21/2003 P. Marchese */ +/* code allows usage of registered DIMMS */ + + /* figure out the memory refresh internal */ + switch (info->RefreshInterval) { + case 0x0: + case 0x80: /* refresh period is 15.625 usec */ + sdram_config_reg = + (unsigned int) (((float) 15.625 * (float) CFG_BUS_HZ) + / (float) 1000000.0); + break; + case 0x1: + case 0x81: /* refresh period is 3.9 usec */ + sdram_config_reg = + (unsigned int) (((float) 3.9 * (float) CFG_BUS_HZ) / + (float) 1000000.0); + break; + case 0x2: + case 0x82: /* refresh period is 7.8 usec */ + sdram_config_reg = + (unsigned int) (((float) 7.8 * (float) CFG_BUS_HZ) / + (float) 1000000.0); + break; + case 0x3: + case 0x83: /* refresh period is 31.3 usec */ + sdram_config_reg = + (unsigned int) (((float) 31.3 * (float) CFG_BUS_HZ) / + (float) 1000000.0); + break; + case 0x4: + case 0x84: /* refresh period is 62.5 usec */ + sdram_config_reg = + (unsigned int) (((float) 62.5 * (float) CFG_BUS_HZ) / + (float) 1000000.0); + break; + case 0x5: + case 0x85: /* refresh period is 125 usec */ + sdram_config_reg = + (unsigned int) (((float) 125 * (float) CFG_BUS_HZ) / + (float) 1000000.0); + break; + default: /* refresh period undefined */ + printf ("DRAM refresh period is unknown!\n"); + printf ("Aborting DRAM setup with an error\n"); + hang (); + break; + } + DP (printf ("calculated refresh interval %0x\n", sdram_config_reg)); + + /* make sure the refresh value is only 14 bits */ + if (sdram_config_reg > 0x1fff) + sdram_config_reg = 0x1fff; + DP (printf ("adjusted refresh interval %0x\n", sdram_config_reg)); + + /* we want physical bank interleaving and */ + /* virtual bank interleaving enabled so do nothing */ + /* since these bits need to be zero to enable the interleaving */ + + /* registered DRAM ? */ + if (info->registeredAddrAndControlInputs == 1) { + /* it's registered DRAM, so set the reg. DRAM bit */ + sdram_config_reg = sdram_config_reg | BIT17; + DP (printf ("Enabling registered DRAM bit\n")); + } + /* turn on DRAM ECC? */ +#ifdef CONFIG_MV64360_ECC + if (info->errorCheckType == 0x2) { + /* DRAM has ECC, so turn it on */ + sdram_config_reg = sdram_config_reg | BIT18; + DP (printf ("Enabling ECC\n")); + } +#endif + /* set the data DQS pin configuration */ + switch (info->sdramWidth) { + case 0x4: /* memory is x4 */ + sdram_config_reg = sdram_config_reg | BIT20 | BIT21; + DP (printf ("Data DQS pins set for 16 pins\n")); + break; + case 0x8: /* memory is x8 or x16 */ + case 0x10: + sdram_config_reg = sdram_config_reg | BIT21; + DP (printf ("Data DQS pins set for 8 pins\n")); + break; + case 0x20: /* memory is x32 */ + /* both bits are cleared for x32 so nothing to do */ + DP (printf ("Data DQS pins set for 2 pins\n")); + break; + default: /* memory width unsupported */ + printf ("DRAM chip width is unknown!\n"); + printf ("Aborting DRAM setup with an error\n"); + hang (); + break; + } + + /* perform read buffer assignments */ + /* we are going to use the Power-up defaults */ + /* bit 26 = CPU = buffer 1 */ + /* bit 27 = PCI bus #0 = buffer 0 */ + /* bit 28 = PCI bus #1 = buffer 0 */ + /* bit 29 = MPSC = buffer 0 */ + /* bit 30 = IDMA = buffer 0 */ + /* bit 31 = Gigabit = buffer 0 */ + sdram_config_reg = sdram_config_reg | BIT26; + /* sdram_config_reg = sdram_config_reg | 0x58000000; */ + /* sdram_config_reg = sdram_config_reg & 0xffffff00; */ + + /* write the value into the SDRAM configuration register */ + GT_REG_WRITE (SDRAM_CONFIG, sdram_config_reg); + DP (printf + ("OOOOOOOOO sdram_conf 0x1400: %08x\n", + GTREGREAD (SDRAM_CONFIG))); + + /* SDRAM open pages control keep open as much as I can */ + GT_REG_WRITE (SDRAM_OPEN_PAGES_CONTROL, 0x0); + DP (printf + ("sdram_open_pages_controll 0x1414: %08x\n", + GTREGREAD (SDRAM_OPEN_PAGES_CONTROL))); + + /* SDRAM D_UNIT_CONTROL_LOW 0x1404 */ + tmp = (GTREGREAD (D_UNIT_CONTROL_LOW) & 0x01); /* Clock Domain Sync from power on reset */ + if (tmp == 0) + DP (printf ("Core Signals are sync (by HW-Setting)!!!\n")); + else + DP (printf + ("Core Signals syncs. are bypassed (by HW-Setting)!!!\n")); + + /* SDRAM set CAS Latency according to SPD information */ + switch (info->memoryType) { + case SDRAM: + printf ("### SD-RAM not supported !!!\n"); + printf ("Aborting!!!\n"); + hang (); + /* ToDo fill SD-RAM if needed !!!!! */ + break; + /* Calculate the settings for SDRAM mode and Dunit control low registers */ + /* Values set according to technical bulletin TB-92 rev. c */ + case DDR: + DP (printf ("### SET-CL for DDR-RAM\n")); + switch (info->maxClSupported_DDR) { + case DDR_CL_3: + tmp_sdram_mode = 0x32; /* CL=3 Burstlength = 4 */ + if (tmp == 1) { /* clocks sync */ + if (info->registeredAddrAndControlInputs == 1) /* registerd DDR SDRAM? */ + tmp_dunit_control_low = 0x05110051; + else + tmp_dunit_control_low = 0x24110051; + DP (printf + ("Max. CL is 3 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } else { /* clk sync. bypassed */ + + if (info->registeredAddrAndControlInputs == 1) /* registerd DDR SDRAM? */ + tmp_dunit_control_low = 0x2C1107F2; + else + tmp_dunit_control_low = 0x3C1107d2; + DP (printf + ("Max. CL is 3 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } + break; + case DDR_CL_2_5: + tmp_sdram_mode = 0x62; /* CL=2.5 Burstlength = 4 */ + if (tmp == 1) { /* clocks sync */ + if (info->registeredAddrAndControlInputs == 1) /* registerd DDR SDRAM? */ + tmp_dunit_control_low = 0x25110051; + else + tmp_dunit_control_low = 0x24110051; + DP (printf + ("Max. CL is 2.5 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } else { /* clk sync. bypassed */ + + if (info->registeredAddrAndControlInputs == 1) { /* registerd DDR SDRAM? */ + printf ("CL = 2.5, Clock Unsync'ed, Dunit Control Low register setting undefined\n"); + printf ("Aborting!!!\n"); + hang (); + } else + tmp_dunit_control_low = 0x1B1107d2; + DP (printf + ("Max. CL is 2.5 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } + break; + case DDR_CL_2: + tmp_sdram_mode = 0x22; /* CL=2 Burstlength = 4 */ + if (tmp == 1) { /* clocks sync */ + if (info->registeredAddrAndControlInputs == 1) /* registerd DDR SDRAM? */ + tmp_dunit_control_low = 0x04110051; + else + tmp_dunit_control_low = 0x03110051; + DP (printf + ("Max. CL is 2 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } else { /* clk sync. bypassed */ + + if (info->registeredAddrAndControlInputs == 1) { /* registerd DDR SDRAM? */ + printf ("CL = 2, Clock Unsync'ed, Dunit Control Low register setting undefined\n"); + printf ("Aborting!!!\n"); + hang (); + } else + tmp_dunit_control_low = 0x3B1107d2; + DP (printf + ("Max. CL is 2 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } + break; + case DDR_CL_1_5: + tmp_sdram_mode = 0x52; /* CL=1.5 Burstlength = 4 */ + if (tmp == 1) { /* clocks sync */ + if (info->registeredAddrAndControlInputs == 1) /* registerd DDR SDRAM? */ + tmp_dunit_control_low = 0x24110051; + else + tmp_dunit_control_low = 0x23110051; + DP (printf + ("Max. CL is 1.5 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } else { /* clk sync. bypassed */ + + if (info->registeredAddrAndControlInputs == 1) { /* registerd DDR SDRAM? */ + printf ("CL = 1.5, Clock Unsync'ed, Dunit Control Low register setting undefined\n"); + printf ("Aborting!!!\n"); + hang (); + } else + tmp_dunit_control_low = 0x1A1107d2; + DP (printf + ("Max. CL is 1.5 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } + break; + + default: + printf ("Max. CL is out of range %d\n", + info->maxClSupported_DDR); + hang (); + break; + } /* end DDR switch */ + break; + } /* end CL switch */ + + /* Write results of CL detection procedure */ + /* set SDRAM mode reg. 0x141c */ + GT_REG_WRITE (SDRAM_MODE, tmp_sdram_mode); + + /* set SDRAM mode SetCommand 0x1418 */ + GT_REG_WRITE (SDRAM_OPERATION, 0x3); + while (GTREGREAD (SDRAM_OPERATION) != 0) { + DP (printf + ("\n*** SDRAM_OPERATION 0x1418 after SDRAM_MODE: Module still busy ... please wait... ***\n")); + } + + /* SDRAM D_UNIT_CONTROL_LOW 0x1404 */ + GT_REG_WRITE (D_UNIT_CONTROL_LOW, tmp_dunit_control_low); + + /* set SDRAM mode SetCommand 0x1418 */ + GT_REG_WRITE (SDRAM_OPERATION, 0x3); + while (GTREGREAD (SDRAM_OPERATION) != 0) { + DP (printf + ("\n*** SDRAM_OPERATION 1418 after D_UNIT_CONTROL_LOW: Module still busy ... please wait... ***\n")); + } + +/*------------------------------------------------------------------------------ */ + + /* bank parameters */ + /* SDRAM address decode register 0x1410 */ + /* program this with the default value */ + tmp = 0x02; /* power-up default address select decoding value */ + + DP (printf ("drb_size (n*64Mbit): %d\n", info->drb_size)); +/* figure out the DRAM chip size */ + sdram_chip_size = + (1 << (info->numOfRowAddresses + info->numOfColAddresses)); + sdram_chip_size *= info->sdramWidth; + sdram_chip_size *= 4; + DP (printf ("computed sdram chip size is %#lx\n", sdram_chip_size)); + /* divide sdram chip size by 64 Mbits */ + sdram_chip_size = sdram_chip_size / 0x4000000; + switch (sdram_chip_size) { + case 1: /* 64 Mbit */ + case 2: /* 128 Mbit */ + DP (printf ("RAM-Device_size 64Mbit or 128Mbit)\n")); + tmp |= (0x00 << 4); + break; + case 4: /* 256 Mbit */ + case 8: /* 512 Mbit */ + DP (printf ("RAM-Device_size 256Mbit or 512Mbit)\n")); + tmp |= (0x01 << 4); + break; + case 16: /* 1 Gbit */ + case 32: /* 2 Gbit */ + DP (printf ("RAM-Device_size 1Gbit or 2Gbit)\n")); + tmp |= (0x02 << 4); + break; + default: + printf ("Error in dram size calculation\n"); + printf ("RAM-Device_size is unsupported\n"); + hang (); + } + + /* SDRAM address control */ + GT_REG_WRITE (SDRAM_ADDR_CONTROL, tmp); + DP (printf + ("setting up sdram address control (0x1410) with: %08lx \n", + tmp)); + +/* ------------------------------------------------------------------------------ */ +/* same settings for registerd & non-registerd DDR SDRAM */ + DP (printf + ("setting up sdram_timing_control_low (0x1408) with: %08x \n", + 0x11511220)); + GT_REG_WRITE (SDRAM_TIMING_CONTROL_LOW, 0x11511220); + + +/* ------------------------------------------------------------------------------ */ + + /* SDRAM configuration */ + tmp = GTREGREAD (SDRAM_CONFIG); + + if (info->registeredAddrAndControlInputs + || info->registeredDQMBinputs) { + tmp |= (1 << 17); + DP (printf + ("SPD says: registered Addr. and Cont.: %d; registered DQMBinputs: %d\n", + info->registeredAddrAndControlInputs, + info->registeredDQMBinputs)); + } + + /* Use buffer 1 to return read data to the CPU + * Page 426 MV64360 */ + tmp |= (1 << 26); + DP (printf + ("Before Buffer assignment - sdram_conf (0x1400): %08x\n", + GTREGREAD (SDRAM_CONFIG))); + DP (printf + ("After Buffer assignment - sdram_conf (0x1400): %08x\n", + GTREGREAD (SDRAM_CONFIG))); + + /* SDRAM timing To_do: */ +/* ------------------------------------------------------------------------------ */ + + DP (printf + ("setting up sdram_timing_control_high (0x140c) with: %08x \n", + 0x9)); + GT_REG_WRITE (SDRAM_TIMING_CONTROL_HIGH, 0x9); + + DP (printf + ("setting up sdram address pads control (0x14c0) with: %08x \n", + 0x7d5014a)); + GT_REG_WRITE (SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x7d5014a); + + DP (printf + indent: Standard input:1450: Warning:old style assignment ambiguity in "=*". Assuming "= *" + +indent: Standard input:1451: Warning:old style assignment ambiguity in "=*". Assuming "= *" + + ("setting up sdram data pads control (0x14c4) with: %08x \n", + 0x7d5014a)); + GT_REG_WRITE (SDRAM_DATA_PADS_CALIBRATION, 0x7d5014a); + +/* ------------------------------------------------------------------------------ */ + + /* set the SDRAM configuration for each bank */ + +/* for (i = info->slot * 2; i < ((info->slot * 2) + info->banks); i++) */ + { + i = info->slot; + DP (printf + ("\n*** Running a MRS cycle for bank %d ***\n", i)); + + /* map the bank */ + memory_map_bank (i, 0, GB / 4); + + /* set SDRAM mode */ /* To_do check it */ + GT_REG_WRITE (SDRAM_OPERATION, 0x3); + check = GTREGREAD (SDRAM_OPERATION); + DP (printf + ("\n*** SDRAM_OPERATION 1418 (0 = Normal Operation) = %08lx ***\n", + check)); + + + /* switch back to normal operation mode */ + GT_REG_WRITE (SDRAM_OPERATION, 0); + check = GTREGREAD (SDRAM_OPERATION); + DP (printf + ("\n*** SDRAM_OPERATION 1418 (0 = Normal Operation) = %08lx ***\n", + check)); + + /* unmap the bank */ + memory_map_bank (i, 0, 0); + } + + 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; +} + +/* ------------------------------------------------------------------------- */ + +/* ppcboot interface function to SDRAM init - this is where all the + * controlling logic happens */ +long int initdram (int board_type) +{ + int s0 = 0, s1 = 0; + int checkbank[4] = {[0 ... 3] = 0 }; + ulong realsize, total, check; + AUX_MEM_DIMM_INFO dimmInfo1; + AUX_MEM_DIMM_INFO dimmInfo2; + int nhr, bank_no; + ulong dest, memSpaceAttr; + + /* first, use the SPD to get info about the SDRAM/ DDRRAM */ + + /* check the NHR bit and skip mem init if it's already done */ + nhr = get_hid0 () & (1 << 16); + + if (nhr) { + printf ("Skipping SD- DDRRAM setup due to NHR bit being set\n"); + } else { + /* DIMM0 */ + s0 = check_dimm (0, &dimmInfo1); + + /* DIMM1 */ + s1 = check_dimm (1, &dimmInfo2); + + memory_map_bank (0, 0, 0); + memory_map_bank (1, 0, 0); + memory_map_bank (2, 0, 0); + memory_map_bank (3, 0, 0); + + /* ronen check correct set of DIMMS */ + if (dimmInfo1.numOfModuleBanks && dimmInfo2.numOfModuleBanks) { + if (dimmInfo1.errorCheckType != + dimmInfo2.errorCheckType) + printf ("***WARNNING***!!!! different ECC support of the DIMMS\n"); + if (dimmInfo1.maxClSupported_DDR != + dimmInfo2.maxClSupported_DDR) + printf ("***WARNNING***!!!! different CAL setting of the DIMMS\n"); + if (dimmInfo1.registeredAddrAndControlInputs != + dimmInfo2.registeredAddrAndControlInputs) + printf ("***WARNNING***!!!! different Registration setting of the DIMMS\n"); + } + + if (dimmInfo1.numOfModuleBanks && setup_sdram (&dimmInfo1)) { + printf ("Setup for DIMM1 failed.\n"); + } + + if (dimmInfo2.numOfModuleBanks && setup_sdram (&dimmInfo2)) { + printf ("Setup for DIMM2 failed.\n"); + } + + /* set the NHR bit */ + set_hid0 (get_hid0 () | (1 << 16)); + } + /* next, size the SDRAM banks */ + + realsize = total = 0; + check = GB / 4; + if (dimmInfo1.numOfModuleBanks > 0) { + checkbank[0] = 1; + } + if (dimmInfo1.numOfModuleBanks > 1) { + checkbank[1] = 1; + } + if (dimmInfo1.numOfModuleBanks > 2) + printf ("Error, SPD claims DIMM1 has >2 banks\n"); + + printf ("-- DIMM1 has %d banks\n", dimmInfo1.numOfModuleBanks); + + if (dimmInfo2.numOfModuleBanks > 0) { + checkbank[2] = 1; + } + if (dimmInfo2.numOfModuleBanks > 1) { + checkbank[3] = 1; + } + if (dimmInfo2.numOfModuleBanks > 2) + printf ("Error, SPD claims DIMM2 has >2 banks\n"); + + printf ("-- DIMM2 has %d banks\n", dimmInfo2.numOfModuleBanks); + + for (bank_no = 0; bank_no < CFG_DRAM_BANKS; bank_no++) { + /* skip over banks that are not populated */ + if (!checkbank[bank_no]) + continue; + + /* ronen - realsize = dram_size((long int *)total, check); */ + if (bank_no == 0 || bank_no == 1) { + if (checkbank[1] == 1) + realsize = dimmInfo1.size / 2; + else + realsize = dimmInfo1.size; + } + if (bank_no == 2 || bank_no == 3) { + if (checkbank[3] == 1) + realsize = dimmInfo2.size / 2; + else + realsize = dimmInfo2.size; + } + memory_map_bank (bank_no, total, realsize); + + /* ronen - initialize the DRAM for ECC */ +#ifdef CONFIG_MV64360_ECC + if ((dimmInfo1.errorCheckType != 0) && + ((dimmInfo2.errorCheckType != 0) + || (dimmInfo2.numOfModuleBanks == 0))) { + printf ("ECC Initialization of Bank %d:", bank_no); + memSpaceAttr = ((~(BIT0 << bank_no)) & 0xf) << 8; + mvDmaSetMemorySpace (0, 0, memSpaceAttr, total, + realsize); + for (dest = total; dest < total + realsize; + dest += _8M) { + mvDmaTransfer (0, total, dest, _8M, + BIT8 /*DMA_DTL_128BYTES */ | + BIT3 /*DMA_HOLD_SOURCE_ADDR */ + | + BIT11 + /*DMA_BLOCK_TRANSFER_MODE */ ); + while (mvDmaIsChannelActive (0)); + } + printf (" PASS\n"); + } +#endif + + total += realsize; + } + + /* ronen- add DRAM conf prints */ + switch ((GTREGREAD (0x141c) >> 4) & 0x7) { + case 0x2: + printf ("CAS Latency = 2"); + break; + case 0x3: + printf ("CAS Latency = 3"); + break; + case 0x5: + printf ("CAS Latency = 1.5"); + break; + case 0x6: + printf ("CAS Latency = 2.5"); + break; + } + printf (" tRP = %d tRAS = %d tRCD=%d\n", + ((GTREGREAD (0x1408) >> 8) & 0xf) + 1, + ((GTREGREAD (0x1408) >> 20) & 0xf) + 1, + ((GTREGREAD (0x1408) >> 4) & 0xf) + 1); + +/* Setup Ethernet DMA Adress window to DRAM Area */ + if (total > _256M) + printf ("*** ONLY the first 256MB DRAM memory are used out of the "); + else + printf ("Total SDRAM memory is "); + /* (cause all the 4 BATS are taken) */ + return (total); +} + + +/* ronen- add Idma functions for usage of the ecc dram init. */ +/******************************************************************************* +* mvDmaIsChannelActive - Checks if a engine is busy. +********************************************************************************/ +int mvDmaIsChannelActive (int engine) +{ + ulong data; + + data = GTREGREAD (MV64360_DMA_CHANNEL0_CONTROL + 4 * engine); + if (data & BIT14 /*activity status */ ) { + return 1; + } + return 0; +} + +/******************************************************************************* +* mvDmaSetMemorySpace - Set a DMA memory window for the DMA's address decoding +* map. +*******************************************************************************/ +int mvDmaSetMemorySpace (ulong memSpace, + ulong memSpaceTarget, + ulong memSpaceAttr, ulong baseAddress, ulong size) +{ + ulong temp; + + /* The base address must be aligned to the size. */ + if (baseAddress % size != 0) { + return 0; + } + if (size >= 0x10000 /*64K */ ) { + size &= 0xffff0000; + baseAddress = (baseAddress & 0xffff0000); + /* Set the new attributes */ + GT_REG_WRITE (MV64360_DMA_BASE_ADDR_REG0 + memSpace * 8, + (baseAddress | memSpaceTarget | memSpaceAttr)); + GT_REG_WRITE ((MV64360_DMA_SIZE_REG0 + memSpace * 8), + (size - 1) & 0xffff0000); + temp = GTREGREAD (MV64360_DMA_BASE_ADDR_ENABLE_REG); + GT_REG_WRITE (DMA_BASE_ADDR_ENABLE_REG, + (temp & ~(BIT0 << memSpace))); + return 1; + } + return 0; +} + + +/******************************************************************************* +* mvDmaTransfer - Transfer data from sourceAddr to destAddr on one of the 4 +* DMA channels. +********************************************************************************/ +int mvDmaTransfer (int engine, ulong sourceAddr, + ulong destAddr, ulong numOfBytes, ulong command) +{ + ulong engOffReg = 0; /* Engine Offset Register */ + + if (numOfBytes > 0xffff) { + command = command | BIT31 /*DMA_16M_DESCRIPTOR_MODE */ ; + } + command = command | ((command >> 6) & 0x7); + engOffReg = engine * 4; + GT_REG_WRITE (MV64360_DMA_CHANNEL0_BYTE_COUNT + engOffReg, + numOfBytes); + GT_REG_WRITE (MV64360_DMA_CHANNEL0_SOURCE_ADDR + engOffReg, + sourceAddr); + GT_REG_WRITE (MV64360_DMA_CHANNEL0_DESTINATION_ADDR + engOffReg, + destAddr); + command = + command | BIT12 /*DMA_CHANNEL_ENABLE */ | BIT9 + /*DMA_NON_CHAIN_MODE */ ; + /* Activate DMA engine By writting to mvDmaControlRegister */ + GT_REG_WRITE (MV64360_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; + unsigned int dfcdl_word = 0x391; /* 0x14f; ronen new dfcdl */ + + for (i = 0; i < 64; i++) { + GT_REG_WRITE (SRAM_DATA0, dfcdl_word); +/* dfcdl_word += 0x41; - ronen new dfcdl */ + } + GT_REG_WRITE (DFCDL_CONFIG0, 0x00300000); /* enable dynamic delay line updating */ + + return (0); +} diff --git a/board/Marvell/db64360/u-boot.lds b/board/Marvell/db64360/u-boot.lds new file mode 100644 index 0000000..0dfa8c0 --- /dev/null +++ b/board/Marvell/db64360/u-boot.lds @@ -0,0 +1,135 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, 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) + } + .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/board/Marvell/db64460/64460.h b/board/Marvell/db64460/64460.h new file mode 100644 index 0000000..8bb0ebf --- /dev/null +++ b/board/Marvell/db64460/64460.h @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * 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/Marvell/db64460/Makefile b/board/Marvell/db64460/Makefile new file mode 100644 index 0000000..768ccdd --- /dev/null +++ b/board/Marvell/db64460/Makefile @@ -0,0 +1,44 @@ +# +# (C) Copyright 2001 +# Josh Huber <huber@mclx.com>, 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 +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +SOBJS = ../common/misc.o + +OBJS = $(BOARD).o ../common/flash.o ../common/serial.o ../common/memory.o pci.o \ + mv_eth.o ../common/ns16550.o mpsc.o ../common/i2c.o \ + sdram_init.o ../common/intel_flash.o + +$(LIB): .depend $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) $(SOBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/Marvell/db64460/config.mk b/board/Marvell/db64460/config.mk new file mode 100644 index 0000000..5a434d9 --- /dev/null +++ b/board/Marvell/db64460/config.mk @@ -0,0 +1,28 @@ +# +# (C) Copyright 2001 +# Josh Huber <huber@mclx.com>, 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 +# + +# +# EVB64460 boards +# + +TEXT_BASE = 0xfff00000 diff --git a/board/Marvell/db64460/db64460.c b/board/Marvell/db64460/db64460.c new file mode 100644 index 0000000..572dc47 --- /dev/null +++ b/board/Marvell/db64460/db64460.c @@ -0,0 +1,936 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, 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 DB64460 eval board based by Ingo.Assmus@keymile.com + */ + +/* + * db64460.c - main board support/init for the Galileo Eval board. + */ + +#include <common.h> +#include <74xx_7xx.h> +#include "../include/memory.h" +#include "../include/pci.h" +#include "../include/mv_gen_reg.h" +#include <net.h> + +#include "eth.h" +#include "mpsc.h" +#include "i2c.h" +#include "64460.h" +#include "mv_regs.h" + +#undef DEBUG +/*#define DEBUG */ + +#define MAP_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); + +/* ------------------------------------------------------------------------- */ + +/* 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_pre_init 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 */ + +/* original ppcboot 1.1.6 source + + temp = in_le32((u32 *)(new_loc + INTERNAL_SPACE_DECODE)); + if ((temp & 0xffff) == new_loc >> 20) + return; + + temp = (in_le32((u32 *)(cur_loc + INTERNAL_SPACE_DECODE)) & + 0xffff0000) | (new_loc >> 20); + + out_le32((u32 *)(cur_loc + INTERNAL_SPACE_DECODE), temp); + + while (GTREGREAD(INTERNAL_SPACE_DECODE) != temp); +original ppcboot 1.1.6 source end */ + + 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_BASE >> 16); + GT_REG_WRITE (PCI_0I_O_ADDRESS_REMAP, CFG_PCI0_IO_BASE >> 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_BASE >> 16); + GT_REG_WRITE (PCI_1I_O_ADDRESS_REMAP, CFG_PCI1_IO_BASE >> 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 P.399 */ +#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_pre_init. + * + * set up gal. device mappings, etc. + */ +int board_pre_init (void) +{ + uchar sram_boot = 0; + + /* + * 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); + + /* No PCI in first release of Port To_do: enable it. */ +#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 MV6446x */ + 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); + /* does not exist in MV6446x + GT_REG_WRITE(CPU_INT_0_MASK, 0); + GT_REG_WRITE(CPU_INT_1_MASK, 0); + GT_REG_WRITE(CPU_INT_2_MASK, 0); + GT_REG_WRITE(CPU_INT_3_MASK, 0); + --------------------- */ + + + /* ----- DEVICE BUS SETTINGS ------ */ + + /* + * EVB + * 0 - SRAM ???? + * 1 - RTC ???? + * 2 - UART ???? + * 3 - Flash checked 32Bit Intel Strata + * boot - BootCS checked 8Bit 29LV040B + * + * Zuma + * 0 - Flash + * boot - BootCS + */ + + /* + * the dual 7450 module requires burst access to the boot + * device, so the serial rom copies the boot device to the + * on-board sram on the eval board, and updates the correct + * registers to boot from the sram. (device0) + */ + if (memoryGetDeviceBaseAddress (DEVICE0) == CFG_DFL_BOOTCS_BASE) + sram_boot = 1; + if (!sram_boot) + memoryMapDeviceSpace (DEVICE0, CFG_DEV0_SPACE, CFG_DEV0_SIZE); + + memoryMapDeviceSpace (DEVICE1, CFG_DEV1_SPACE, CFG_DEV1_SIZE); + memoryMapDeviceSpace (DEVICE2, CFG_DEV2_SPACE, CFG_DEV2_SIZE); + memoryMapDeviceSpace (DEVICE3, CFG_DEV3_SPACE, CFG_DEV3_SIZE); + + + /* configure device timing */ +#ifdef CFG_DEV0_PAR /* set port parameters for SRAM device module access */ + if (!sram_boot) + GT_REG_WRITE (DEVICE_BANK0PARAMETERS, CFG_DEV0_PAR); +#endif + +#ifdef CFG_DEV1_PAR /* set port parameters for RTC device module access */ + GT_REG_WRITE (DEVICE_BANK1PARAMETERS, CFG_DEV1_PAR); +#endif +#ifdef CFG_DEV2_PAR /* set port parameters for DUART device module access */ + GT_REG_WRITE (DEVICE_BANK2PARAMETERS, CFG_DEV2_PAR); +#endif + +#ifdef CFG_32BIT_BOOT_PAR /* set port parameters for Flash device module access */ + /* detect if we are booting from the 32 bit flash */ + if (GTREGREAD (DEVICE_BOOT_BANK_PARAMETERS) & (0x3 << 20)) { + /* 32 bit boot flash */ + GT_REG_WRITE (DEVICE_BANK3PARAMETERS, CFG_8BIT_BOOT_PAR); + GT_REG_WRITE (DEVICE_BOOT_BANK_PARAMETERS, + CFG_32BIT_BOOT_PAR); + } else { + /* 8 bit boot flash */ + GT_REG_WRITE (DEVICE_BANK3PARAMETERS, CFG_32BIT_BOOT_PAR); + GT_REG_WRITE (DEVICE_BOOT_BANK_PARAMETERS, CFG_8BIT_BOOT_PAR); + } +#else + /* 8 bit boot flash only */ +/* GT_REG_WRITE(DEVICE_BOOT_BANK_PARAMETERS, CFG_8BIT_BOOT_PAR);*/ +#endif + + + 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); + DEBUG_LED0_ON (); + DEBUG_LED1_ON (); + DEBUG_LED2_ON (); + + return 0; +} + +/* various things to do after relocation */ + +int misc_init_r () +{ + icache_enable (); +#ifdef CFG_L2 + l2cache_enable (); +#endif +#ifdef CONFIG_MPSC + + mpsc_sdma_init (); + mpsc_init2 (); +#endif + +#if 0 + /* disable the dcache and MMU */ + dcache_lock (); +#endif + return 0; +} + +void after_reloc (ulong dest_addr, gd_t * gd) +{ + /* check to see if we booted from the sram. If so, move things + * back to the way they should be. (we're running from main + * memory at this point now */ + if (memoryGetDeviceBaseAddress (DEVICE0) == CFG_DFL_BOOTCS_BASE) { + memoryMapDeviceSpace (DEVICE0, CFG_DEV0_SPACE, CFG_DEV0_SIZE); + memoryMapDeviceSpace (BOOT_DEVICE, CFG_DFL_BOOTCS_BASE, _8M); + } + display_mem_map (); + /* now, jump to the main ppcboot 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) +{ + int l_type = 0; + + printf ("BOARD: %s\n", CFG_BOARD_NAME); + return (l_type); +} + +/* utility functions */ +void debug_led (int led, int mode) +{ + volatile int *addr = 0; + int dummy; + + if (mode == 1) { + switch (led) { + case 0: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x08000); + break; + + case 1: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x0c000); + break; + + case 2: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x10000); + break; + } + } else if (mode == 0) { + switch (led) { + case 0: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x14000); + break; + + case 1: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x18000); + break; + + case 2: + addr = (int *) ((unsigned int) CFG_DEV1_SPACE | + 0x1c000); + break; + } + } + + dummy = *addr; +} + +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); + } + } + + /* 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); + for (j = 0; + j <= + PCI_REGION0 + /*ronen currently only first PCI MEM is used 3 */ ; + j++) { + base = pciGetSpaceBase (i, j); + size = pciGetSpaceSize (i, j); + printf ("MEMORY %d: base - 0x%08x\tsize - %dM bytes\n", j, base, size >> 20); + } + } + + /* Devices */ + printf ("\nDEVICES\n"); + for (i = 0; i <= DEVICE3; i++) { + base = memoryGetDeviceBaseAddress (i); + size = memoryGetDeviceSize (i); + width = memoryGetDeviceWidth (i) * 8; + printf ("DEV %d: base - 0x%08x size - %dM bytes\twidth - %d bits", i, base, size >> 20, width); + if (i == 0) + printf ("\t- EXT SRAM (actual - 1M)\n"); + else if (i == 1) + printf ("\t- RTC\n"); + else if (i == 2) + printf ("\t- UART\n"); + else + printf ("\t- LARGE FLASH\n"); + } + + /* 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\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[] = { + 0xaaaaaaaaaaaaaaaa, + 0xcccccccccccccccc, + 0xf0f0f0f0f0f0f0f0, + 0xff00ff00ff00ff00, + 0xffff0000ffff0000, + 0xffffffff00000000, + 0x00000000ffffffff, + 0x0000ffff0000ffff, + 0x00ff00ff00ff00ff, + 0x0f0f0f0f0f0f0f0f, + 0x3333333333333333, + 0x5555555555555555 +}; + +/*********************************************************************/ +/* 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; + 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; + 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, runaddress, runwalk; + + s = getenv ("testdramdata"); + rundata = (s && (*s == 'y')) ? 1 : 0; + s = getenv ("testdramaddress"); + runaddress = (s && (*s == 'y')) ? 1 : 0; + s = getenv ("testdramwalk"); + runwalk = (s && (*s == 'y')) ? 1 : 0; + +/* rundata = 1; */ +/* runaddress = 0; */ +/* runwalk = 0; */ + + 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); + +} + +void board_prebootm_init () +{ + +/* change window size of PCI1 IO in order tp prevent overlaping with REG BASE. */ + GT_REG_WRITE (PCI_1_IO_SIZE, (_64K - 1) >> 16); + +/* Stop GigE Rx DMA engines */ + GT_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (0), 0x0000ff00); + GT_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (1), 0x0000ff00); + GT_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (2), 0x0000ff00); + +/* Relocate MV64460 internal regs */ + my_remap_gt_regs_bootm (CFG_GT_REGS, BRIDGE_REG_BASE_BOOTM); + + icache_disable (); + invalidate_l1_instruction_cache (); + flush_data_cache (); + dcache_disable (); +} diff --git a/board/Marvell/db64460/eth.h b/board/Marvell/db64460/eth.h new file mode 100644 index 0000000..6c3b2e0 --- /dev/null +++ b/board/Marvell/db64460/eth.h @@ -0,0 +1,41 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, 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 __EVB64460_ETH_H__ +#define __EVB64460_ETH_H__ + +#include <asm/types.h> +#include <asm/io.h> +#include <asm/byteorder.h> +#include <common.h> + +int db64460_eth0_poll(void); +int db64460_eth0_transmit(unsigned int s, volatile char *p); +void db64460_eth0_disable(void); +bool network_start(bd_t *bis); + +#endif /* __EVB64460_ETH_H__ */ diff --git a/board/Marvell/db64460/mpsc.c b/board/Marvell/db64460/mpsc.c new file mode 100644 index 0000000..33fbc49 --- /dev/null +++ b/board/Marvell/db64460/mpsc.c @@ -0,0 +1,1019 @@ +/* + * (C) Copyright 2001 + * John Clemens <clemens@mclx.com>, 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 <ingo.assmus@keymile.com> + * + ************************************************************************/ + +/* + * mpsc.c - driver for console over the MPSC. + */ + + +#include <common.h> +#include <config.h> +#include <asm/cache.h> + +#include <malloc.h> +#include "mpsc.h" + +#include "mv_regs.h" + +#include "../include/memory.h" + +/* 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_indent: Standard input:229: Warning:old style assignment ambiguity in "=&". Assuming "= &" + +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) +{ + DECLARE_GLOBAL_DATA_PTR; + 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 Bank0 */ + if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT, + MV64460_SDMA_DRAM_CS_0_TARGET, + 0, + memoryGetBankBaseAddress + (CS_0_LOW_DECODE_ADDRESS), + memoryGetBankSize (BANK0)) != true) + printf ("%s: SDMA_Window0 memory setup failed !!! \n", + __FUNCTION__); + + +/* Disable MPSC-Window1 */ + if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_1_BIT, + MV64460_SDMA_DRAM_CS_0_TARGET, + 0, + memoryGetBankBaseAddress + (CS_1_LOW_DECODE_ADDRESS), + memoryGetBankSize (BANK3)) != 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_0_TARGET, + 0, + memoryGetBankBaseAddress + (CS_2_LOW_DECODE_ADDRESS), + memoryGetBankSize (BANK3)) != 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_0_TARGET, + 0, + memoryGetBankBaseAddress + (CS_3_LOW_DECODE_ADDRESS), + memoryGetBankSize (BANK3)) != 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) +{ + DECLARE_GLOBAL_DATA_PTR; + 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/Marvell/db64460/mpsc.h b/board/Marvell/db64460/mpsc.h new file mode 100644 index 0000000..3cc0c0f --- /dev/null +++ b/board/Marvell/db64460/mpsc.h @@ -0,0 +1,156 @@ +/* + * (C) Copyright 2001 + * John Clemens <clemens@mclx.com>, 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 <ingo.assmus@keymile.com> + * + ************************************************************************/ + + +/* + * mpsc.h - header file for MPSC in uart mode (console driver) + */ + +#ifndef __MPSC_H__ +#define __MPSC_H__ + +/* include actual Galileo defines */ +#include "../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/Marvell/db64460/mv_eth.c b/board/Marvell/db64460/mv_eth.c new file mode 100644 index 0000000..b78fda3 --- /dev/null +++ b/board/Marvell/db64460/mv_eth.c @@ -0,0 +1,3182 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * 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.c - header file for the polled mode GT ethernet driver + */ +#include <common.h> +#include <net.h> +#include <malloc.h> + +#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 + +#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))) + +/* 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); + +#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; + +/************************************************* + *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 + +#define my_cpu_to_le32(x) my_le32_to_cpu((x)) + +unsigned long my_le32_to_cpu (unsigned long x) +{ + return (((x & 0x000000ffU) << 24) | + ((x & 0x0000ff00U) << 8) | + ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24)); +} + + +/********************************************************************** + * mv64460_eth_print_phy_status + * + * Prints gigabit ethenret phy status + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + **********************************************************************/ + +static 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); +} + + +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]; + + 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; + + dev->priv = (void *) ethernet_private = + calloc (sizeof (*ethernet_private), 1); + 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... */ + ethernet_private->port_private = (void *) port_private = + calloc (sizeof (*ethernet_private), 1); + 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); + + } + 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, phy_reg_data; + + 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 = 0x8 + port_num; + + /* 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)); + + /* Check Link status on phy */ + eth_port_read_smi_reg (port_num, 1, &phy_reg_data); + if (!(phy_reg_data & 0x20)) { + /* Reset PHY */ + if ((ethernet_phy_reset (port_num)) != true) { + printf ("$$ Warnning: No link on port %d \n", + port_num); + return 0; + } else { + eth_port_read_smi_reg (port_num, 1, &phy_reg_data); + if (!(phy_reg_data & 0x20)) { + printf ("### Error: Phy is not active\n"); + return 0; + } + } + } else { + mv64460_eth_print_phy_status (dev); + } + 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; + + 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); + } +#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); +} + +/******************************************************************************* + * 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; + + /* 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); +/* printf(" Phy-Port %d has addess %d \n",eth_port_num, phy_addr );*/ + + /* 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; +} + +/******************************************************************************* + * 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; +} + +/******************************************************************************* + * 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/Marvell/db64460/mv_eth.h b/board/Marvell/db64460/mv_eth.h new file mode 100644 index 0000000..b4e498b --- /dev/null +++ b/board/Marvell/db64460/mv_eth.h @@ -0,0 +1,840 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * 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 <asm/types.h> +#include <asm/io.h> +#include <asm/byteorder.h> +#include <common.h> +#include <net.h> +#include "mv_regs.h" +#include "../common/ppc_error_no.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 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/Marvell/db64460/mv_regs.h b/board/Marvell/db64460/mv_regs.h new file mode 100644 index 0000000..fb50bb6 --- /dev/null +++ b/board/Marvell/db64460/mv_regs.h @@ -0,0 +1,1124 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * 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_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/Marvell/db64460/pci.c b/board/Marvell/db64460/pci.c new file mode 100644 index 0000000..5637284 --- /dev/null +++ b/board/Marvell/db64460/pci.c @@ -0,0 +1,940 @@ +/* + * (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 <common.h> +#include <pci.h> + +#include "../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 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_write_config_dword (dev, PCI_BASE_ADDRESS_0 + offset, + 0x0); + pci_read_config_dword (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_write_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4, + bar_value); + } +} + + +/* 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[] = { + {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 DEBUG + gt_pci_bus_mode_display (PCI_HOST0); +#endif + + 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); + pciArbiterEnable (PCI_HOST0); + 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); + + pci0_hose.last_busno = pci_hose_scan (&pci0_hose); + +#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); + + pci1_hose.last_busno = pci_hose_scan (&pci1_hose); + + command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MEMORY; + pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); + +} diff --git a/board/Marvell/db64460/sdram_init.c b/board/Marvell/db64460/sdram_init.c new file mode 100644 index 0000000..8cfe84c --- /dev/null +++ b/board/Marvell/db64460/sdram_init.c @@ -0,0 +1,1985 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, 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 <common.h> +#include <74xx_7xx.h> +#include "../include/memory.h" +#include "../include/pci.h" +#include "../include/mv_gen_reg.h" +#include <net.h> + +#include "eth.h" +#include "mpsc.h" +#include "../common/i2c.h" +#include "64460.h" +#include "mv_regs.h" + +#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); + +/* ------------------------------------------------------------------------- */ + +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; +} + +#define GB (1 << 30) + +/* much of this code is based on (or is) the code in the pip405 port */ +/* thanks go to the authors of said port - Josh */ + +/* structure to store the relevant information about an sdram bank */ +typedef struct sdram_info { + uchar drb_size; + uchar registered, ecc; + uchar tpar; + uchar tras_clocks; + uchar burst_len; + uchar banks, slot; +} sdram_info_t; + +/* Typedefs for 'gtAuxilGetDIMMinfo' function */ + +typedef enum _memoryType { SDRAM, DDR } MEMORY_TYPE; + +typedef enum _voltageInterface { TTL_5V_TOLERANT, LVTTL, HSTL_1_5V, + SSTL_3_3V, SSTL_2_5V, VOLTAGE_UNKNOWN, +} VOLTAGE_INTERFACE; + +typedef enum _max_CL_supported_DDR { DDR_CL_1 = 1, DDR_CL_1_5 = 2, DDR_CL_2 = + 4, DDR_CL_2_5 = 8, DDR_CL_3 = 16, DDR_CL_3_5 = + 32, DDR_CL_FAULT } MAX_CL_SUPPORTED_DDR; +typedef enum _max_CL_supported_SD { SD_CL_1 = + 1, SD_CL_2, SD_CL_3, SD_CL_4, SD_CL_5, SD_CL_6, SD_CL_7, + SD_FAULT } MAX_CL_SUPPORTED_SD; + + +/* SDRAM/DDR information struct */ +typedef struct _gtMemoryDimmInfo { + MEMORY_TYPE memoryType; + unsigned int numOfRowAddresses; + unsigned int numOfColAddresses; + unsigned int numOfModuleBanks; + unsigned int dataWidth; + VOLTAGE_INTERFACE voltageInterface; + unsigned int errorCheckType; /* ECC , PARITY.. */ + unsigned int sdramWidth; /* 4,8,16 or 32 */ ; + unsigned int errorCheckDataWidth; /* 0 - no, 1 - Yes */ + unsigned int minClkDelay; + unsigned int burstLengthSupported; + unsigned int numOfBanksOnEachDevice; + unsigned int suportedCasLatencies; + unsigned int RefreshInterval; + unsigned int maxCASlatencySupported_LoP; /* LoP left of point (measured in ns) */ + unsigned int maxCASlatencySupported_RoP; /* RoP right of point (measured in ns) */ + MAX_CL_SUPPORTED_DDR maxClSupported_DDR; + MAX_CL_SUPPORTED_SD maxClSupported_SD; + unsigned int moduleBankDensity; + /* module attributes (true for yes) */ + bool bufferedAddrAndControlInputs; + bool registeredAddrAndControlInputs; + bool onCardPLL; + bool bufferedDQMBinputs; + bool registeredDQMBinputs; + bool differentialClockInput; + bool redundantRowAddressing; + + /* module general attributes */ + bool suportedAutoPreCharge; + bool suportedPreChargeAll; + bool suportedEarlyRasPreCharge; + bool suportedWrite1ReadBurst; + bool suported5PercentLowVCC; + bool suported5PercentUpperVCC; + /* module timing parameters */ + unsigned int minRasToCasDelay; + unsigned int minRowActiveRowActiveDelay; + unsigned int minRasPulseWidth; + unsigned int minRowPrechargeTime; /* measured in ns */ + + int addrAndCommandHoldTime; /* LoP left of point (measured in ns) */ + int addrAndCommandSetupTime; /* (measured in ns/100) */ + int dataInputSetupTime; /* LoP left of point (measured in ns) */ + int dataInputHoldTime; /* LoP left of point (measured in ns) */ +/* tAC times for highest 2nd and 3rd highest CAS Latency values */ + unsigned int clockToDataOut_LoP; /* LoP left of point (measured in ns) */ + unsigned int clockToDataOut_RoP; /* RoP right of point (measured in ns) */ + unsigned int clockToDataOutMinus1_LoP; /* LoP left of point (measured in ns) */ + unsigned int clockToDataOutMinus1_RoP; /* RoP right of point (measured in ns) */ + unsigned int clockToDataOutMinus2_LoP; /* LoP left of point (measured in ns) */ + unsigned int clockToDataOutMinus2_RoP; /* RoP right of point (measured in ns) */ + + unsigned int minimumCycleTimeAtMaxCasLatancy_LoP; /* LoP left of point (measured in ns) */ + unsigned int minimumCycleTimeAtMaxCasLatancy_RoP; /* RoP right of point (measured in ns) */ + + unsigned int minimumCycleTimeAtMaxCasLatancyMinus1_LoP; /* LoP left of point (measured in ns) */ + unsigned int minimumCycleTimeAtMaxCasLatancyMinus1_RoP; /* RoP right of point (measured in ns) */ + + unsigned int minimumCycleTimeAtMaxCasLatancyMinus2_LoP; /* LoP left of point (measured in ns) */ + unsigned int minimumCycleTimeAtMaxCasLatancyMinus2_RoP; /* RoP right of point (measured in ns) */ + + /* Parameters calculated from + the extracted DIMM information */ + unsigned int size; + unsigned int deviceDensity; /* 16,64,128,256 or 512 Mbit */ + unsigned int numberOfDevices; + uchar drb_size; /* DRAM size in n*64Mbit */ + uchar slot; /* Slot Number this module is inserted in */ + uchar spd_raw_data[128]; /* Content of SPD-EEPROM copied 1:1 */ +#ifdef DEBUG + uchar manufactura[8]; /* Content of SPD-EEPROM Byte 64-71 */ + uchar modul_id[18]; /* Content of SPD-EEPROM Byte 73-90 */ + uchar vendor_data[27]; /* Content of SPD-EEPROM Byte 99-125 */ + unsigned long modul_serial_no; /* Content of SPD-EEPROM Byte 95-98 */ + unsigned int manufac_date; /* Content of SPD-EEPROM Byte 93-94 */ + unsigned int modul_revision; /* Content of SPD-EEPROM Byte 91-92 */ + uchar manufac_place; /* Content of SPD-EEPROM Byte 72 */ + +#endif +} AUX_MEM_DIMM_INFO; + + +/* + * translate ns.ns/10 coding of SPD timing values + * into 10 ps unit values + */ +static inline unsigned short NS10to10PS (unsigned char spd_byte) +{ + unsigned short ns, ns10; + + /* isolate upper nibble */ + ns = (spd_byte >> 4) & 0x0F; + /* isolate lower nibble */ + ns10 = (spd_byte & 0x0F); + + return (ns * 100 + ns10 * 10); +} + +/* + * translate ns coding of SPD timing values + * into 10 ps unit values + */ +static inline unsigned short NSto10PS (unsigned char spd_byte) +{ + return (spd_byte * 100); +} + +/* This code reads the SPD chip on the sdram and populates + * the array which is passed in with the relevant information */ +/* static int check_dimm(uchar slot, AUX_MEM_DIMM_INFO *info) */ +static int check_dimm (uchar slot, AUX_MEM_DIMM_INFO * dimmInfo) +{ + DECLARE_GLOBAL_DATA_PTR; + + unsigned long spd_checksum; + +#ifdef ZUMA_NTL + /* zero all the values */ + memset (info, 0, sizeof (*info)); + +/* + if (!slot) { + info->slot = 0; + info->banks = 1; + info->registered = 0; + info->drb_size = 16;*/ /* 16 - 256MBit, 32 - 512MBit */ +/* info->tpar = 3; + info->tras_clocks = 5; + info->burst_len = 4; +*/ +#ifdef CONFIG_MV64460_ECC + /* check for ECC/parity [0 = none, 1 = parity, 2 = ecc] */ + dimmInfo->errorCheckType = 2; +/* info->ecc = 2;*/ +#endif +} + +return 0; + +#else + uchar addr = slot == 0 ? DIMM0_I2C_ADDR : DIMM1_I2C_ADDR; + int ret; + unsigned int i, j, density = 1, devicesForErrCheck = 0; + +#ifdef DEBUG + unsigned int k; +#endif + unsigned int rightOfPoint = 0, leftOfPoint = 0, mult, div, time_tmp; + int sign = 1, shift, maskLeftOfPoint, maskRightOfPoint; + uchar supp_cal, cal_val; + ulong memclk, tmemclk; + ulong tmp; + uchar trp_clocks = 0, trcd_clocks, tras_clocks, trrd_clocks; + uchar data[128]; + + memclk = gd->bus_clk; + tmemclk = 1000000000 / (memclk / 100); /* in 10 ps units */ + + DP (puts ("before i2c read\n")); + + ret = i2c_read (addr, 0, 1, data, 128); + + DP (puts ("after i2c read\n")); + + /* zero all the values */ + memset (dimmInfo, 0, sizeof (*dimmInfo)); + + /* copy the SPD content 1:1 into the dimmInfo structure */ + for (i = 0; i <= 127; i++) { + dimmInfo->spd_raw_data[i] = data[i]; + } + + if (ret) { + DP (printf ("No DIMM in slot %d [err = %x]\n", slot, ret)); + return 0; + } else + dimmInfo->slot = slot; /* start to fill up dimminfo for this "slot" */ + +#ifdef CFG_DISPLAY_DIMM_SPD_CONTENT + + for (i = 0; i <= 127; i++) { + printf ("SPD-EEPROM Byte %3d = %3x (%3d)\n", i, data[i], + data[i]); + } + +#endif +#ifdef DEBUG +/* find Manufactura of Dimm Module */ + for (i = 0; i < sizeof (dimmInfo->manufactura); i++) { + dimmInfo->manufactura[i] = data[64 + i]; + } + printf ("\nThis RAM-Module is produced by: %s\n", + dimmInfo->manufactura); + +/* find Manul-ID of Dimm Module */ + for (i = 0; i < sizeof (dimmInfo->modul_id); i++) { + dimmInfo->modul_id[i] = data[73 + i]; + } + printf ("The Module-ID of this RAM-Module is: %s\n", + dimmInfo->modul_id); + +/* find Vendor-Data of Dimm Module */ + for (i = 0; i < sizeof (dimmInfo->vendor_data); i++) { + dimmInfo->vendor_data[i] = data[99 + i]; + } + printf ("Vendor Data of this RAM-Module is: %s\n", + dimmInfo->vendor_data); + +/* find modul_serial_no of Dimm Module */ + dimmInfo->modul_serial_no = (*((unsigned long *) (&data[95]))); + printf ("Serial No. of this RAM-Module is: %ld (%lx)\n", + dimmInfo->modul_serial_no, dimmInfo->modul_serial_no); + +/* find Manufac-Data of Dimm Module */ + dimmInfo->manufac_date = (*((unsigned int *) (&data[93]))); + printf ("Manufactoring Date of this RAM-Module is: %d.%d\n", data[93], data[94]); /*dimmInfo->manufac_date */ + +/* find modul_revision of Dimm Module */ + dimmInfo->modul_revision = (*((unsigned int *) (&data[91]))); + printf ("Module Revision of this RAM-Module is: %d.%d\n", data[91], data[92]); /* dimmInfo->modul_revision */ + +/* find manufac_place of Dimm Module */ + dimmInfo->manufac_place = (*((unsigned char *) (&data[72]))); + printf ("manufac_place of this RAM-Module is: %d\n", + dimmInfo->manufac_place); + +#endif + +/*------------------------------------------------------------------------------------------------------------------------------*/ +/* calculate SPD checksum */ +/*------------------------------------------------------------------------------------------------------------------------------*/ + spd_checksum = 0; + + for (i = 0; i <= 62; i++) { + spd_checksum += data[i]; + } + + if ((spd_checksum & 0xff) != data[63]) { + printf ("### Error in SPD Checksum !!! Is_value: %2x should value %2x\n", (unsigned int) (spd_checksum & 0xff), data[63]); + hang (); + } + + else + printf ("SPD Checksum ok!\n"); + + +/*------------------------------------------------------------------------------------------------------------------------------*/ + for (i = 2; i <= 35; i++) { + switch (i) { + case 2: /* Memory type (DDR / SDRAM) */ + dimmInfo->memoryType = (data[i] == 0x7) ? DDR : SDRAM; +#ifdef DEBUG + if (dimmInfo->memoryType == 0) + DP (printf + ("Dram_type in slot %d is: SDRAM\n", + dimmInfo->slot)); + if (dimmInfo->memoryType == 1) + DP (printf + ("Dram_type in slot %d is: DDRAM\n", + dimmInfo->slot)); +#endif + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 3: /* Number Of Row Addresses */ + dimmInfo->numOfRowAddresses = data[i]; + DP (printf + ("Module Number of row addresses: %d\n", + dimmInfo->numOfRowAddresses)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 4: /* Number Of Column Addresses */ + dimmInfo->numOfColAddresses = data[i]; + DP (printf + ("Module Number of col addresses: %d\n", + dimmInfo->numOfColAddresses)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 5: /* Number Of Module Banks */ + dimmInfo->numOfModuleBanks = data[i]; + DP (printf + ("Number of Banks on Mod. : %d\n", + dimmInfo->numOfModuleBanks)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 6: /* Data Width */ + dimmInfo->dataWidth = data[i]; + DP (printf + ("Module Data Width: %d\n", + dimmInfo->dataWidth)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 8: /* Voltage Interface */ + switch (data[i]) { + case 0x0: + dimmInfo->voltageInterface = TTL_5V_TOLERANT; + DP (printf + ("Module is TTL_5V_TOLERANT\n")); + break; + case 0x1: + dimmInfo->voltageInterface = LVTTL; + DP (printf + ("Module is LVTTL\n")); + break; + case 0x2: + dimmInfo->voltageInterface = HSTL_1_5V; + DP (printf + ("Module is TTL_5V_TOLERANT\n")); + break; + case 0x3: + dimmInfo->voltageInterface = SSTL_3_3V; + DP (printf + ("Module is HSTL_1_5V\n")); + break; + case 0x4: + dimmInfo->voltageInterface = SSTL_2_5V; + DP (printf + ("Module is SSTL_2_5V\n")); + break; + default: + dimmInfo->voltageInterface = VOLTAGE_UNKNOWN; + DP (printf + ("Module is VOLTAGE_UNKNOWN\n")); + break; + } + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 9: /* Minimum Cycle Time At Max CasLatancy */ + shift = (dimmInfo->memoryType == DDR) ? 4 : 2; + mult = (dimmInfo->memoryType == DDR) ? 10 : 25; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf0 : 0xfc; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf : 0x03; + leftOfPoint = (data[i] & maskLeftOfPoint) >> shift; + rightOfPoint = (data[i] & maskRightOfPoint) * mult; + dimmInfo->minimumCycleTimeAtMaxCasLatancy_LoP = + leftOfPoint; + dimmInfo->minimumCycleTimeAtMaxCasLatancy_RoP = + rightOfPoint; + DP (printf + ("Minimum Cycle Time At Max CasLatancy: %d.%d [ns]\n", + leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 10: /* Clock To Data Out */ + div = (dimmInfo->memoryType == DDR) ? 100 : 10; + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / div; + rightOfPoint = time_tmp % div; + dimmInfo->clockToDataOut_LoP = leftOfPoint; + dimmInfo->clockToDataOut_RoP = rightOfPoint; + DP (printf ("Clock To Data Out: %d.%2d [ns]\n", leftOfPoint, rightOfPoint)); /*dimmInfo->clockToDataOut */ + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + +/*#ifdef CONFIG_ECC */ + case 11: /* Error Check Type */ + dimmInfo->errorCheckType = data[i]; + DP (printf + ("Error Check Type (0=NONE): %d\n", + dimmInfo->errorCheckType)); + break; +/* #endif */ +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 12: /* Refresh Interval */ + dimmInfo->RefreshInterval = data[i]; + DP (printf + ("RefreshInterval (80= Self refresh Normal, 15.625us) : %x\n", + dimmInfo->RefreshInterval)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 13: /* Sdram Width */ + dimmInfo->sdramWidth = data[i]; + DP (printf + ("Sdram Width: %d\n", + dimmInfo->sdramWidth)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 14: /* Error Check Data Width */ + dimmInfo->errorCheckDataWidth = data[i]; + DP (printf + ("Error Check Data Width: %d\n", + dimmInfo->errorCheckDataWidth)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 15: /* Minimum Clock Delay */ + dimmInfo->minClkDelay = data[i]; + DP (printf + ("Minimum Clock Delay: %d\n", + dimmInfo->minClkDelay)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 16: /* Burst Length Supported */ + /******-******-******-******* + * bit3 | bit2 | bit1 | bit0 * + *******-******-******-******* + burst length = * 8 | 4 | 2 | 1 * + ***************************** + + If for example bit0 and bit2 are set, the burst + length supported are 1 and 4. */ + + dimmInfo->burstLengthSupported = data[i]; +#ifdef DEBUG + DP (printf + ("Burst Length Supported: ")); + if (dimmInfo->burstLengthSupported & 0x01) + DP (printf ("1, ")); + if (dimmInfo->burstLengthSupported & 0x02) + DP (printf ("2, ")); + if (dimmInfo->burstLengthSupported & 0x04) + DP (printf ("4, ")); + if (dimmInfo->burstLengthSupported & 0x08) + DP (printf ("8, ")); + DP (printf (" Bit \n")); +#endif + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 17: /* Number Of Banks On Each Device */ + dimmInfo->numOfBanksOnEachDevice = data[i]; + DP (printf + ("Number Of Banks On Each Chip: %d\n", + dimmInfo->numOfBanksOnEachDevice)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 18: /* Suported Cas Latencies */ + + /* DDR: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | TBD | 3.5 | 3 | 2.5 | 2 | 1.5 | 1 * + ********************************************************* + SDRAM: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | 7 | 6 | 5 | 4 | 3 | 2 | 1 * + ********************************************************/ + dimmInfo->suportedCasLatencies = data[i]; +#ifdef DEBUG + DP (printf + ("Suported Cas Latencies: (CL) ")); + if (dimmInfo->memoryType == 0) { /* SDRAM */ + for (k = 0; k <= 7; k++) { + if (dimmInfo-> + suportedCasLatencies & (1 << k)) + DP (printf + ("%d, ", + k + 1)); + } + + } else { /* DDR-RAM */ + + if (dimmInfo->suportedCasLatencies & 1) + DP (printf ("1, ")); + if (dimmInfo->suportedCasLatencies & 2) + DP (printf ("1.5, ")); + if (dimmInfo->suportedCasLatencies & 4) + DP (printf ("2, ")); + if (dimmInfo->suportedCasLatencies & 8) + DP (printf ("2.5, ")); + if (dimmInfo->suportedCasLatencies & 16) + DP (printf ("3, ")); + if (dimmInfo->suportedCasLatencies & 32) + DP (printf ("3.5, ")); + + } + DP (printf ("\n")); +#endif + /* Calculating MAX CAS latency */ + for (j = 7; j > 0; j--) { + if (((dimmInfo-> + suportedCasLatencies >> j) & 0x1) == + 1) { + switch (dimmInfo->memoryType) { + case DDR: + /* CAS latency 1, 1.5, 2, 2.5, 3, 3.5 */ + switch (j) { + case 7: + DP (printf + ("Max. Cas Latencies (DDR): ERROR !!!\n")); + dimmInfo-> + maxClSupported_DDR + = + DDR_CL_FAULT; + hang (); + break; + case 6: + DP (printf + ("Max. Cas Latencies (DDR): ERROR !!!\n")); + dimmInfo-> + maxClSupported_DDR + = + DDR_CL_FAULT; + hang (); + break; + case 5: + DP (printf + ("Max. Cas Latencies (DDR): 3.5 clk's\n")); + dimmInfo-> + maxClSupported_DDR + = DDR_CL_3_5; + break; + case 4: + DP (printf + ("Max. Cas Latencies (DDR): 3 clk's \n")); + dimmInfo-> + maxClSupported_DDR + = DDR_CL_3; + break; + case 3: + DP (printf + ("Max. Cas Latencies (DDR): 2.5 clk's \n")); + dimmInfo-> + maxClSupported_DDR + = DDR_CL_2_5; + break; + case 2: + DP (printf + ("Max. Cas Latencies (DDR): 2 clk's \n")); + dimmInfo-> + maxClSupported_DDR + = DDR_CL_2; + break; + case 1: + DP (printf + ("Max. Cas Latencies (DDR): 1.5 clk's \n")); + dimmInfo-> + maxClSupported_DDR + = DDR_CL_1_5; + break; + } + + /* ronen - in case we have a DIMM with minimumCycleTimeAtMaxCasLatancy + lower then our SDRAM cycle count, we won't be able to support this CAL + and we will have to use lower CAL. (minus - means from 3.0 to 2.5) */ + if ((dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_LoP + < + CFG_DDR_SDRAM_CYCLE_COUNT_LOP) + || + ((dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_LoP + == + CFG_DDR_SDRAM_CYCLE_COUNT_LOP) + && (dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_RoP + < + CFG_DDR_SDRAM_CYCLE_COUNT_ROP))) + { + dimmInfo-> + maxClSupported_DDR + = + dimmInfo-> + maxClSupported_DDR + >> 1; + DP (printf + ("*** Change actual Cas Latencies cause of minimumCycleTime n")); + } + /* ronen - checkif the Dimm frequency compared to the Sysclock. */ + if ((dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_LoP + > + CFG_DDR_SDRAM_CYCLE_COUNT_LOP) + || + ((dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_LoP + == + CFG_DDR_SDRAM_CYCLE_COUNT_LOP) + && (dimmInfo-> + minimumCycleTimeAtMaxCasLatancy_RoP + > + CFG_DDR_SDRAM_CYCLE_COUNT_ROP))) + { + printf ("*********************************************************\n"); + printf ("*** sysClock is higher than SDRAM's allowed frequency ***\n"); + printf ("*********************************************************\n"); + hang (); + } + + dimmInfo-> + maxCASlatencySupported_LoP + = + 1 + + (int) (5 * j / 10); + if (((5 * j) % 10) != 0) + dimmInfo-> + maxCASlatencySupported_RoP + = 5; + else + dimmInfo-> + maxCASlatencySupported_RoP + = 0; + DP (printf + ("Max. Cas Latencies (DDR LoP.RoP Notation): %d.%d \n", + dimmInfo-> + maxCASlatencySupported_LoP, + dimmInfo-> + maxCASlatencySupported_RoP)); + break; + case SDRAM: + /* CAS latency 1, 2, 3, 4, 5, 6, 7 */ + dimmInfo->maxClSupported_SD = j; /* Cas Latency DDR-RAM Coded */ + DP (printf + ("Max. Cas Latencies (SD): %d\n", + dimmInfo-> + maxClSupported_SD)); + dimmInfo-> + maxCASlatencySupported_LoP + = j; + dimmInfo-> + maxCASlatencySupported_RoP + = 0; + DP (printf + ("Max. Cas Latencies (DDR LoP.RoP Notation): %d.%d \n", + dimmInfo-> + maxCASlatencySupported_LoP, + dimmInfo-> + maxCASlatencySupported_RoP)); + break; + } + break; + } + } + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 21: /* Buffered Address And Control Inputs */ + DP (printf ("\nModul Attributes (SPD Byte 21): \n")); + dimmInfo->bufferedAddrAndControlInputs = + data[i] & BIT0; + dimmInfo->registeredAddrAndControlInputs = + (data[i] & BIT1) >> 1; + dimmInfo->onCardPLL = (data[i] & BIT2) >> 2; + dimmInfo->bufferedDQMBinputs = (data[i] & BIT3) >> 3; + dimmInfo->registeredDQMBinputs = + (data[i] & BIT4) >> 4; + dimmInfo->differentialClockInput = + (data[i] & BIT5) >> 5; + dimmInfo->redundantRowAddressing = + (data[i] & BIT6) >> 6; +#ifdef DEBUG + if (dimmInfo->bufferedAddrAndControlInputs == 1) + DP (printf + (" - Buffered Address/Control Input: Yes \n")); + else + DP (printf + (" - Buffered Address/Control Input: No \n")); + + if (dimmInfo->registeredAddrAndControlInputs == 1) + DP (printf + (" - Registered Address/Control Input: Yes \n")); + else + DP (printf + (" - Registered Address/Control Input: No \n")); + + if (dimmInfo->onCardPLL == 1) + DP (printf + (" - On-Card PLL (clock): Yes \n")); + else + DP (printf + (" - On-Card PLL (clock): No \n")); + + if (dimmInfo->bufferedDQMBinputs == 1) + DP (printf + (" - Bufferd DQMB Inputs: Yes \n")); + else + DP (printf + (" - Bufferd DQMB Inputs: No \n")); + + if (dimmInfo->registeredDQMBinputs == 1) + DP (printf + (" - Registered DQMB Inputs: Yes \n")); + else + DP (printf + (" - Registered DQMB Inputs: No \n")); + + if (dimmInfo->differentialClockInput == 1) + DP (printf + (" - Differential Clock Input: Yes \n")); + else + DP (printf + (" - Differential Clock Input: No \n")); + + if (dimmInfo->redundantRowAddressing == 1) + DP (printf + (" - redundant Row Addressing: Yes \n")); + else + DP (printf + (" - redundant Row Addressing: No \n")); + +#endif + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 22: /* Suported AutoPreCharge */ + DP (printf ("\nModul Attributes (SPD Byte 22): \n")); + dimmInfo->suportedEarlyRasPreCharge = data[i] & BIT0; + dimmInfo->suportedAutoPreCharge = + (data[i] & BIT1) >> 1; + dimmInfo->suportedPreChargeAll = + (data[i] & BIT2) >> 2; + dimmInfo->suportedWrite1ReadBurst = + (data[i] & BIT3) >> 3; + dimmInfo->suported5PercentLowVCC = + (data[i] & BIT4) >> 4; + dimmInfo->suported5PercentUpperVCC = + (data[i] & BIT5) >> 5; +#ifdef DEBUG + if (dimmInfo->suportedEarlyRasPreCharge == 1) + DP (printf + (" - Early Ras Precharge: Yes \n")); + else + DP (printf + (" - Early Ras Precharge: No \n")); + + if (dimmInfo->suportedAutoPreCharge == 1) + DP (printf + (" - AutoPreCharge: Yes \n")); + else + DP (printf + (" - AutoPreCharge: No \n")); + + if (dimmInfo->suportedPreChargeAll == 1) + DP (printf + (" - Precharge All: Yes \n")); + else + DP (printf + (" - Precharge All: No \n")); + + if (dimmInfo->suportedWrite1ReadBurst == 1) + DP (printf + (" - Write 1/ReadBurst: Yes \n")); + else + DP (printf + (" - Write 1/ReadBurst: No \n")); + + if (dimmInfo->suported5PercentLowVCC == 1) + DP (printf + (" - lower VCC tolerance: 5 Percent \n")); + else + DP (printf + (" - lower VCC tolerance: 10 Percent \n")); + + if (dimmInfo->suported5PercentUpperVCC == 1) + DP (printf + (" - upper VCC tolerance: 5 Percent \n")); + else + DP (printf + (" - upper VCC tolerance: 10 Percent \n")); + +#endif + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 23: /* Minimum Cycle Time At Maximum Cas Latancy Minus 1 (2nd highest CL) */ + shift = (dimmInfo->memoryType == DDR) ? 4 : 2; + mult = (dimmInfo->memoryType == DDR) ? 10 : 25; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf0 : 0xfc; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf : 0x03; + leftOfPoint = (data[i] & maskLeftOfPoint) >> shift; + rightOfPoint = (data[i] & maskRightOfPoint) * mult; + dimmInfo->minimumCycleTimeAtMaxCasLatancyMinus1_LoP = + leftOfPoint; + dimmInfo->minimumCycleTimeAtMaxCasLatancyMinus1_RoP = + rightOfPoint; + DP (printf ("Minimum Cycle Time At 2nd highest CasLatancy (0 = Not supported): %d.%d [ns]\n", leftOfPoint, rightOfPoint)); /*dimmInfo->minimumCycleTimeAtMaxCasLatancy */ + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 24: /* Clock To Data Out 2nd highest Cas Latency Value */ + div = (dimmInfo->memoryType == DDR) ? 100 : 10; + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / div; + rightOfPoint = time_tmp % div; + dimmInfo->clockToDataOutMinus1_LoP = leftOfPoint; + dimmInfo->clockToDataOutMinus1_RoP = rightOfPoint; + DP (printf + ("Clock To Data Out (2nd CL value): %d.%2d [ns]\n", + leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 25: /* Minimum Cycle Time At Maximum Cas Latancy Minus 2 (3rd highest CL) */ + shift = (dimmInfo->memoryType == DDR) ? 4 : 2; + mult = (dimmInfo->memoryType == DDR) ? 10 : 25; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf0 : 0xfc; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0xf : 0x03; + leftOfPoint = (data[i] & maskLeftOfPoint) >> shift; + rightOfPoint = (data[i] & maskRightOfPoint) * mult; + dimmInfo->minimumCycleTimeAtMaxCasLatancyMinus2_LoP = + leftOfPoint; + dimmInfo->minimumCycleTimeAtMaxCasLatancyMinus2_RoP = + rightOfPoint; + DP (printf ("Minimum Cycle Time At 3rd highest CasLatancy (0 = Not supported): %d.%d [ns]\n", leftOfPoint, rightOfPoint)); /*dimmInfo->minimumCycleTimeAtMaxCasLatancy */ + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 26: /* Clock To Data Out 3rd highest Cas Latency Value */ + div = (dimmInfo->memoryType == DDR) ? 100 : 10; + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / div; + rightOfPoint = time_tmp % div; + dimmInfo->clockToDataOutMinus2_LoP = leftOfPoint; + dimmInfo->clockToDataOutMinus2_RoP = rightOfPoint; + DP (printf + ("Clock To Data Out (3rd CL value): %d.%2d [ns]\n", + leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 27: /* Minimum Row Precharge Time */ + shift = (dimmInfo->memoryType == DDR) ? 2 : 0; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xfc : 0xff; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0x03 : 0x00; + leftOfPoint = ((data[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (data[i] & maskRightOfPoint) * 25; + + dimmInfo->minRowPrechargeTime = ((leftOfPoint * 100) + rightOfPoint); /* measured in n times 10ps Intervals */ + trp_clocks = + (dimmInfo->minRowPrechargeTime + + (tmemclk - 1)) / tmemclk; + DP (printf + ("*** 1 clock cycle = %ld 10ps intervalls = %ld.%ld ns****\n", + tmemclk, tmemclk / 100, tmemclk % 100)); + DP (printf + ("Minimum Row Precharge Time [ns]: %d.%2d = in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 28: /* Minimum Row Active to Row Active Time */ + shift = (dimmInfo->memoryType == DDR) ? 2 : 0; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xfc : 0xff; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0x03 : 0x00; + leftOfPoint = ((data[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (data[i] & maskRightOfPoint) * 25; + + dimmInfo->minRowActiveRowActiveDelay = ((leftOfPoint * 100) + rightOfPoint); /* measured in 100ns Intervals */ + trrd_clocks = + (dimmInfo->minRowActiveRowActiveDelay + + (tmemclk - 1)) / tmemclk; + DP (printf + ("Minimum Row Active -To- Row Active Delay [ns]: %d.%2d = in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 29: /* Minimum Ras-To-Cas Delay */ + shift = (dimmInfo->memoryType == DDR) ? 2 : 0; + maskLeftOfPoint = + (dimmInfo->memoryType == DDR) ? 0xfc : 0xff; + maskRightOfPoint = + (dimmInfo->memoryType == DDR) ? 0x03 : 0x00; + leftOfPoint = ((data[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (data[i] & maskRightOfPoint) * 25; + + dimmInfo->minRowActiveRowActiveDelay = ((leftOfPoint * 100) + rightOfPoint); /* measured in 100ns Intervals */ + trcd_clocks = + (dimmInfo->minRowActiveRowActiveDelay + + (tmemclk - 1)) / tmemclk; + DP (printf + ("Minimum Ras-To-Cas Delay [ns]: %d.%2d = in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 30: /* Minimum Ras Pulse Width */ + dimmInfo->minRasPulseWidth = data[i]; + tras_clocks = + (NSto10PS (data[i]) + + (tmemclk - 1)) / tmemclk; + DP (printf + ("Minimum Ras Pulse Width [ns]: %d = in Clk cycles %d\n", + dimmInfo->minRasPulseWidth, tras_clocks)); + + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 31: /* Module Bank Density */ + dimmInfo->moduleBankDensity = data[i]; + DP (printf + ("Module Bank Density: %d\n", + dimmInfo->moduleBankDensity)); +#ifdef DEBUG + DP (printf + ("*** Offered Densities (more than 1 = Multisize-Module): ")); + { + if (dimmInfo->moduleBankDensity & 1) + DP (printf ("4MB, ")); + if (dimmInfo->moduleBankDensity & 2) + DP (printf ("8MB, ")); + if (dimmInfo->moduleBankDensity & 4) + DP (printf ("16MB, ")); + if (dimmInfo->moduleBankDensity & 8) + DP (printf ("32MB, ")); + if (dimmInfo->moduleBankDensity & 16) + DP (printf ("64MB, ")); + if (dimmInfo->moduleBankDensity & 32) + DP (printf ("128MB, ")); + if ((dimmInfo->moduleBankDensity & 64) + || (dimmInfo->moduleBankDensity & 128)) { + DP (printf ("ERROR, ")); + hang (); + } + } + DP (printf ("\n")); +#endif + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 32: /* Address And Command Setup Time (measured in ns/1000) */ + sign = 1; + switch (dimmInfo->memoryType) { + case DDR: + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + break; + case SDRAM: + leftOfPoint = (data[i] & 0xf0) >> 4; + if (leftOfPoint > 7) { + leftOfPoint = data[i] & 0x70 >> 4; + sign = -1; + } + rightOfPoint = (data[i] & 0x0f); + break; + } + dimmInfo->addrAndCommandSetupTime = + (leftOfPoint * 100 + rightOfPoint) * sign; + DP (printf + ("Address And Command Setup Time [ns]: %d.%d\n", + sign * leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 33: /* Address And Command Hold Time */ + sign = 1; + switch (dimmInfo->memoryType) { + case DDR: + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + break; + case SDRAM: + leftOfPoint = (data[i] & 0xf0) >> 4; + if (leftOfPoint > 7) { + leftOfPoint = data[i] & 0x70 >> 4; + sign = -1; + } + rightOfPoint = (data[i] & 0x0f); + break; + } + dimmInfo->addrAndCommandHoldTime = + (leftOfPoint * 100 + rightOfPoint) * sign; + DP (printf + ("Address And Command Hold Time [ns]: %d.%d\n", + sign * leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 34: /* Data Input Setup Time */ + sign = 1; + switch (dimmInfo->memoryType) { + case DDR: + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + break; + case SDRAM: + leftOfPoint = (data[i] & 0xf0) >> 4; + if (leftOfPoint > 7) { + leftOfPoint = data[i] & 0x70 >> 4; + sign = -1; + } + rightOfPoint = (data[i] & 0x0f); + break; + } + dimmInfo->dataInputSetupTime = + (leftOfPoint * 100 + rightOfPoint) * sign; + DP (printf + ("Data Input Setup Time [ns]: %d.%d\n", + sign * leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + + case 35: /* Data Input Hold Time */ + sign = 1; + switch (dimmInfo->memoryType) { + case DDR: + time_tmp = + (((data[i] & 0xf0) >> 4) * 10) + + ((data[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + break; + case SDRAM: + leftOfPoint = (data[i] & 0xf0) >> 4; + if (leftOfPoint > 7) { + leftOfPoint = data[i] & 0x70 >> 4; + sign = -1; + } + rightOfPoint = (data[i] & 0x0f); + break; + } + dimmInfo->dataInputHoldTime = + (leftOfPoint * 100 + rightOfPoint) * sign; + DP (printf + ("Data Input Hold Time [ns]: %d.%d\n\n", + sign * leftOfPoint, rightOfPoint)); + break; +/*------------------------------------------------------------------------------------------------------------------------------*/ + } + } + /* calculating the sdram density */ + for (i = 0; + i < dimmInfo->numOfRowAddresses + dimmInfo->numOfColAddresses; + i++) { + density = density * 2; + } + dimmInfo->deviceDensity = density * dimmInfo->numOfBanksOnEachDevice * + dimmInfo->sdramWidth; + dimmInfo->numberOfDevices = + (dimmInfo->dataWidth / dimmInfo->sdramWidth) * + dimmInfo->numOfModuleBanks; + devicesForErrCheck = + (dimmInfo->dataWidth - 64) / dimmInfo->sdramWidth; + if ((dimmInfo->errorCheckType == 0x1) + || (dimmInfo->errorCheckType == 0x2) + || (dimmInfo->errorCheckType == 0x3)) { + dimmInfo->size = + (dimmInfo->deviceDensity / 8) * + (dimmInfo->numberOfDevices - + /* ronen on the 1G dimm we get wrong value. (was devicesForErrCheck) */ + dimmInfo->numberOfDevices / 8); + } else { + dimmInfo->size = + (dimmInfo->deviceDensity / 8) * + dimmInfo->numberOfDevices; + } + + /* compute the module DRB size */ + tmp = (1 << + (dimmInfo->numOfRowAddresses + dimmInfo->numOfColAddresses)); + tmp *= dimmInfo->numOfModuleBanks; + tmp *= dimmInfo->sdramWidth; + tmp = tmp >> 24; /* div by 0x4000000 (64M) */ + dimmInfo->drb_size = (uchar) tmp; + DP (printf ("Module DRB size (n*64Mbit): %d\n", dimmInfo->drb_size)); + + /* try a CAS latency of 3 first... */ + + /* bit 1 is CL2, bit 2 is CL3 */ + supp_cal = (dimmInfo->suportedCasLatencies & 0x6) >> 1; + + cal_val = 0; + if (supp_cal & 3) { + if (NS10to10PS (data[9]) <= tmemclk) + cal_val = 3; + } + + /* then 2... */ + if (supp_cal & 2) { + if (NS10to10PS (data[23]) <= tmemclk) + cal_val = 2; + } + + DP (printf ("cal_val = %d\n", cal_val)); + + /* bummer, did't work... */ + if (cal_val == 0) { + DP (printf ("Couldn't find a good CAS latency\n")); + hang (); + return 0; + } + + return true; +#endif +} + +/* sets up the GT properly with information passed in */ +int setup_sdram (AUX_MEM_DIMM_INFO * info) +{ + ulong tmp, check; + ulong tmp_sdram_mode = 0; /* 0x141c */ + ulong tmp_dunit_control_low = 0; /* 0x1404 */ + int i; + + /* added 8/21/2003 P. Marchese */ + unsigned int sdram_config_reg; + + /* added 10/10/2003 P. Marchese */ + ulong sdram_chip_size; + + /* sanity checking */ + if (!info->numOfModuleBanks) { + printf ("setup_sdram called with 0 banks\n"); + return 1; + } + + /* delay line */ + set_dfcdlInit (); /* may be its not needed */ + DP (printf ("Delay line set done\n")); + + /* set SDRAM mode NOP */ /* To_do check it */ + GT_REG_WRITE (SDRAM_OPERATION, 0x5); + while (GTREGREAD (SDRAM_OPERATION) != 0) { + DP (printf + ("\n*** SDRAM_OPERATION 1418: Module still busy ... please wait... ***\n")); + } + + /* SDRAM configuration */ +/* added 8/21/2003 P. Marchese */ +/* code allows usage of registered DIMMS */ + + /* figure out the memory refresh internal */ + switch (info->RefreshInterval) { + case 0x0: + case 0x80: /* refresh period is 15.625 usec */ + sdram_config_reg = + (unsigned int) (((float) 15.625 * (float) CFG_BUS_HZ) + / (float) 1000000.0); + break; + case 0x1: + case 0x81: /* refresh period is 3.9 usec */ + sdram_config_reg = + (unsigned int) (((float) 3.9 * (float) CFG_BUS_HZ) / + (float) 1000000.0); + break; + case 0x2: + case 0x82: /* refresh period is 7.8 usec */ + sdram_config_reg = + (unsigned int) (((float) 7.8 * (float) CFG_BUS_HZ) / + (float) 1000000.0); + break; + case 0x3: + case 0x83: /* refresh period is 31.3 usec */ + sdram_config_reg = + (unsigned int) (((float) 31.3 * (float) CFG_BUS_HZ) / + (float) 1000000.0); + break; + case 0x4: + case 0x84: /* refresh period is 62.5 usec */ + sdram_config_reg = + (unsigned int) (((float) 62.5 * (float) CFG_BUS_HZ) / + (float) 1000000.0); + break; + case 0x5: + case 0x85: /* refresh period is 125 usec */ + sdram_config_reg = + (unsigned int) (((float) 125 * (float) CFG_BUS_HZ) / + (float) 1000000.0); + break; + default: /* refresh period undefined */ + printf ("DRAM refresh period is unknown!\n"); + printf ("Aborting DRAM setup with an error\n"); + hang (); + break; + } + DP (printf ("calculated refresh interval %0x\n", sdram_config_reg)); + + /* make sure the refresh value is only 14 bits */ + if (sdram_config_reg > 0x1fff) + sdram_config_reg = 0x1fff; + DP (printf ("adjusted refresh interval %0x\n", sdram_config_reg)); + + /* we want physical bank interleaving and */ + /* virtual bank interleaving enabled so do nothing */ + /* since these bits need to be zero to enable the interleaving */ + + /* registered DRAM ? */ + if (info->registeredAddrAndControlInputs == 1) { + /* it's registered DRAM, so set the reg. DRAM bit */ + sdram_config_reg = sdram_config_reg | BIT17; + DP (printf ("Enabling registered DRAM bit\n")); + } + /* turn on DRAM ECC? */ +#ifdef CONFIG_MV64460_ECC + if (info->errorCheckType == 0x2) { + /* DRAM has ECC, so turn it on */ + sdram_config_reg = sdram_config_reg | BIT18; + DP (printf ("Enabling ECC\n")); + } +#endif + /* set the data DQS pin configuration */ + switch (info->sdramWidth) { + case 0x4: /* memory is x4 */ + sdram_config_reg = sdram_config_reg | BIT20 | BIT21; + DP (printf ("Data DQS pins set for 16 pins\n")); + break; + case 0x8: /* memory is x8 or x16 */ + case 0x10: + sdram_config_reg = sdram_config_reg | BIT21; + DP (printf ("Data DQS pins set for 8 pins\n")); + break; + case 0x20: /* memory is x32 */ + /* both bits are cleared for x32 so nothing to do */ + DP (printf ("Data DQS pins set for 2 pins\n")); + break; + default: /* memory width unsupported */ + printf ("DRAM chip width is unknown!\n"); + printf ("Aborting DRAM setup with an error\n"); + hang (); + break; + } + + /*ronen db64460 */ + /* perform read buffer assignments */ + /* we are going to use the Power-up defaults */ + /* bit 27 = PCI bus #0 = buffer 0 */ + /* bit 28 = PCI bus #1 = buffer 0 */ + /* bit 29 = MPSC = buffer 0 */ + /* bit 30 = IDMA = buffer 0 */ + /* bit 31 = Gigabit = buffer 0 */ + sdram_config_reg = sdram_config_reg | 0x58000000; + sdram_config_reg = sdram_config_reg & 0xffffff00; + /* bit 14 FBSplit = FCRAM controller bsplit enable. */ + /* bit 15 vw = FCRAM Variable write length enable. */ + /* bit 16 DType = Dram Type (0 = FCRAM,1 = Standard) */ + sdram_config_reg = sdram_config_reg | BIT14 | BIT15; + + /* write the value into the SDRAM configuration register */ + GT_REG_WRITE (SDRAM_CONFIG, sdram_config_reg); + DP (printf ("sdram_conf 0x1400: %08x\n", GTREGREAD (SDRAM_CONFIG))); + + /* SDRAM open pages control keep open as much as I can */ + GT_REG_WRITE (SDRAM_OPEN_PAGES_CONTROL, 0x0); + DP (printf + ("sdram_open_pages_controll 0x1414: %08x\n", + GTREGREAD (SDRAM_OPEN_PAGES_CONTROL))); + + /* SDRAM D_UNIT_CONTROL_LOW 0x1404 */ + tmp = (GTREGREAD (D_UNIT_CONTROL_LOW) & 0x01); /* Clock Domain Sync from power on reset */ + if (tmp == 0) + DP (printf ("Core Signals are sync (by HW-Setting)!!!\n")); + else + DP (printf + ("Core Signals syncs. are bypassed (by HW-Setting)!!!\n")); + + /* SDRAM set CAS Latency according to SPD information */ + switch (info->memoryType) { + case SDRAM: + printf ("### SD-RAM not supported !!!\n"); + printf ("Aborting!!!\n"); + hang (); + /* ToDo fill SD-RAM if needed !!!!! */ + break; + /* Calculate the settings for SDRAM mode and Dunit control low registers */ + /* Values set according to technical bulletin TB-92 rev. c */ + case DDR: + DP (printf ("### SET-CL for DDR-RAM\n")); + /* ronen db64460 - change the tmp_dunit_control_low setting!!! */ + switch (info->maxClSupported_DDR) { + case DDR_CL_3: + tmp_sdram_mode = 0x32; /* CL=3 Burstlength = 4 */ + if (tmp == 1) { /* clocks sync */ + if (info->registeredAddrAndControlInputs == 1) /* registerd DDR SDRAM? */ + tmp_dunit_control_low = 0x05110051; + else + tmp_dunit_control_low = 0x24110051; + DP (printf + ("Max. CL is 3 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + printf ("Warnning: DRAM ClkSync was never tested(db64460)!!!!!\n"); + } else { /* clk sync. bypassed */ + + if (info->registeredAddrAndControlInputs == 1) /* registerd DDR SDRAM? */ + tmp_dunit_control_low = 0xC5000540; + else + tmp_dunit_control_low = 0xC4000540; + DP (printf + ("Max. CL is 3 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } + break; + case DDR_CL_2_5: + tmp_sdram_mode = 0x62; /* CL=2.5 Burstlength = 4 */ + if (tmp == 1) { /* clocks sync */ + if (info->registeredAddrAndControlInputs == 1) /* registerd DDR SDRAM? */ + tmp_dunit_control_low = 0x25110051; + else + tmp_dunit_control_low = 0x24110051; + DP (printf + ("Max. CL is 2.5 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + printf ("Warnning: DRAM ClkSync was never tested(db64460)!!!!!\n"); + } else { /* clk sync. bypassed */ + + if (info->registeredAddrAndControlInputs == 1) { /* registerd DDR SDRAM? */ + tmp_dunit_control_low = 0xC5000540; + /* printf("CL = 2.5, Clock Unsync'ed, Dunit Control Low register setting undefined\n");1 */ + /* printf("Aborting!!!\n");1 */ + /* hang();1 */ + } else + tmp_dunit_control_low = 0xC4000540; + DP (printf + ("Max. CL is 2.5 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } + break; + case DDR_CL_2: + tmp_sdram_mode = 0x22; /* CL=2 Burstlength = 4 */ + if (tmp == 1) { /* clocks sync */ + if (info->registeredAddrAndControlInputs == 1) /* registerd DDR SDRAM? */ + tmp_dunit_control_low = 0x04110051; + else + tmp_dunit_control_low = 0x03110051; + DP (printf + ("Max. CL is 2 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + printf ("Warnning: DRAM ClkSync was never tested(db64460)!!!!!\n"); + } else { /* clk sync. bypassed */ + + if (info->registeredAddrAndControlInputs == 1) { /* registerd DDR SDRAM? */ + /*printf("CL = 2, Clock Unsync'ed, Dunit Control Low register setting undefined\n");1 */ + /*printf("Aborting!!!\n");1 */ + /*hang();1 */ + tmp_dunit_control_low = 0xC4000540; + } else + tmp_dunit_control_low = 0xC3000540;; + DP (printf + ("Max. CL is 2 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } + break; + case DDR_CL_1_5: + tmp_sdram_mode = 0x52; /* CL=1.5 Burstlength = 4 */ + if (tmp == 1) { /* clocks sync */ + if (info->registeredAddrAndControlInputs == 1) /* registerd DDR SDRAM? */ + tmp_dunit_control_low = 0x24110051; + else + tmp_dunit_control_low = 0x23110051; + DP (printf + ("Max. CL is 1.5 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + printf ("Warnning: DRAM ClkSync was never tested(db64460)!!!!!\n"); + } else { /* clk sync. bypassed */ + + if (info->registeredAddrAndControlInputs == 1) { /* registerd DDR SDRAM? */ + /*printf("CL = 1.5, Clock Unsync'ed, Dunit Control Low register setting undefined\n");1 */ + /*printf("Aborting!!!\n");1 */ + /*hang();1 */ + tmp_dunit_control_low = 0xC4000540; + } else + tmp_dunit_control_low = 0xC3000540; + DP (printf + ("Max. CL is 1.5 CLKs 0x141c= %08lx, 0x1404 = %08lx\n", + tmp_sdram_mode, tmp_dunit_control_low)); + } + break; + + default: + printf ("Max. CL is out of range %d\n", + info->maxClSupported_DDR); + hang (); + break; + } /* end DDR switch */ + break; + } /* end CL switch */ + + /* Write results of CL detection procedure */ + /* set SDRAM mode reg. 0x141c */ + GT_REG_WRITE (SDRAM_MODE, tmp_sdram_mode); + + /* set SDRAM mode SetCommand 0x1418 */ + GT_REG_WRITE (SDRAM_OPERATION, 0x3); + while (GTREGREAD (SDRAM_OPERATION) != 0) { + DP (printf + ("\n*** SDRAM_OPERATION 0x1418 after SDRAM_MODE: Module still busy ... please wait... ***\n")); + } + + /* SDRAM D_UNIT_CONTROL_LOW 0x1404 */ + GT_REG_WRITE (D_UNIT_CONTROL_LOW, tmp_dunit_control_low); + + /* set SDRAM mode SetCommand 0x1418 */ + GT_REG_WRITE (SDRAM_OPERATION, 0x3); + while (GTREGREAD (SDRAM_OPERATION) != 0) { + DP (printf + ("\n*** SDRAM_OPERATION 1418 after D_UNIT_CONTROL_LOW: Module still busy ... please wait... ***\n")); + } + +/*------------------------------------------------------------------------------ */ + + /* bank parameters */ + /* SDRAM address decode register 0x1410 */ + /* program this with the default value */ + tmp = 0x02; /* power-up default address select decoding value */ + + DP (printf ("drb_size (n*64Mbit): %d\n", info->drb_size)); +/* figure out the DRAM chip size */ + sdram_chip_size = + (1 << (info->numOfRowAddresses + info->numOfColAddresses)); + sdram_chip_size *= info->sdramWidth; + sdram_chip_size *= 4; + DP (printf ("computed sdram chip size is %#lx\n", sdram_chip_size)); + /* divide sdram chip size by 64 Mbits */ + sdram_chip_size = sdram_chip_size / 0x4000000; + switch (sdram_chip_size) { + case 1: /* 64 Mbit */ + case 2: /* 128 Mbit */ + DP (printf ("RAM-Device_size 64Mbit or 128Mbit)\n")); + tmp |= (0x00 << 4); + break; + case 4: /* 256 Mbit */ + case 8: /* 512 Mbit */ + DP (printf ("RAM-Device_size 256Mbit or 512Mbit)\n")); + tmp |= (0x01 << 4); + break; + case 16: /* 1 Gbit */ + case 32: /* 2 Gbit */ + DP (printf ("RAM-Device_size 1Gbit or 2Gbit)\n")); + tmp |= (0x02 << 4); + break; + default: + printf ("Error in dram size calculation\n"); + printf ("RAM-Device_size is unsupported\n"); + hang (); + } + + /* SDRAM address control */ + GT_REG_WRITE (SDRAM_ADDR_CONTROL, tmp); + DP (printf + ("setting up sdram address control (0x1410) with: %08lx \n", + tmp)); + +/* ------------------------------------------------------------------------------ */ +/* same settings for registerd & non-registerd DDR SDRAM */ + DP (printf + ("setting up sdram_timing_control_low (0x1408) with: %08x \n", + 0x01501220)); + /*ronen db64460 */ + GT_REG_WRITE (SDRAM_TIMING_CONTROL_LOW, 0x01501220); + + +/* ------------------------------------------------------------------------------ */ + + /* SDRAM configuration */ + tmp = GTREGREAD (SDRAM_CONFIG); + + if (info->registeredAddrAndControlInputs + || info->registeredDQMBinputs) { + tmp |= (1 << 17); + DP (printf + ("SPD says: registered Addr. and Cont.: %d; registered DQMBinputs: %d\n", + info->registeredAddrAndControlInputs, + info->registeredDQMBinputs)); + } + + /* Use buffer 1 to return read data to the CPU + * Page 426 MV6indent: Standard input:1464: Warning:old style assignment ambiguity in "=*". Assuming "= *" + +indent: Standard input:1465: Warning:old style assignment ambiguity in "=*". Assuming "= *" + +4460 */ + tmp |= (1 << 26); + DP (printf + ("Before Buffer assignment - sdram_conf (0x1400): %08x\n", + GTREGREAD (SDRAM_CONFIG))); + DP (printf + ("After Buffer assignment - sdram_conf (0x1400): %08x\n", + GTREGREAD (SDRAM_CONFIG))); + + /* SDRAM timing To_do: */ +/* ------------------------------------------------------------------------------ */ + /* ronen db64460 */ + DP (printf + ("setting up sdram_timing_control_high (0x140c) with: %08x \n", + 0xc)); + GT_REG_WRITE (SDRAM_TIMING_CONTROL_HIGH, 0xc); + + DP (printf + ("setting up sdram address pads control (0x14c0) with: %08x \n", + 0x7d5014a)); + GT_REG_WRITE (SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x7d5014a); + + DP (printf + ("setting up sdram data pads control (0x14c4) with: %08x \n", + 0x7d5014a)); + GT_REG_WRITE (SDRAM_DATA_PADS_CALIBRATION, 0x7d5014a); + +/* ------------------------------------------------------------------------------ */ + + /* set the SDRAM configuration for each bank */ + +/* for (i = info->slot * 2; i < ((info->slot * 2) + info->banks); i++) */ + { + i = info->slot; + DP (printf + ("\n*** Running a MRS cycle for bank %d ***\n", i)); + + /* map the bank */ + memory_map_bank (i, 0, GB / 4); + + /* set SDRAM mode */ /* To_do check it */ + GT_REG_WRITE (SDRAM_OPERATION, 0x3); + check = GTREGREAD (SDRAM_OPERATION); + DP (printf + ("\n*** SDRAM_OPERATION 1418 (0 = Normal Operation) = %08lx ***\n", + check)); + + + /* switch back to normal operation mode */ + GT_REG_WRITE (SDRAM_OPERATION, 0); + check = GTREGREAD (SDRAM_OPERATION); + DP (printf + ("\n*** SDRAM_OPERATION 1418 (0 = Normal Operation) = %08lx ***\n", + check)); + + /* unmap the bank */ + memory_map_bank (i, 0, 0); + } + + 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; +} + +/* ------------------------------------------------------------------------- */ + +/* ppcboot interface function to SDRAM init - this is where all the + * controlling logic happens */ +long int initdram (int board_type) +{ + int s0 = 0, s1 = 0; + int checkbank[4] = {[0 ... 3] = 0 }; + ulong realsize, total, check; + AUX_MEM_DIMM_INFO dimmInfo1; + AUX_MEM_DIMM_INFO dimmInfo2; + int nhr, bank_no; + ulong dest, memSpaceAttr; + + /* first, use the SPD to get info about the SDRAM/ DDRRAM */ + + /* check the NHR bit and skip mem init if it's already done */ + nhr = get_hid0 () & (1 << 16); + + if (nhr) { + printf ("Skipping SD- DDRRAM setup due to NHR bit being set\n"); + } else { + /* DIMM0 */ + s0 = check_dimm (0, &dimmInfo1); + + /* DIMM1 */ + s1 = check_dimm (1, &dimmInfo2); + + memory_map_bank (0, 0, 0); + memory_map_bank (1, 0, 0); + memory_map_bank (2, 0, 0); + memory_map_bank (3, 0, 0); + + /* ronen check correct set of DIMMS */ + if (dimmInfo1.numOfModuleBanks && dimmInfo2.numOfModuleBanks) { + if (dimmInfo1.errorCheckType != + dimmInfo2.errorCheckType) + printf ("***WARNNING***!!!! different ECC support of the DIMMS\n"); + if (dimmInfo1.maxClSupported_DDR != + dimmInfo2.maxClSupported_DDR) + printf ("***WARNNING***!!!! different CAL setting of the DIMMS\n"); + if (dimmInfo1.registeredAddrAndControlInputs != + dimmInfo2.registeredAddrAndControlInputs) + printf ("***WARNNING***!!!! different Registration setting of the DIMMS\n"); + } + + if (dimmInfo1.numOfModuleBanks && setup_sdram (&dimmInfo1)) { + printf ("Setup for DIMM1 failed.\n"); + } + + if (dimmInfo2.numOfModuleBanks && setup_sdram (&dimmInfo2)) { + printf ("Setup for DIMM2 failed.\n"); + } + + /* set the NHR bit */ + set_hid0 (get_hid0 () | (1 << 16)); + } + /* next, size the SDRAM banks */ + + realsize = total = 0; + check = GB / 4; + if (dimmInfo1.numOfModuleBanks > 0) { + checkbank[0] = 1; + } + if (dimmInfo1.numOfModuleBanks > 1) { + checkbank[1] = 1; + } + if (dimmInfo1.numOfModuleBanks > 2) + printf ("Error, SPD claims DIMM1 has >2 banks\n"); + + printf ("-- DIMM1 has %d banks\n", dimmInfo1.numOfModuleBanks); + + if (dimmInfo2.numOfModuleBanks > 0) { + checkbank[2] = 1; + } + if (dimmInfo2.numOfModuleBanks > 1) { + checkbank[3] = 1; + } + if (dimmInfo2.numOfModuleBanks > 2) + printf ("Error, SPD claims DIMM2 has >2 banks\n"); + + printf ("-- DIMM2 has %d banks\n", dimmInfo2.numOfModuleBanks); + + for (bank_no = 0; bank_no < CFG_DRAM_BANKS; bank_no++) { + /* skip over banks that are not populated */ + if (!checkbank[bank_no]) + continue; + + /* ronen - realsize = dram_size((long int *)total, check); */ + if (bank_no == 0 || bank_no == 1) { + if (checkbank[1] == 1) + realsize = dimmInfo1.size / 2; + else + realsize = dimmInfo1.size; + } + if (bank_no == 2 || bank_no == 3) { + if (checkbank[3] == 1) + realsize = dimmInfo2.size / 2; + else + realsize = dimmInfo2.size; + } + memory_map_bank (bank_no, total, realsize); + + /* ronen - initialize the DRAM for ECC */ +#ifdef CONFIG_MV64460_ECC + if ((dimmInfo1.errorCheckType != 0) && + ((dimmInfo2.errorCheckType != 0) + || (dimmInfo2.numOfModuleBanks == 0))) { + printf ("ECC Initialization of Bank %d:", bank_no); + memSpaceAttr = ((~(BIT0 << bank_no)) & 0xf) << 8; + mvDmaSetMemorySpace (0, 0, memSpaceAttr, total, + realsize); + for (dest = total; dest < total + realsize; + dest += _8M) { + mvDmaTransfer (0, total, dest, _8M, + BIT8 /*DMA_DTL_128BYTES */ | + BIT3 /*DMA_HOLD_SOURCE_ADDR */ + | + BIT11 + /*DMA_BLOCK_TRANSFER_MODE */ ); + while (mvDmaIsChannelActive (0)); + } + printf (" PASS\n"); + } +#endif + + total += realsize; + } + + /* ronen */ + switch ((GTREGREAD (0x141c) >> 4) & 0x7) { + case 0x2: + printf ("CAS Latency = 2"); + break; + case 0x3: + printf ("CAS Latency = 3"); + break; + case 0x5: + printf ("CAS Latency = 1.5"); + break; + case 0x6: + printf ("CAS Latency = 2.5"); + break; + } + printf (" tRP = %d tRAS = %d tRCD=%d\n", + ((GTREGREAD (0x1408) >> 8) & 0xf) + 1, + ((GTREGREAD (0x1408) >> 20) & 0xf) + 1, + ((GTREGREAD (0x1408) >> 4) & 0xf) + 1); + +/* Setup Ethernet DMA Adress window to DRAM Area */ + if (total > _256M) + printf ("*** ONLY the first 256MB DRAM memory are used out of the "); + else + printf ("Total SDRAM memory is "); + /* (cause all the 4 BATS are taken) */ + return (total); +} + + +/* ronen- add Idma functions for usage of the ecc dram init. */ +/******************************************************************************* +* mvDmaIsChannelActive - Checks if a engine is busy. +********************************************************************************/ +int mvDmaIsChannelActive (int engine) +{ + ulong data; + + data = GTREGREAD (MV64460_DMA_CHANNEL0_CONTROL + 4 * engine); + if (data & BIT14 /*activity status */ ) { + return 1; + } + return 0; +} + +/******************************************************************************* +* mvDmaSetMemorySpace - Set a DMA memory window for the DMA's address decoding +* map. +*******************************************************************************/ +int mvDmaSetMemorySpace (ulong memSpace, + ulong memSpaceTarget, + ulong memSpaceAttr, ulong baseAddress, ulong size) +{ + ulong temp; + + /* The base address must be aligned to the size. */ + if (baseAddress % size != 0) { + return 0; + } + if (size >= 0x10000 /*64K */ ) { + size &= 0xffff0000; + baseAddress = (baseAddress & 0xffff0000); + /* Set the new attributes */ + GT_REG_WRITE (MV64460_DMA_BASE_ADDR_REG0 + memSpace * 8, + (baseAddress | memSpaceTarget | memSpaceAttr)); + 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 sourceAddr to destAddr on one of the 4 +* DMA channels. +********************************************************************************/ +int mvDmaTransfer (int engine, ulong sourceAddr, + ulong destAddr, ulong numOfBytes, ulong command) +{ + ulong engOffReg = 0; /* Engine Offset Register */ + + if (numOfBytes > 0xffff) { + command = command | BIT31 /*DMA_16M_DESCRIPTOR_MODE */ ; + } + command = command | ((command >> 6) & 0x7); + engOffReg = engine * 4; + GT_REG_WRITE (MV64460_DMA_CHANNEL0_BYTE_COUNT + engOffReg, + numOfBytes); + 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 engine 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) +{ + /*ronen the dfcdl init are done by the I2C */ + return (0); +} diff --git a/board/Marvell/db64460/u-boot.lds b/board/Marvell/db64460/u-boot.lds new file mode 100644 index 0000000..0dfa8c0 --- /dev/null +++ b/board/Marvell/db64460/u-boot.lds @@ -0,0 +1,135 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, 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) + } + .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/board/Marvell/include/core.h b/board/Marvell/include/core.h new file mode 100644 index 0000000..081d5fd --- /dev/null +++ b/board/Marvell/include/core.h @@ -0,0 +1,238 @@ +/* Core.h - Basic core logic functions and definitions */ + +/* Copyright Galileo Technology. */ + +/* +DESCRIPTION +This header file contains simple read/write macros for addressing +the SDRAM, devices, GT`s internal registers and PCI (using the PCI`s address +space). The macros take care of Big/Little endian conversions. +*/ + +#ifndef __INCcoreh +#define __INCcoreh + +#include "mv_gen_reg.h" + +extern unsigned int INTERNAL_REG_BASE_ADDR; + +/****************************************/ +/* GENERAL Definitions */ +/****************************************/ + +#define NO_BIT 0x00000000 +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#define _1K 0x00000400 +#define _2K 0x00000800 +#define _4K 0x00001000 +#define _8K 0x00002000 +#define _16K 0x00004000 +#define _32K 0x00008000 +#define _64K 0x00010000 +#define _128K 0x00020000 +#define _256K 0x00040000 +#define _512K 0x00080000 + +#define _1M 0x00100000 +#define _2M 0x00200000 +#define _3M 0x00300000 +#define _4M 0x00400000 +#define _5M 0x00500000 +#define _6M 0x00600000 +#define _7M 0x00700000 +#define _8M 0x00800000 +#define _9M 0x00900000 +#define _10M 0x00a00000 +#define _11M 0x00b00000 +#define _12M 0x00c00000 +#define _13M 0x00d00000 +#define _14M 0x00e00000 +#define _15M 0x00f00000 +#define _16M 0x01000000 + +#define _32M 0x02000000 +#define _64M 0x04000000 +#define _128M 0x08000000 +#define _256M 0x10000000 +#define _512M 0x20000000 + +#define _1G 0x40000000 +#define _2G 0x80000000 + +typedef enum _bool{false,true} bool; + +/* Little to Big endian conversion macros */ + +#ifdef LE /* Little Endian */ +#define SHORT_SWAP(X) (X) +#define WORD_SWAP(X) (X) +#define LONG_SWAP(X) ((l64)(X)) + +#else /* Big Endian */ +#define SHORT_SWAP(X) ((X <<8 ) | (X >> 8)) + +#define WORD_SWAP(X) (((X)&0xff)<<24)+ \ + (((X)&0xff00)<<8)+ \ + (((X)&0xff0000)>>8)+ \ + (((X)&0xff000000)>>24) + +#define LONG_SWAP(X) ( (l64) (((X)&0xffULL)<<56)+ \ + (((X)&0xff00ULL)<<40)+ \ + (((X)&0xff0000ULL)<<24)+ \ + (((X)&0xff000000ULL)<<8)+ \ + (((X)&0xff00000000ULL)>>8)+ \ + (((X)&0xff0000000000ULL)>>24)+ \ + (((X)&0xff000000000000ULL)>>40)+ \ + (((X)&0xff00000000000000ULL)>>56)) + +#endif + +#ifndef NULL +#define NULL 0 +#endif + +/* Those two definitions were defined to be compatible with MIPS */ +#define NONE_CACHEABLE 0x00000000 +#define CACHEABLE 0x00000000 + +/* 750 cache line */ +#define CACHE_LINE_SIZE 32 +#define CACHELINE_MASK_BITS (CACHE_LINE_SIZE - 1) +#define CACHELINE_ROUNDUP(A) (((A)+CACHELINE_MASK_BITS) & ~CACHELINE_MASK_BITS) + +/* Read/Write to/from GT`s internal registers */ +#define GT_REG_READ(offset, pData) \ +*pData = ( *((volatile unsigned int *)(NONE_CACHEABLE | \ + INTERNAL_REG_BASE_ADDR | (offset))) ) ; \ +*pData = WORD_SWAP(*pData) + +#define GTREGREAD(offset) \ + (WORD_SWAP( *((volatile unsigned int *)(NONE_CACHEABLE | \ + INTERNAL_REG_BASE_ADDR | (offset))) )) + +#define GT_REG_WRITE(offset, data) \ +*((unsigned int *)( INTERNAL_REG_BASE_ADDR | (offset))) = \ + WORD_SWAP(data) + +/* Write 32/16/8 bit */ +#define WRITE_CHAR(address, data) \ + *((unsigned char *)(address)) = data +#define WRITE_SHORT(address, data) \ + *((unsigned short *)(address)) = data +#define WRITE_WORD(address, data) \ + *((unsigned int *)(address)) = data + +#define GT_WRITE_CHAR(address, data) WRITE_CHAR(address, data) + +/* Write 32/16/8 bit NonCacheable */ +/* +#define GT_WRITE_CHAR(address, data) \ + (*((unsigned char *)NONE_CACHEABLE(address))) = data +#define GT_WRITE_SHORT(address, data) \ + (*((unsigned short *)NONE_CACHEABLE(address))) = data +#define GT_WRITE_WORD(address, data) \ + (*((unsigned int *)NONE_CACHEABLE(address))) = data +*/ + /*#define GT_WRITE_CHAR(address, data) ((*((volatile unsigned char *)NONE_CACHEABLE((address)))) = ((unsigned char)(data)))1 */ + + /*#define GT_WRITE_SHORT(address, data) ((*((volatile unsigned short *)NONE_CACHEABLE((address)))) = ((unsigned short)(data)))1 */ + + /*#define GT_WRITE_WORD(address, data) ((*((volatile unsigned int *)NONE_CACHEABLE((address)))) = ((unsigned int)(data)))1 */ + + +/* Read 32/16/8 bits - returns data in variable. */ +#define READ_CHAR(address, pData) \ + *pData = *((volatile unsigned char *)(address)) + +#define READ_SHORT(address, pData) \ + *pData = *((volatile unsigned short *)(address)) + +#define READ_WORD(address, pData) \ + *pData = *((volatile unsigned int *)(address)) + +/* Read 32/16/8 bit - returns data direct. */ +#define READCHAR(address) \ + *((volatile unsigned char *)((address) | NONE_CACHEABLE)) + +#define READSHORT(address) \ + *((volatile unsigned short *)((address) | NONE_CACHEABLE)) + +#define READWORD(address) \ + *((volatile unsigned int *)((address) | NONE_CACHEABLE)) + +/* Those two Macros were defined to be compatible with MIPS */ +#define VIRTUAL_TO_PHY(x) (((unsigned int)x) & 0xffffffff) +#define PHY_TO_VIRTUAL(x) (((unsigned int)x) | NONE_CACHEABLE) + +/* SET_REG_BITS(regOffset,bits) - + gets register offset and bits: a 32bit value. It set to logic '1' in the + internal register the bits which given as an input example: + SET_REG_BITS(0x840,BIT3 | BIT24 | BIT30) - set bits: 3,24 and 30 to logic + '1' in register 0x840 while the other bits stays as is. */ +#define SET_REG_BITS(regOffset,bits) \ + *(unsigned int*)(NONE_CACHEABLE | INTERNAL_REG_BASE_ADDR | \ + regOffset) |= (unsigned int)WORD_SWAP(bits) + +/* RESET_REG_BITS(regOffset,bits) - + gets register offset and bits: a 32bit value. It set to logic '0' in the + internal register the bits which given as an input example: + RESET_REG_BITS(0x840,BIT3 | BIT24 | BIT30) - set bits: 3,24 and 30 to logic + '0' in register 0x840 while the other bits stays as is. */ +#define RESET_REG_BITS(regOffset,bits) \ + *(unsigned int*)(NONE_CACHEABLE | INTERNAL_REG_BASE_ADDR \ + | regOffset) &= ~( (unsigned int)WORD_SWAP(bits) ) +/* gets register offset and bits: a 32bit value. It set to logic '1' in the + internal register the bits which given as an input example: + GT_SET_REG_BITS(0x840,BIT3 | BIT24 | BIT30) - set bits: 3,24 and 30 to logic + '1' in register 0x840 while the other bits stays as is. */ + /*#define GT_SET_REG_BITS(regOffset,bits) ((*((volatile unsigned int*)(NONE_CACHEABLE(INTERNAL_REG_BASE_ADDR) | (regOffset)))) |= ((unsigned int)WORD_SWAP(bits)))1 */ + /*#define GT_SET_REG_BITS(regOffset,bits) RESET_REG_BITS(regOffset,bits)1 */ +#define GT_SET_REG_BITS(regOffset,bits) SET_REG_BITS(regOffset,bits) +/* gets register offset and bits: a 32bit value. It set to logic '0' in the + internal register the bits which given as an input example: + GT_RESET_REG_BITS(0x840,BIT3 | BIT24 | BIT30) - set bits: 3,24 and 30 to + logic '0' in register 0x840 while the other bits stays as is. */ + /*#define GT_RESET_REG_BITS(regOffset,bits) ((*((volatile unsigned int*)(NONE_CACHEABLE(INTERNAL_REG_BASE_ADDR) | (regOffset)))) &= ~((unsigned int)WORD_SWAP(bits)))1 */ +#define GT_RESET_REG_BITS(regOffset,bits) RESET_REG_BITS(regOffset,bits) + + +#define DEBUG_LED0_ON() WRITE_CHAR(memoryGetDeviceBaseAddress(DEVICE1) | 0x8000,0) +#define DEBUG_LED1_ON() WRITE_CHAR(memoryGetDeviceBaseAddress(DEVICE1) | 0xc000,0) +#define DEBUG_LED2_ON() WRITE_CHAR(memoryGetDeviceBaseAddress(DEVICE1) | 0x10000,0) +#define DEBUG_LED0_OFF() WRITE_CHAR(memoryGetDeviceBaseAddress(DEVICE1) | 0x14000,0) +#define DEBUG_LED1_OFF() WRITE_CHAR(memoryGetDeviceBaseAddress(DEVICE1) | 0x18000,0) +#define DEBUG_LED2_OFF() WRITE_CHAR(memoryGetDeviceBaseAddress(DEVICE1) | 0x1c000,0) + +#endif /* __INCcoreh */ diff --git a/board/Marvell/include/memory.h b/board/Marvell/include/memory.h new file mode 100644 index 0000000..0947b6e --- /dev/null +++ b/board/Marvell/include/memory.h @@ -0,0 +1,173 @@ +/* Memory.h - Memory mappings and remapping functions declarations */ + +/* Copyright - Galileo technology. */ + +#ifndef __INCmemoryh +#define __INCmemoryh + +/* includes */ + +#include "core.h" + +/* defines */ + +#define DONT_MODIFY 0xffffffff +#define PARITY_SUPPORT 0x40000000 +#define MINIMUM_MEM_BANK_SIZE 0x10000 +#define MINIMUM_DEVICE_WINDOW_SIZE 0x10000 +#define MINIMUM_PCI_WINDOW_SIZE 0x10000 +#define MINIMUM_ACCESS_WIN_SIZE 0x10000 + +#define _8BIT 0x00000000 +#define _16BIT 0x00100000 +#define _32BIT 0x00200000 +#define _64BIT 0x00300000 + +/* typedefs */ + + typedef struct deviceParam +{ /* boundary values */ + unsigned int turnOff; /* 0x0 - 0xf */ + unsigned int acc2First; /* 0x0 - 0x1f */ + unsigned int acc2Next; /* 0x0 - 0x1f */ + unsigned int ale2Wr; /* 0x0 - 0xf */ + unsigned int wrLow; /* 0x0 - 0xf */ + unsigned int wrHigh; /* 0x0 - 0xf */ + unsigned int badrSkew; /* 0x0 - 0x2 */ + unsigned int DPEn; /* 0x0 - 0x1 */ + unsigned int deviceWidth; /* in Bytes */ +} DEVICE_PARAM; + + +typedef enum __memBank{BANK0,BANK1,BANK2,BANK3} MEMORY_BANK; +typedef enum __memDevice{DEVICE0,DEVICE1,DEVICE2,DEVICE3,BOOT_DEVICE} DEVICE; + +/*typedef enum __memoryProtectRegion{MEM_REGION0,MEM_REGION1,MEM_REGION2, \ + MEM_REGION3,MEM_REGION4,MEM_REGION5, \ + MEM_REGION6,MEM_REGION7} \ + MEMORY_PROTECT_REGION;*/ +/* There are four possible windows that can be defined as protected */ +typedef enum _memoryProtectWindow{MEM_WINDOW0,MEM_WINDOW1,MEM_WINDOW2, + MEM_WINDOW3 + } MEMORY_PROTECT_WINDOW; +/* When defining a protected window , this paramter indicates whether it + is accessible or not */ +typedef enum __memoryAccess{MEM_ACCESS_ALLOWED,MEM_ACCESS_FORBIDEN} \ + MEMORY_ACCESS; +typedef enum __memoryWrite{MEM_WRITE_ALLOWED,MEM_WRITE_FORBIDEN} \ + MEMORY_ACCESS_WRITE; +typedef enum __memoryCacheProtect{MEM_CACHE_ALLOWED,MEM_CACHE_FORBIDEN} \ + MEMORY_CACHE_PROTECT; +typedef enum __memorySnoopType{MEM_NO_SNOOP,MEM_SNOOP_WT,MEM_SNOOP_WB} \ + MEMORY_SNOOP_TYPE; +typedef enum __memorySnoopRegion{MEM_SNOOP_REGION0,MEM_SNOOP_REGION1, \ + MEM_SNOOP_REGION2,MEM_SNOOP_REGION3} \ + MEMORY_SNOOP_REGION; + +/* There are 21 memory windows dedicated for the varios interfaces (PCI, + devCS (devices), CS(DDR), interenal registers and SRAM) used by the CPU's + address decoding mechanism. */ +typedef enum _memoryWindow {CS_0_WINDOW = BIT0, CS_1_WINDOW = BIT1, + CS_2_WINDOW = BIT2, CS_3_WINDOW = BIT3, + DEVCS_0_WINDOW = BIT4, DEVCS_1_WINDOW = BIT5, + DEVCS_2_WINDOW = BIT6, DEVCS_3_WINDOW = BIT7, + BOOT_CS_WINDOW = BIT8, PCI_0_IO_WINDOW = BIT9, + PCI_0_MEM0_WINDOW = BIT10, + PCI_0_MEM1_WINDOW = BIT11, + PCI_0_MEM2_WINDOW = BIT12, + PCI_0_MEM3_WINDOW = BIT13, PCI_1_IO_WINDOW = BIT14, + PCI_1_MEM0_WINDOW = BIT15, PCI_1_MEM1_WINDOW =BIT16, + PCI_1_MEM2_WINDOW = BIT17, PCI_1_MEM3_WINDOW =BIT18, + INTEGRATED_SRAM_WINDOW = BIT19, + INTERNAL_SPACE_WINDOW = BIT20, + ALL_WINDOWS = 0X1FFFFF + } MEMORY_WINDOW; + +typedef enum _memoryWindowStatus {MEM_WINDOW_ENABLED,MEM_WINDOW_DISABLED + } MEMORY_WINDOW_STATUS; + + +typedef enum _pciMemWindow{PCI_0_IO,PCI_0_MEM0,PCI_0_MEM1,PCI_0_MEM2,PCI_0_MEM3 +#ifdef INCLUDE_PCI_1 + ,PCI_1_IO,PCI_1_MEM0,PCI_1_MEM1,PCI_1_MEM2,PCI_1_MEM3 +#endif /* INCLUDE_PCI_1 */ + } PCI_MEM_WINDOW; + + +/* -------------------------------------------------------------------------------------------------*/ + +/* functions */ +unsigned int memoryGetBankBaseAddress(MEMORY_BANK bank); +unsigned int memoryGetDeviceBaseAddress(DEVICE device); +/* New at MV6436x */ +unsigned int MemoryGetPciBaseAddr(PCI_MEM_WINDOW pciWindow); +unsigned int memoryGetBankSize(MEMORY_BANK bank); +unsigned int memoryGetDeviceSize(DEVICE device); +unsigned int memoryGetDeviceWidth(DEVICE device); +/* New at MV6436x */ +unsigned int gtMemoryGetPciWindowSize(PCI_MEM_WINDOW pciWindow); + +/* when given base Address and size Set new WINDOW for SCS_X. (X = 0,1,2 or 3*/ +bool memoryMapBank(MEMORY_BANK bank, unsigned int bankBase,unsigned int bankLength); +/* Set a new base and size for one of the memory banks (CS0 - CS3) */ +bool gtMemorySetMemoryBank(MEMORY_BANK bank, unsigned int bankBase, + unsigned int bankSize); +bool memoryMapDeviceSpace(DEVICE device, unsigned int deviceBase,unsigned int deviceLength); + +/* Change the Internal Register Base Address to a new given Address. */ +bool memoryMapInternalRegistersSpace(unsigned int internalRegBase); +/* returns internal Register Space Base Address. */ +unsigned int memoryGetInternalRegistersSpace(void); + +/* Returns the integrated SRAM Base Address. */ +unsigned int memoryGetInternalSramBaseAddr(void); +/* -------------------------------------------------------------------------------------------------*/ + +/* Set new base address for the integrated SRAM. */ +void memorySetInternalSramBaseAddr(unsigned int sramBaseAddress); +/* -------------------------------------------------------------------------------------------------*/ + +/* Delete a protection feature to a given space. */ +void memoryDisableProtectRegion(MEMORY_PROTECT_WINDOW window); +/* -------------------------------------------------------------------------------------------------*/ + +/* Writes a new remap value to the remap register */ +unsigned int memorySetPciRemapValue(PCI_MEM_WINDOW memoryWindow, + unsigned int remapValueHigh, + unsigned int remapValueLow); +/* -------------------------------------------------------------------------------------------------*/ + +/* Configurate the protection feature to a given space. */ +bool memorySetProtectRegion(MEMORY_PROTECT_WINDOW window, + MEMORY_ACCESS gtMemoryAccess, + MEMORY_ACCESS_WRITE gtMemoryWrite, + MEMORY_CACHE_PROTECT cacheProtection, + unsigned int baseAddress, + unsigned int size); + +/* Configurate the protection feature to a given space. */ +/*bool memorySetProtectRegion(MEMORY_PROTECT_REGION region, + MEMORY_ACCESS memoryAccess, + MEMORY_ACCESS_WRITE memoryWrite, + MEMORY_CACHE_PROTECT cacheProtection, + unsigned int baseAddress, + unsigned int regionLength); */ +/* Configurate the snoop feature to a given space. */ +bool memorySetRegionSnoopMode(MEMORY_SNOOP_REGION region, + MEMORY_SNOOP_TYPE snoopType, + unsigned int baseAddress, + unsigned int regionLength); + +bool memoryRemapAddress(unsigned int remapReg, unsigned int remapValue); +bool memoryGetDeviceParam(DEVICE_PARAM *deviceParam, DEVICE deviceNum); +bool memorySetDeviceParam(DEVICE_PARAM *deviceParam, DEVICE deviceNum); +/* Set a new base and size for one of the PCI windows. */ +bool memorySetPciWindow(PCI_MEM_WINDOW pciWindow, unsigned int pciWindowBase, + unsigned int pciWindowSize); + +/* Disable or enable one of the 21 windows dedicated for the CPU's + address decoding mechanism */ +void MemoryDisableWindow(MEMORY_WINDOW window); +void MemoryEnableWindow (MEMORY_WINDOW window); +MEMORY_WINDOW_STATUS MemoryGetMemWindowStatus(MEMORY_WINDOW window); +#endif /* __INCmemoryh */ diff --git a/board/Marvell/include/mv_gen_reg.h b/board/Marvell/include/mv_gen_reg.h new file mode 100644 index 0000000..5e4f076 --- /dev/null +++ b/board/Marvell/include/mv_gen_reg.h @@ -0,0 +1,2288 @@ +/* mv_gen_reg.h - Internal registers definition file */ +/* Copyright - Galileo technology. */ + + +/******************************************************************************* +* Copyright 2002, GALILEO TECHNOLOGY, LTD. * +* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL. * +* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT * +* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE * +* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL. * +* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED, * +* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE. * +* * +* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES, * +* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL * +* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K. * +* (MJKK), GALILEO TECHNOLOGY LTD. (GTL) AND GALILEO TECHNOLOGY, INC. (GTI). * +******************************************************************************** +* mv_gen_reg.h - Marvell 64360 and 64460 Internal registers definition file. +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv_gen_regh +#define __INCmv_gen_regh + + +/* Supported by the Atlantis */ +#define INCLUDE_PCI_1 +#define INCLUDE_PCI_0_ARBITER +#define INCLUDE_PCI_1_ARBITER +#define INCLUDE_SNOOP_SUPPORT +#define INCLUDE_P2P +#define INCLUDE_ETH_PORT_2 +#define INCLUDE_CPU_MAPPING +#define INCLUDE_MPSC + +/* Not supported features */ +#undef INCLUDE_CNTMR_4_7 +#undef INCLUDE_DMA_4_7 + + +/****************************************/ +/* Processor Address Space */ +/****************************************/ +/* DDR SDRAM BAR and size registers */ + +/* Sdram's BAR'S */ +#define SCS_0_LOW_DECODE_ADDRESS 0x008 +#define SCS_0_HIGH_DECODE_ADDRESS 0x010 +#define SCS_1_LOW_DECODE_ADDRESS 0x208 +#define SCS_1_HIGH_DECODE_ADDRESS 0x210 +#define SCS_2_LOW_DECODE_ADDRESS 0x018 +#define SCS_2_HIGH_DECODE_ADDRESS 0x020 +#define SCS_3_LOW_DECODE_ADDRESS 0x218 +#define SCS_3_HIGH_DECODE_ADDRESS 0x220 + +/* Make it fit the MV64360 and MV64460 Lowlevel driver */ +#define CS_0_BASE_ADDR SCS_0_LOW_DECODE_ADDRESS +#define CS_0_SIZE SCS_0_HIGH_DECODE_ADDRESS +#define CS_1_BASE_ADDR SCS_1_LOW_DECODE_ADDRESS +#define CS_1_SIZE SCS_1_HIGH_DECODE_ADDRESS +#define CS_2_BASE_ADDR SCS_2_LOW_DECODE_ADDRESS +#define CS_2_SIZE SCS_2_HIGH_DECODE_ADDRESS +#define CS_3_BASE_ADDR SCS_3_LOW_DECODE_ADDRESS +#define CS_3_SIZE SCS_3_HIGH_DECODE_ADDRESS + +/* Devices BAR'S */ +#define CS_0_LOW_DECODE_ADDRESS 0x028 +#define CS_0_HIGH_DECODE_ADDRESS 0x030 +#define CS_1_LOW_DECODE_ADDRESS 0x228 +#define CS_1_HIGH_DECODE_ADDRESS 0x230 +#define CS_2_LOW_DECODE_ADDRESS 0x248 +#define CS_2_HIGH_DECODE_ADDRESS 0x250 +#define CS_3_LOW_DECODE_ADDRESS 0x038 +#define CS_3_HIGH_DECODE_ADDRESS 0x040 +#define BOOTCS_LOW_DECODE_ADDRESS 0x238 +#define BOOTCS_HIGH_DECODE_ADDRESS 0x240 + +/* Make it fit the MV64360 and MV64460 Lowlevel driver */ +/* Devices BAR and size registers */ + +#define DEV_CS0_BASE_ADDR CS_0_LOW_DECODE_ADDRESS +#define DEV_CS0_SIZE CS_0_HIGH_DECODE_ADDRESS +#define DEV_CS1_BASE_ADDR CS_1_LOW_DECODE_ADDRESS +#define DEV_CS1_SIZE CS_1_HIGH_DECODE_ADDRESS +#define DEV_CS2_BASE_ADDR CS_2_LOW_DECODE_ADDRESS +#define DEV_CS2_SIZE CS_2_HIGH_DECODE_ADDRESS +#define DEV_CS3_BASE_ADDR CS_3_LOW_DECODE_ADDRESS +#define DEV_CS3_SIZE CS_3_HIGH_DECODE_ADDRESS +#define BOOTCS_BASE_ADDR BOOTCS_LOW_DECODE_ADDRESS +#define BOOTCS_SIZE BOOTCS_HIGH_DECODE_ADDRESS + +/* PCI 0 BAR and size registers old names of evb64260*/ + +#define PCI_0I_O_LOW_DECODE_ADDRESS 0x048 +#define PCI_0I_O_HIGH_DECODE_ADDRESS 0x050 +#define PCI_0MEMORY0_LOW_DECODE_ADDRESS 0x058 +#define PCI_0MEMORY0_HIGH_DECODE_ADDRESS 0x060 +#define PCI_0MEMORY1_LOW_DECODE_ADDRESS 0x080 +#define PCI_0MEMORY1_HIGH_DECODE_ADDRESS 0x088 +#define PCI_0MEMORY2_LOW_DECODE_ADDRESS 0x258 +#define PCI_0MEMORY2_HIGH_DECODE_ADDRESS 0x260 +#define PCI_0MEMORY3_LOW_DECODE_ADDRESS 0x280 +#define PCI_0MEMORY3_HIGH_DECODE_ADDRESS 0x288 + +/* Make it fit the MV64360 and MV64460 Lowlevel driver */ +#define PCI_0_IO_BASE_ADDR 0x048 +#define PCI_0_IO_SIZE 0x050 +#define PCI_0_MEMORY0_BASE_ADDR 0x058 +#define PCI_0_MEMORY0_SIZE 0x060 +#define PCI_0_MEMORY1_BASE_ADDR 0x080 +#define PCI_0_MEMORY1_SIZE 0x088 +#define PCI_0_MEMORY2_BASE_ADDR 0x258 +#define PCI_0_MEMORY2_SIZE 0x260 +#define PCI_0_MEMORY3_BASE_ADDR 0x280 +#define PCI_0_MEMORY3_SIZE 0x288 + +/* PCI 1 BAR and size registers old names of evb64260*/ +#define PCI_1I_O_LOW_DECODE_ADDRESS 0x090 +#define PCI_1I_O_HIGH_DECODE_ADDRESS 0x098 +#define PCI_1MEMORY0_LOW_DECODE_ADDRESS 0x0a0 +#define PCI_1MEMORY0_HIGH_DECODE_ADDRESS 0x0a8 +#define PCI_1MEMORY1_LOW_DECODE_ADDRESS 0x0b0 +#define PCI_1MEMORY1_HIGH_DECODE_ADDRESS 0x0b8 +#define PCI_1MEMORY2_LOW_DECODE_ADDRESS 0x2a0 +#define PCI_1MEMORY2_HIGH_DECODE_ADDRESS 0x2a8 +#define PCI_1MEMORY3_LOW_DECODE_ADDRESS 0x2b0 +#define PCI_1MEMORY3_HIGH_DECODE_ADDRESS 0x2b8 + +/* Make it fit the MV64360 and MV64460 Lowlevel driver */ +#define PCI_1_IO_BASE_ADDR 0x090 +#define PCI_1_IO_SIZE 0x098 +#define PCI_1_MEMORY0_BASE_ADDR 0x0a0 +#define PCI_1_MEMORY0_SIZE 0x0a8 +#define PCI_1_MEMORY1_BASE_ADDR 0x0b0 +#define PCI_1_MEMORY1_SIZE 0x0b8 +#define PCI_1_MEMORY2_BASE_ADDR 0x2a0 +#define PCI_1_MEMORY2_SIZE 0x2a8 +#define PCI_1_MEMORY3_BASE_ADDR 0x2b0 +#define PCI_1_MEMORY3_SIZE 0x2b8 + +/* internal registers space base address */ +#define INTERNAL_SPACE_DECODE 0x068 +#define INTERNAL_SPACE_BASE_ADDR INTERNAL_SPACE_DECODE + +/* SRAM base address */ +#define INTEGRATED_SRAM_BASE_ADDR 0x268 + +/* Enables the CS , DEV_CS , PCI 0 and PCI 1 + windows above */ +#define BASE_ADDR_ENABLE 0x278 + + +#define CPU_0_LOW_DECODE_ADDRESS 0x290 +#define CPU_0_HIGH_DECODE_ADDRESS 0x298 +#define CPU_1_LOW_DECODE_ADDRESS 0x2c0 +#define CPU_1_HIGH_DECODE_ADDRESS 0x2c8 + +/****************************************/ +/* PCI remap registers */ +/****************************************/ +/*****************************************************************************************/ + /* PCI 0 */ +/* old fashion evb 64260 */ +#define PCI_0I_O_ADDRESS_REMAP 0x0f0 +#define PCI_0MEMORY0_ADDRESS_REMAP 0x0f8 +#define PCI_0MEMORY0_HIGH_ADDRESS_REMAP 0x320 +#define PCI_0MEMORY1_ADDRESS_REMAP 0x100 +#define PCI_0MEMORY1_HIGH_ADDRESS_REMAP 0x328 +#define PCI_0MEMORY2_ADDRESS_REMAP 0x2f8 +#define PCI_0MEMORY2_HIGH_ADDRESS_REMAP 0x330 +#define PCI_0MEMORY3_ADDRESS_REMAP 0x300 +#define PCI_0MEMORY3_HIGH_ADDRESS_REMAP 0x338 + +#define PCI_0_IO_ADDR_REMAP PCI_0I_O_ADDRESS_REMAP +#define PCI_0_MEMORY0_LOW_ADDR_REMAP PCI_0MEMORY0_ADDRESS_REMAP +#define PCI_0_MEMORY0_HIGH_ADDR_REMAP PCI_0MEMORY0_HIGH_ADDRESS_REMAP +#define PCI_0_MEMORY1_LOW_ADDR_REMAP PCI_0MEMORY1_ADDRESS_REMAP +#define PCI_0_MEMORY1_HIGH_ADDR_REMAP PCI_0MEMORY1_HIGH_ADDRESS_REMAP +#define PCI_0_MEMORY2_LOW_ADDR_REMAP PCI_0MEMORY2_ADDRESS_REMAP +#define PCI_0_MEMORY2_HIGH_ADDR_REMAP PCI_0MEMORY2_HIGH_ADDRESS_REMAP +#define PCI_0_MEMORY3_LOW_ADDR_REMAP PCI_0MEMORY3_ADDRESS_REMAP +#define PCI_0_MEMORY3_HIGH_ADDR_REMAP PCI_0MEMORY3_HIGH_ADDRESS_REMAP + + /* PCI 1 */ +/* old fashion evb 64260 */ +#define PCI_1I_O_ADDRESS_REMAP 0x108 +#define PCI_1MEMORY0_ADDRESS_REMAP 0x110 +#define PCI_1MEMORY0_HIGH_ADDRESS_REMAP 0x340 +#define PCI_1MEMORY1_ADDRESS_REMAP 0x118 +#define PCI_1MEMORY1_HIGH_ADDRESS_REMAP 0x348 +#define PCI_1MEMORY2_ADDRESS_REMAP 0x310 +#define PCI_1MEMORY2_HIGH_ADDRESS_REMAP 0x350 +#define PCI_1MEMORY3_ADDRESS_REMAP 0x318 +#define PCI_1MEMORY3_HIGH_ADDRESS_REMAP 0x358 + +#define PCI_1_IO_ADDR_REMAP PCI_1I_O_ADDRESS_REMAP +#define PCI_1_MEMORY0_LOW_ADDR_REMAP PCI_1MEMORY0_ADDRESS_REMAP +#define PCI_1_MEMORY0_HIGH_ADDR_REMAP PCI_1MEMORY0_HIGH_ADDRESS_REMAP +#define PCI_1_MEMORY1_LOW_ADDR_REMAP PCI_1MEMORY1_ADDRESS_REMAP +#define PCI_1_MEMORY1_HIGH_ADDR_REMAP PCI_1MEMORY1_HIGH_ADDRESS_REMAP +#define PCI_1_MEMORY2_LOW_ADDR_REMAP PCI_1MEMORY2_ADDRESS_REMAP +#define PCI_1_MEMORY2_HIGH_ADDR_REMAP PCI_1MEMORY2_HIGH_ADDRESS_REMAP +#define PCI_1_MEMORY3_LOW_ADDR_REMAP PCI_1MEMORY3_ADDRESS_REMAP +#define PCI_1_MEMORY3_HIGH_ADDR_REMAP PCI_1MEMORY3_HIGH_ADDRESS_REMAP + +/* old fashion evb 64260 */ +#define CPU_PCI_0_HEADERS_RETARGET_CONTROL 0x3b0 +#define CPU_PCI_0_HEADERS_RETARGET_BASE 0x3b8 +#define CPU_PCI_1_HEADERS_RETARGET_CONTROL 0x3c0 +#define CPU_PCI_1_HEADERS_RETARGET_BASE 0x3c8 +#define CPU_GE_HEADERS_RETARGET_CONTROL 0x3d0 +#define CPU_GE_HEADERS_RETARGET_BASE 0x3d8 + +/* MV64360 and MV64460 no changes needed*/ +/*****************************************************************************************/ + +/****************************************/ +/* CPU Control Registers */ +/****************************************/ +/* CPU MASTER CONTROL REGISTER */ +#define CPU_CONFIGURATION 0x000 +#define CPU_MASTER_CONTROL 0x160 + +#define CPU_CONFIG 0x000 +#define CPU_MODE 0x120 +#define CPU_MASTER_CONTROL 0x160 +/* new in MV64360 and MV64460 */ +#define CPU_CROSS_BAR_CONTROL_LOW 0x150 +#define CPU_CROSS_BAR_CONTROL_HIGH 0x158 +#define CPU_CROSS_BAR_TIMEOUT 0x168 + +/****************************************/ +/* SMP RegisterS */ +/****************************************/ + +#define SMP_WHO_AM_I 0x200 +#define SMP_CPU0_DOORBELL 0x214 +#define SMP_CPU0_DOORBELL_CLEAR 0x21C +#define SMP_CPU1_DOORBELL 0x224 +#define SMP_CPU1_DOORBELL_CLEAR 0x22C +#define SMP_CPU0_DOORBELL_MASK 0x234 +#define SMP_CPU1_DOORBELL_MASK 0x23C +#define SMP_SEMAPHOR0 0x244 +#define SMP_SEMAPHOR1 0x24c +#define SMP_SEMAPHOR2 0x254 +#define SMP_SEMAPHOR3 0x25c +#define SMP_SEMAPHOR4 0x264 +#define SMP_SEMAPHOR5 0x26c +#define SMP_SEMAPHOR6 0x274 +#define SMP_SEMAPHOR7 0x27c + + +/****************************************/ +/* CPU Sync Barrier */ +/****************************************/ +#define CPU_0_SYNC_BARRIER_TRIGGER 0x0c0 +#define CPU_0_SYNC_BARRIER_VIRTUAL 0x0c8 +#define CPU_1_SYNC_BARRIER_TRIGGER 0x0d0 +#define CPU_1_SYNC_BARRIER_VIRTUAL 0x0d8 + + +/****************************************/ +/* CPU Access Protect */ +/****************************************/ + +#define CPU_LOW_PROTECT_ADDRESS_0 0x180 +#define CPU_HIGH_PROTECT_ADDRESS_0 0x188 +#define CPU_LOW_PROTECT_ADDRESS_1 0x190 +#define CPU_HIGH_PROTECT_ADDRESS_1 0x198 +#define CPU_LOW_PROTECT_ADDRESS_2 0x1a0 +#define CPU_HIGH_PROTECT_ADDRESS_2 0x1a8 +#define CPU_LOW_PROTECT_ADDRESS_3 0x1b0 +#define CPU_HIGH_PROTECT_ADDRESS_3 0x1b8 +/*#define CPU_LOW_PROTECT_ADDRESS_4 0x1c0 +#define CPU_HIGH_PROTECT_ADDRESS_4 0x1c8 +#define CPU_LOW_PROTECT_ADDRESS_5 0x1d0 +#define CPU_HIGH_PROTECT_ADDRESS_5 0x1d8 +#define CPU_LOW_PROTECT_ADDRESS_6 0x1e0 +#define CPU_HIGH_PROTECT_ADDRESS_6 0x1e8 +#define CPU_LOW_PROTECT_ADDRESS_7 0x1f0 +#define CPU_HIGH_PROTECT_ADDRESS_7 0x1f8 +*/ + +#define CPU_PROTECT_WINDOW_0_BASE_ADDR CPU_LOW_PROTECT_ADDRESS_0 /* 0x180 */ +#define CPU_PROTECT_WINDOW_0_SIZE CPU_HIGH_PROTECT_ADDRESS_0 /* 0x188 */ +#define CPU_PROTECT_WINDOW_1_BASE_ADDR CPU_LOW_PROTECT_ADDRESS_1 /* 0x190 */ +#define CPU_PROTECT_WINDOW_1_SIZE CPU_HIGH_PROTECT_ADDRESS_1 /* 0x198 */ +#define CPU_PROTECT_WINDOW_2_BASE_ADDR CPU_LOW_PROTECT_ADDRESS_2 /*0x1a0 */ +#define CPU_PROTECT_WINDOW_2_SIZE CPU_HIGH_PROTECT_ADDRESS_2 /* 0x1a8 */ +#define CPU_PROTECT_WINDOW_3_BASE_ADDR CPU_LOW_PROTECT_ADDRESS_3 /* 0x1b0 */ +#define CPU_PROTECT_WINDOW_3_SIZE CPU_HIGH_PROTECT_ADDRESS_3 /* 0x1b8 */ + + +/****************************************/ +/* Snoop Control */ +/****************************************/ + +/*#define SNOOP_BASE_ADDRESS_0 0x380 +#define SNOOP_TOP_ADDRESS_0 0x388 +#define SNOOP_BASE_ADDRESS_1 0x390 +#define SNOOP_TOP_ADDRESS_1 0x398 +#define SNOOP_BASE_ADDRESS_2 0x3a0 +#define SNOOP_TOP_ADDRESS_2 0x3a8 +#define SNOOP_BASE_ADDRESS_3 0x3b0 +#define SNOOP_TOP_ADDRESS_3 0x3b8 +*/ + +/****************************************/ +/* Integrated SRAM Registers */ +/****************************************/ + +#define SRAM_CONFIG 0x380 +#define SRAM_TEST_MODE 0x3F4 +#define SRAM_ERROR_CAUSE 0x388 +#define SRAM_ERROR_ADDR 0x390 +#define SRAM_ERROR_ADDR_HIGH 0x3F8 +#define SRAM_ERROR_DATA_LOW 0x398 +#define SRAM_ERROR_DATA_HIGH 0x3a0 +#define SRAM_ERROR_DATA_PARITY 0x3a8 + +/****************************************/ +/* CPU Error Report */ +/****************************************/ + +#define CPU_ERROR_ADDRESS_LOW 0x070 +#define CPU_ERROR_ADDRESS_HIGH 0x078 +#define CPU_ERROR_DATA_LOW 0x128 +#define CPU_ERROR_DATA_HIGH 0x130 +#define CPU_ERROR_PARITY 0x138 +#define CPU_ERROR_CAUSE 0x140 +#define CPU_ERROR_MASK 0x148 + +#define CPU_ERROR_ADDR_LOW CPU_ERROR_ADDRESS_LOW /* 0x0701 */ +#define CPU_ERROR_ADDR_HIGH CPU_ERROR_ADDRESS_HIGH /* 0x0781 */ + +/****************************************/ +/* Pslave Debug */ +/* CPU Interface Debug Registers */ +/****************************************/ + +#define X_0_ADDRESS 0x360 +#define X_0_COMMAND_ID 0x368 +#define X_1_ADDRESS 0x370 +#define X_1_COMMAND_ID 0x378 + /*#define WRITE_DATA_LOW 0x3c01 */ + /*#define WRITE_DATA_HIGH 0x3c81 */ + /*#define WRITE_BYTE_ENABLE 0x3e01 */ + /*#define READ_DATA_LOW 0x3d01 */ + /*#define READ_DATA_HIGH 0x3d81 */ + /*#define READ_ID 0x3e81 */ + +#define PUNIT_SLAVE_DEBUG_LOW X_0_ADDRESS /* 0x3601 */ +#define PUNIT_SLAVE_DEBUG_HIGH X_0_COMMAND_ID /* 0x3681 */ +#define PUNIT_MASTER_DEBUG_LOW X_1_ADDRESS /* 0x3701 */ +#define PUNIT_MASTER_DEBUG_HIGH X_1_COMMAND_ID /* 0x3781 */ +#define PUNIT_MMASK 0x3e4 + + +/****************************************/ +/* SDRAM and Device Address Space */ +/****************************************/ + +/****************************************/ +/* SDRAM Configuration */ +/****************************************/ +#define SDRAM_CONFIG 0x1400 /* MV64260 0x448 some changes*/ +#define D_UNIT_CONTROL_LOW 0x1404 /* NEW in MV64360 and MV64460 */ +#define D_UNIT_CONTROL_HIGH 0x1424 /* NEW in MV64360 and MV64460 */ +#define SDRAM_TIMING_CONTROL_LOW 0x1408 /* MV64260 0x4b4 new SDRAM TIMING REGISTER */ +#define SDRAM_TIMING_CONTROL_HIGH 0x140c /* MV64260 0x4b4 new SDRAM TIMING REGISTER */ +#define SDRAM_ADDR_CONTROL 0x1410 /* MV64260 0x47c some changes*/ +#define SDRAM_OPEN_PAGES_CONTROL 0x1414 /* NEW in MV64360 and MV64460 */ +#define SDRAM_OPERATION 0x1418 /* MV64260 0x474 some changes*/ +#define SDRAM_MODE 0x141c /* NEW in MV64360 and MV64460 */ +#define EXTENDED_DRAM_MODE 0x1420 /* NEW in MV64360 and MV64460 */ +#define SDRAM_CROSS_BAR_CONTROL_LOW 0x1430 /* MV64260 0x4a8 NO changes*/ +#define SDRAM_CROSS_BAR_CONTROL_HIGH 0x1434 /* MV64260 0x4ac NO changes*/ +#define SDRAM_CROSS_BAR_TIMEOUT 0x1438 /* MV64260 0x4b0 NO changes*/ +#define SDRAM_ADDR_CTRL_PADS_CALIBRATION 0x14c0 /* what is this ??? */ +#define SDRAM_DATA_PADS_CALIBRATION 0x14c4 /* what is this ??? */ +/****************************************/ +/* SDRAM Configuration MV64260 */ +/****************************************/ + /*#define SDRAM_CONFIGURATION 0x4481 */ + /*#define SDRAM_OPERATION_MODE 0x4741 */ + /*#define SDRAM_ADDRESS_DECODE 0x47c1 */ + /*#define SDRAM_UMA_CONTROL 0x4a4 eliminated in MV64360 and MV64460 */ + /*#define SDRAM_CROSS_BAR_CONTROL_LOW 0x4a81 */ + /*#define SDRAM_CROSS_BAR_CONTROL_HIGH 0x4ac1 */ + /*#define SDRAM_CROSS_BAR_TIMEOUT 0x4b01 */ + /*#define SDRAM_TIMING 0x4b41 */ + + +/****************************************/ +/* SDRAM Error Report */ +/****************************************/ +#define SDRAM_ERROR_DATA_LOW 0x1444 /* MV64260 0x484 NO changes*/ +#define SDRAM_ERROR_DATA_HIGH 0x1440 /* MV64260 0x480 NO changes*/ +#define SDRAM_ERROR_ADDR 0x1450 /* MV64260 0x490 NO changes*/ +#define SDRAM_RECEIVED_ECC 0x1448 /* MV64260 0x488 NO changes*/ +#define SDRAM_CALCULATED_ECC 0x144c /* MV64260 0x48c NO changes*/ +#define SDRAM_ECC_CONTROL 0x1454 /* MV64260 0x494 NO changes*/ +#define SDRAM_ECC_ERROR_COUNTER 0x1458 /* MV64260 0x498 NO changes*/ +#define SDRAM_MMASK 0x1B40 /* NEW Register in MV64360 and MV64460 DO NOT USE !!!*/ +/****************************************/ +/* SDRAM Error Report MV64260 */ +/****************************************/ + /*#define SDRAM_ERROR_DATA_LOW 0x4841 */ + /*#define SDRAM_ERROR_DATA_HIGH 0x4801 */ + /*#define SDRAM_AND_DEVICE_ERROR_ADDRESS 0x4901 */ + /*#define SDRAM_RECEIVED_ECC 0x4881 */ + /*#define SDRAM_CALCULATED_ECC 0x48c1 */ + /*#define SDRAM_ECC_CONTROL 0x4941 */ + /*#define SDRAM_ECC_ERROR_COUNTER 0x4981 */ + +/******************************************/ +/* Controlled Delay Line (CDL) Registers */ +/******************************************/ +#define DFCDL_CONFIG0 0x1480 +#define DFCDL_CONFIG1 0x1484 +#define DLL_WRITE 0x1488 +#define DLL_READ 0x148c +#define SRAM_ADDR 0x1490 +#define SRAM_DATA0 0x1494 +#define SRAM_DATA1 0x1498 +#define SRAM_DATA2 0x149c +#define DFCL_PROBE 0x14a0 + + +/****************************************/ +/* SDRAM Parameters only in MV64260 */ +/****************************************/ + + /*#define SDRAM_BANK0PARAMETERS 0x44C eliminated in MV64360 and MV64460 */ + /*#define SDRAM_BANK1PARAMETERS 0x450 eliminated in MV64360 and MV64460 */ + /*#define SDRAM_BANK2PARAMETERS 0x454 eliminated in MV64360 and MV64460 */ + /*#define SDRAM_BANK3PARAMETERS 0x458 eliminated in MV64360 and MV64460 */ + +/******************************************/ +/* Debug Registers */ +/******************************************/ + +#define DUNIT_DEBUG_LOW 0x1460 +#define DUNIT_DEBUG_HIGH 0x1464 +#define DUNIT_MMASK 0x1b40 + +/****************************************/ +/* SDunit Debug (for internal use) */ +/****************************************/ + +#define X0_ADDRESS 0x500 +#define X0_COMMAND_AND_ID 0x504 +#define X0_WRITE_DATA_LOW 0x508 +#define X0_WRITE_DATA_HIGH 0x50c +#define X0_WRITE_BYTE_ENABLE 0x518 +#define X0_READ_DATA_LOW 0x510 +#define X0_READ_DATA_HIGH 0x514 +#define X0_READ_ID 0x51c +#define X1_ADDRESS 0x520 +#define X1_COMMAND_AND_ID 0x524 +#define X1_WRITE_DATA_LOW 0x528 +#define X1_WRITE_DATA_HIGH 0x52c +#define X1_WRITE_BYTE_ENABLE 0x538 +#define X1_READ_DATA_LOW 0x530 +#define X1_READ_DATA_HIGH 0x534 +#define X1_READ_ID 0x53c +#define X0_SNOOP_ADDRESS 0x540 +#define X0_SNOOP_COMMAND 0x544 +#define X1_SNOOP_ADDRESS 0x548 +#define X1_SNOOP_COMMAND 0x54c + +/****************************************/ +/* Device Parameters */ +/****************************************/ + +#define DEVICE_BANK0PARAMETERS 0x45c +#define DEVICE_BANK1PARAMETERS 0x460 +#define DEVICE_BANK2PARAMETERS 0x464 +#define DEVICE_BANK3PARAMETERS 0x468 +#define DEVICE_BOOT_BANK_PARAMETERS 0x46c +#define DEVICE_CONTROL 0x4c0 +#define DEVICE_CROSS_BAR_CONTROL_LOW 0x4c8 +#define DEVICE_CROSS_BAR_CONTROL_HIGH 0x4cc +#define DEVICE_CROSS_BAR_TIMEOUT 0x4c4 + +/****************************************/ +/* Device Parameters */ +/****************************************/ + +#define DEVICE_BANK0_PARAMETERS DEVICE_BANK0PARAMETERS /* 0x45c1 */ +#define DEVICE_BANK1_PARAMETERS DEVICE_BANK1PARAMETERS /* 0x4601 */ +#define DEVICE_BANK2_PARAMETERS DEVICE_BANK2PARAMETERS /* 0x4641 */ +#define DEVICE_BANK3_PARAMETERS DEVICE_BANK3PARAMETERS /* 0x4681 */ +/*#define DEVICE_BOOT_BANK_PARAMETERS 0x46c1 */ +#define DEVICE_INTERFACE_CONTROL DEVICE_CONTROL /* 0x4c01 */ +#define DEVICE_INTERFACE_CROSS_BAR_CONTROL_LOW DEVICE_CROSS_BAR_CONTROL_LOW /* 0x4c81 */ +#define DEVICE_INTERFACE_CROSS_BAR_CONTROL_HIGH DEVICE_CROSS_BAR_CONTROL_HIGH /* 0x4cc1 */ +#define DEVICE_INTERFACE_CROSS_BAR_TIMEOUT DEVICE_CROSS_BAR_TIMEOUT /* 0x4c41 */ + + +/****************************************/ +/* Device Interrupt */ +/****************************************/ + +#define DEVICE_INTERRUPT_CAUSE 0x4d0 +#define DEVICE_INTERRUPT_MASK 0x4d4 +#define DEVICE_ERROR_ADDRESS 0x4d8 + /*#define DEVICE_INTERRUPT_CAUSE 0x4d01 */ + /*#define DEVICE_INTERRUPT_MASK 0x4d41 */ +#define DEVICE_ERROR_ADDR DEVICE_ERROR_ADDRESS /*0x4d81 */ +#define DEVICE_ERROR_DATA 0x4dc +#define DEVICE_ERROR_PARITY 0x4e0 + +/****************************************/ +/* Device debug registers */ +/****************************************/ + +#define DEVICE_DEBUG_LOW 0x4e4 +#define DEVICE_DEBUG_HIGH 0x4e8 +#define RUNIT_MMASK 0x4f0 + +/****************************************/ +/* DMA Record */ +/****************************************/ + + /*#define CHANNEL4_DMA_BYTE_COUNT 0x9001 */ + /*#define CHANNEL5_DMA_BYTE_COUNT 0x9041 */ + /*#define CHANNEL6_DMA_BYTE_COUNT 0x9081 */ + /*#define CHANNEL7_DMA_BYTE_COUNT 0x90C1 */ + /*#define CHANNEL4_DMA_SOURCE_ADDRESS 0x9101 */ + /*#define CHANNEL5_DMA_SOURCE_ADDRESS 0x9141 */ + /*#define CHANNEL6_DMA_SOURCE_ADDRESS 0x9181 */ + /*#define CHANNEL7_DMA_SOURCE_ADDRESS 0x91C1 */ + /*#define CHANNEL4_DMA_DESTINATION_ADDRESS 0x9201 */ + /*#define CHANNEL5_DMA_DESTINATION_ADDRESS 0x9241 */ + /*#define CHANNEL6_DMA_DESTINATION_ADDRESS 0x9281 */ + /*#define CHANNEL7_DMA_DESTINATION_ADDRESS 0x92C1 */ + /*#define CHANNEL4NEXT_RECORD_POINTER 0x9301 */ + /*#define CHANNEL5NEXT_RECORD_POINTER 0x9341 */ + /*#define CHANNEL6NEXT_RECORD_POINTER 0x9381 */ + /*#define CHANNEL7NEXT_RECORD_POINTER 0x93C1 */ + /*#define CHANNEL4CURRENT_DESCRIPTOR_POINTER 0x9701 */ + /*#define CHANNEL5CURRENT_DESCRIPTOR_POINTER 0x9741 */ + /*#define CHANNEL6CURRENT_DESCRIPTOR_POINTER 0x9781 */ + /*#define CHANNEL7CURRENT_DESCRIPTOR_POINTER 0x97C1 */ + /*#define CHANNEL0_DMA_SOURCE_HIGH_PCI_ADDRESS 0x8901 */ + /*#define CHANNEL1_DMA_SOURCE_HIGH_PCI_ADDRESS 0x8941 */ + /*#define CHANNEL2_DMA_SOURCE_HIGH_PCI_ADDRESS 0x8981 */ + /*#define CHANNEL3_DMA_SOURCE_HIGH_PCI_ADDRESS 0x89c1 */ + /*#define CHANNEL4_DMA_SOURCE_HIGH_PCI_ADDRESS 0x9901 */ + /*#define CHANNEL5_DMA_SOURCE_HIGH_PCI_ADDRESS 0x9941 */ + /*#define CHANNEL6_DMA_SOURCE_HIGH_PCI_ADDRESS 0x9981 */ + /*#define CHANNEL7_DMA_SOURCE_HIGH_PCI_ADDRESS 0x99c1 */ + /*#define CHANNEL0_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x8a01 */ + /*#define CHANNEL1_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x8a41 */ + /*#define CHANNEL2_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x8a81 */ + /*#define CHANNEL3_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x8ac1 */ + /*#define CHANNEL4_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x9a01 */ + /*#define CHANNEL5_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x9a41 */ + /*#define CHANNEL6_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x9a81 */ + /*#define CHANNEL7_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x9ac1 */ + /*#define CHANNEL0_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x8b01 */ + /*#define CHANNEL1_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x8b41 */ + /*#define CHANNEL2_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x8b81 */ + /*#define CHANNEL3_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x8bc1 */ + /*#define CHANNEL4_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x9b01 */ + /*#define CHANNEL5_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x9b41 */ + /*#define CHANNEL6_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x9b81 */ + /*#define CHANNEL7_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x9bc1 */ + +/****************************************/ +/* DMA Channel Control */ +/****************************************/ + +#define CHANNEL0CONTROL 0x840 +#define CHANNEL0CONTROL_HIGH 0x880 +#define CHANNEL1CONTROL 0x844 +#define CHANNEL1CONTROL_HIGH 0x884 +#define CHANNEL2CONTROL 0x848 +#define CHANNEL2CONTROL_HIGH 0x888 +#define CHANNEL3CONTROL 0x84C +#define CHANNEL3CONTROL_HIGH 0x88C + +#define DMA_CHANNEL0_CONTROL CHANNEL0CONTROL /*0x8401 */ +#define DMA_CHANNEL0_CONTROL_HIGH CHANNEL0CONTROL_HIGH /*0x8801 */ +#define DMA_CHANNEL1_CONTROL CHANNEL1CONTROL /* 0x8441 */ +#define DMA_CHANNEL1_CONTROL_HIGH CHANNEL1CONTROL_HIGH /*0x8841 */ +#define DMA_CHANNEL2_CONTROL CHANNEL2CONTROL /*0x8481 */ +#define DMA_CHANNEL2_CONTROL_HIGH CHANNEL2CONTROL_HIGH /*0x8881 */ +#define DMA_CHANNEL3_CONTROL CHANNEL3CONTROL /*0x84C1 */ +#define DMA_CHANNEL3_CONTROL_HIGH CHANNEL3CONTROL_HIGH /*0x88C1 */ + + /*#define CHANNEL4CONTROL 0x9401 */ + /*#define CHANNEL4CONTROL_HIGH 0x9801 */ + /*#define CHANNEL5CONTROL 0x9441 */ + /*#define CHANNEL5CONTROL_HIGH 0x9841 */ + /*#define CHANNEL6CONTROL 0x9481 */ + /*#define CHANNEL6CONTROL_HIGH 0x9881 */ + /*#define CHANNEL7CONTROL 0x94C1 */ + /*#define CHANNEL7CONTROL_HIGH 0x98C1 */ + + +/****************************************/ +/* DMA Arbiter */ +/****************************************/ + + /*#define ARBITER_CONTROL_0_3 0x8601 */ +#define ARBITER_CONTROL_4_7 0x960 +/****************************************/ +/* IDMA Registers */ +/****************************************/ + +#define DMA_CHANNEL0_BYTE_COUNT CHANNEL0_DMA_BYTE_COUNT /*0x8001 */ +#define DMA_CHANNEL1_BYTE_COUNT CHANNEL1_DMA_BYTE_COUNT /*0x8041 */ +#define DMA_CHANNEL2_BYTE_COUNT CHANNEL2_DMA_BYTE_COUNT /*0x8081 */ +#define DMA_CHANNEL3_BYTE_COUNT CHANNEL3_DMA_BYTE_COUNT /*0x80C1 */ +#define DMA_CHANNEL0_SOURCE_ADDR CHANNEL0_DMA_SOURCE_ADDRESS /*0x8101 */ +#define DMA_CHANNEL1_SOURCE_ADDR CHANNEL1_DMA_SOURCE_ADDRESS /*0x8141 */ +#define DMA_CHANNEL2_SOURCE_ADDR CHANNEL2_DMA_SOURCE_ADDRESS /*0x8181 */ +#define DMA_CHANNEL3_SOURCE_ADDR CHANNEL3_DMA_SOURCE_ADDRESS /*0x81c1 */ +#define DMA_CHANNEL0_DESTINATION_ADDR CHANNEL0_DMA_DESTINATION_ADDRESS /*0x8201 */ +#define DMA_CHANNEL1_DESTINATION_ADDR CHANNEL1_DMA_DESTINATION_ADDRESS /*0x8241 */ +#define DMA_CHANNEL2_DESTINATION_ADDR CHANNEL2_DMA_DESTINATION_ADDRESS /*0x8281 */ +#define DMA_CHANNEL3_DESTINATION_ADDR CHANNEL3_DMA_DESTINATION_ADDRESS /*0x82C1 */ +#define DMA_CHANNEL0_NEXT_DESCRIPTOR_POINTER CHANNEL0NEXT_RECORD_POINTER /*0x8301 */ +#define DMA_CHANNEL1_NEXT_DESCRIPTOR_POINTER CHANNEL1NEXT_RECORD_POINTER /*0x8341 */ +#define DMA_CHANNEL2_NEXT_DESCRIPTOR_POINTER CHANNEL2NEXT_RECORD_POINTER /*0x8381 */ +#define DMA_CHANNEL3_NEXT_DESCRIPTOR_POINTER CHANNEL3NEXT_RECORD_POINTER /*0x83C1 */ +#define DMA_CHANNEL0_CURRENT_DESCRIPTOR_POINTER CHANNEL0CURRENT_DESCRIPTOR_POINTER /*0x8701 */ +#define DMA_CHANNEL1_CURRENT_DESCRIPTOR_POINTER CHANNEL1CURRENT_DESCRIPTOR_POINTER /*0x8741 */ +#define DMA_CHANNEL2_CURRENT_DESCRIPTOR_POINTER CHANNEL2CURRENT_DESCRIPTOR_POINTER /*0x8781 */ +#define DMA_CHANNEL3_CURRENT_DESCRIPTOR_POINTER CHANNEL3CURRENT_DESCRIPTOR_POINTER /*0x87C1 */ + +#define CHANNEL3CURRENT_DESCRIPTOR_POINTER 0x87C +#define CHANNEL2CURRENT_DESCRIPTOR_POINTER 0x878 +#define CHANNEL1CURRENT_DESCRIPTOR_POINTER 0x874 +#define CHANNEL0CURRENT_DESCRIPTOR_POINTER 0x870 +#define CHANNEL0NEXT_RECORD_POINTER 0x830 +#define CHANNEL1NEXT_RECORD_POINTER 0x834 +#define CHANNEL2NEXT_RECORD_POINTER 0x838 +#define CHANNEL3NEXT_RECORD_POINTER 0x83C +#define CHANNEL0_DMA_DESTINATION_ADDRESS 0x820 +#define CHANNEL1_DMA_DESTINATION_ADDRESS 0x824 +#define CHANNEL2_DMA_DESTINATION_ADDRESS 0x828 +#define CHANNEL3_DMA_DESTINATION_ADDRESS 0x82C +#define CHANNEL0_DMA_SOURCE_ADDRESS 0x810 +#define CHANNEL1_DMA_SOURCE_ADDRESS 0x814 +#define CHANNEL2_DMA_SOURCE_ADDRESS 0x818 +#define CHANNEL3_DMA_SOURCE_ADDRESS 0x81C +#define CHANNEL0_DMA_BYTE_COUNT 0x800 +#define CHANNEL1_DMA_BYTE_COUNT 0x804 +#define CHANNEL2_DMA_BYTE_COUNT 0x808 +#define CHANNEL3_DMA_BYTE_COUNT 0x80C + + /* IDMA Address Decoding Base Address Registers */ + +#define DMA_BASE_ADDR_REG0 0xa00 +#define DMA_BASE_ADDR_REG1 0xa08 +#define DMA_BASE_ADDR_REG2 0xa10 +#define DMA_BASE_ADDR_REG3 0xa18 +#define DMA_BASE_ADDR_REG4 0xa20 +#define DMA_BASE_ADDR_REG5 0xa28 +#define DMA_BASE_ADDR_REG6 0xa30 +#define DMA_BASE_ADDR_REG7 0xa38 + + /* IDMA Address Decoding Size Address Register */ + +#define DMA_SIZE_REG0 0xa04 +#define DMA_SIZE_REG1 0xa0c +#define DMA_SIZE_REG2 0xa14 +#define DMA_SIZE_REG3 0xa1c +#define DMA_SIZE_REG4 0xa24 +#define DMA_SIZE_REG5 0xa2c +#define DMA_SIZE_REG6 0xa34 +#define DMA_SIZE_REG7 0xa3C + + /* IDMA Address Decoding High Address Remap and Access + Protection Registers */ + +#define DMA_HIGH_ADDR_REMAP_REG0 0xa60 +#define DMA_HIGH_ADDR_REMAP_REG1 0xa64 +#define DMA_HIGH_ADDR_REMAP_REG2 0xa68 +#define DMA_HIGH_ADDR_REMAP_REG3 0xa6C +#define DMA_BASE_ADDR_ENABLE_REG 0xa80 +#define DMA_CHANNEL0_ACCESS_PROTECTION_REG 0xa70 +#define DMA_CHANNEL1_ACCESS_PROTECTION_REG 0xa74 +#define DMA_CHANNEL2_ACCESS_PROTECTION_REG 0xa78 +#define DMA_CHANNEL3_ACCESS_PROTECTION_REG 0xa7c +#define DMA_ARBITER_CONTROL 0x860 +#define DMA_CROSS_BAR_TIMEOUT 0x8d0 + + /* IDMA Headers Retarget Registers */ + + /*#define CPU_IDMA_HEADERS_RETARGET_CONTROL 0x3e01 */ + /*#define CPU_IDMA_HEADERS_RETARGET_BASE 0x3e81 */ + +#define DMA_HEADERS_RETARGET_CONTROL 0xa84 +#define DMA_HEADERS_RETARGET_BASE 0xa88 + +/****************************************/ +/* DMA Interrupt */ +/****************************************/ + +#define CHANELS0_3_INTERRUPT_CAUSE 0x8c0 +#define CHANELS0_3_INTERRUPT_MASK 0x8c4 +#define CHANELS0_3_ERROR_ADDRESS 0x8c8 +#define CHANELS0_3_ERROR_SELECT 0x8cc + /*#define CHANELS4_7_INTERRUPT_CAUSE 0x9c01 */ + /*#define CHANELS4_7_INTERRUPT_MASK 0x9c41 */ + /*#define CHANELS4_7_ERROR_ADDRESS 0x9c81 */ + /*#define CHANELS4_7_ERROR_SELECT 0x9cc1 */ + +#define DMA_INTERRUPT_CAUSE_REG CHANELS0_3_INTERRUPT_CAUSE /*0x8c01 */ +#define DMA_INTERRUPT_CAUSE_MASK CHANELS0_3_INTERRUPT_MASK /*0x8c41 */ +#define DMA_ERROR_ADDR CHANELS0_3_ERROR_ADDRESS /*0x8c81 */ +#define DMA_ERROR_SELECT CHANELS0_3_ERROR_SELECT /*0x8cc1 */ + + +/****************************************/ +/* DMA Debug (for internal use) */ +/****************************************/ + +#define DMA_X0_ADDRESS 0x8e0 +#define DMA_X0_COMMAND_AND_ID 0x8e4 + /*#define DMA_X0_WRITE_DATA_LOW 0x8e81 */ + /*#define DMA_X0_WRITE_DATA_HIGH 0x8ec1 */ + /*#define DMA_X0_WRITE_BYTE_ENABLE 0x8f81 */ + /*#define DMA_X0_READ_DATA_LOW 0x8f01 */ + /*#define DMA_X0_READ_DATA_HIGH 0x8f41 */ + /*#define DMA_X0_READ_ID 0x8fc1 */ + /*#define DMA_X1_ADDRESS 0x9e01 */ + /*#define DMA_X1_COMMAND_AND_ID 0x9e41 */ + /*#define DMA_X1_WRITE_DATA_LOW 0x9e81 */ + /*#define DMA_X1_WRITE_DATA_HIGH 0x9ec1 */ + /*#define DMA_X1_WRITE_BYTE_ENABLE 0x9f81 */ + /*#define DMA_X1_READ_DATA_LOW 0x9f01 */ + /*#define DMA_X1_READ_DATA_HIGH 0x9f41 */ + /*#define DMA_X1_READ_ID 0x9fc1 */ + + /* IDMA Debug Register ( for internal use ) */ + +#define DMA_DEBUG_LOW DMA_X0_ADDRESS /* 0x8e01 */ +#define DMA_DEBUG_HIGH DMA_X0_COMMAND_AND_ID /*0x8e41 */ +#define DMA_SPARE 0xA8C + + +/****************************************/ +/* Timer_Counter */ +/****************************************/ + +#define TIMER_COUNTER0 0x850 +#define TIMER_COUNTER1 0x854 +#define TIMER_COUNTER2 0x858 +#define TIMER_COUNTER3 0x85C +#define TIMER_COUNTER_0_3_CONTROL 0x864 +#define TIMER_COUNTER_0_3_INTERRUPT_CAUSE 0x868 +#define TIMER_COUNTER_0_3_INTERRUPT_MASK 0x86c + /*#define TIMER_COUNTER4 0x9501 */ + /*#define TIMER_COUNTER5 0x9541 */ + /*#define TIMER_COUNTER6 0x9581 */ + /*#define TIMER_COUNTER7 0x95C1 */ + /*#define TIMER_COUNTER_4_7_CONTROL 0x9641 */ + /*#define TIMER_COUNTER_4_7_INTERRUPT_CAUSE 0x9681 */ + /*#define TIMER_COUNTER_4_7_INTERRUPT_MASK 0x96c1 */ + +/****************************************/ +/* PCI Slave Address Decoding */ +/****************************************/ +/****************************************/ +/* PCI Slave Address Decoding registers */ +/****************************************/ +#define PCI_0_CS_0_BANK_SIZE PCI_0SCS_0_BANK_SIZE /*0xc081 */ +#define PCI_1_CS_0_BANK_SIZE PCI_1SCS_0_BANK_SIZE /* 0xc881 */ +#define PCI_0_CS_1_BANK_SIZE PCI_0SCS_1_BANK_SIZE /*0xd081 */ +#define PCI_1_CS_1_BANK_SIZE PCI_1SCS_1_BANK_SIZE /* 0xd881 */ +#define PCI_0_CS_2_BANK_SIZE PCI_0SCS_2_BANK_SIZE /*0xc0c1 */ +#define PCI_1_CS_2_BANK_SIZE PCI_1SCS_2_BANK_SIZE /*0xc8c1 */ +#define PCI_0_CS_3_BANK_SIZE PCI_0SCS_3_BANK_SIZE /*0xd0c1 */ +#define PCI_1_CS_3_BANK_SIZE PCI_1SCS_3_BANK_SIZE /*0xd8c1 */ +#define PCI_0_DEVCS_0_BANK_SIZE PCI_0CS_0_BANK_SIZE /*0xc101 */ +#define PCI_1_DEVCS_0_BANK_SIZE PCI_1CS_0_BANK_SIZE /*0xc901 */ +#define PCI_0_DEVCS_1_BANK_SIZE PCI_0CS_1_BANK_SIZE /*0xd101 */ +#define PCI_1_DEVCS_1_BANK_SIZE PCI_1CS_1_BANK_SIZE /* 0xd901 */ +#define PCI_0_DEVCS_2_BANK_SIZE PCI_0CS_2_BANK_SIZE /* 0xd181 */ +#define PCI_1_DEVCS_2_BANK_SIZE PCI_1CS_2_BANK_SIZE /*0xd981 */ +#define PCI_0_DEVCS_3_BANK_SIZE PCI_0CS_3_BANK_SIZE /* 0xc141 */ +#define PCI_1_DEVCS_3_BANK_SIZE PCI_1CS_3_BANK_SIZE /*0xc941 */ +#define PCI_0_DEVCS_BOOT_BANK_SIZE PCI_0CS_BOOT_BANK_SIZE /*0xd141 */ +#define PCI_1_DEVCS_BOOT_BANK_SIZE PCI_1CS_BOOT_BANK_SIZE /* 0xd941 */ +#define PCI_0_P2P_MEM0_BAR_SIZE PCI_0P2P_MEM0_BAR_SIZE /*0xd1c1 */ +#define PCI_1_P2P_MEM0_BAR_SIZE PCI_1P2P_MEM0_BAR_SIZE /*0xd9c1 */ +#define PCI_0_P2P_MEM1_BAR_SIZE PCI_0P2P_MEM1_BAR_SIZE /*0xd201 */ +#define PCI_1_P2P_MEM1_BAR_SIZE PCI_1P2P_MEM1_BAR_SIZE /*0xda01 */ +#define PCI_0_P2P_I_O_BAR_SIZE PCI_0P2P_I_O_BAR_SIZE /*0xd241 */ +#define PCI_1_P2P_I_O_BAR_SIZE PCI_1P2P_I_O_BAR_SIZE /*0xda41 */ +#define PCI_0_CPU_BAR_SIZE PCI_0CPU_BAR_SIZE /*0xd281 */ +#define PCI_1_CPU_BAR_SIZE PCI_1CPU_BAR_SIZE /*0xda81 */ +#define PCI_0_INTERNAL_SRAM_BAR_SIZE PCI_0DAC_SCS_0_BANK_SIZE /*0xe001 */ +#define PCI_1_INTERNAL_SRAM_BAR_SIZE PCI_1DAC_SCS_0_BANK_SIZE /*0xe801 */ +#define PCI_0_EXPANSION_ROM_BAR_SIZE PCI_0EXPANSION_ROM_BAR_SIZE /*0xd2c1 */ +#define PCI_1_EXPANSION_ROM_BAR_SIZE PCI_1EXPANSION_ROM_BAR_SIZE /*0xd9c1 */ +#define PCI_0_BASE_ADDR_REG_ENABLE PCI_0BASE_ADDRESS_REGISTERS_ENABLE /*0xc3c1 */ +#define PCI_1_BASE_ADDR_REG_ENABLE PCI_1BASE_ADDRESS_REGISTERS_ENABLE /*0xcbc1 */ +#define PCI_0_CS_0_BASE_ADDR_REMAP PCI_0SCS_0_BASE_ADDRESS_REMAP /*0xc481 */ +#define PCI_1_CS_0_BASE_ADDR_REMAP PCI_1SCS_0_BASE_ADDRESS_REMAP /*0xcc81 */ +#define PCI_0_CS_1_BASE_ADDR_REMAP PCI_0SCS_1_BASE_ADDRESS_REMAP /*0xd481 */ +#define PCI_1_CS_1_BASE_ADDR_REMAP PCI_1SCS_1_BASE_ADDRESS_REMAP /*0xdc81 */ +#define PCI_0_CS_2_BASE_ADDR_REMAP PCI_0SCS_2_BASE_ADDRESS_REMAP /*0xc4c1 */ +#define PCI_1_CS_2_BASE_ADDR_REMAP PCI_1SCS_2_BASE_ADDRESS_REMAP /*0xccc1 */ +#define PCI_0_CS_3_BASE_ADDR_REMAP PCI_0SCS_3_BASE_ADDRESS_REMAP /*0xd4c1 */ +#define PCI_1_CS_3_BASE_ADDR_REMAP PCI_1SCS_3_BASE_ADDRESS_REMAP /* 0xdcc1 */ +#define PCI_0_CS_0_BASE_HIGH_ADDR_REMAP PCI_0DAC_SCS_0_BASE_ADDRESS_REMAP +#define PCI_1_CS_0_BASE_HIGH_ADDR_REMAP PCI_1DAC_SCS_0_BASE_ADDRESS_REMAP +#define PCI_0_CS_1_BASE_HIGH_ADDR_REMAP PCI_0DAC_SCS_1_BASE_ADDRESS_REMAP +#define PCI_1_CS_1_BASE_HIGH_ADDR_REMAP PCI_1DAC_SCS_1_BASE_ADDRESS_REMAP +#define PCI_0_CS_2_BASE_HIGH_ADDR_REMAP PCI_0DAC_SCS_2_BASE_ADDRESS_REMAP +#define PCI_1_CS_2_BASE_HIGH_ADDR_REMAP PCI_1DAC_SCS_2_BASE_ADDRESS_REMAP +#define PCI_0_CS_3_BASE_HIGH_ADDR_REMAP PCI_0DAC_SCS_3_BASE_ADDRESS_REMAP +#define PCI_1_CS_3_BASE_HIGH_ADDR_REMAP PCI_1DAC_SCS_3_BASE_ADDRESS_REMAP +#define PCI_0_DEVCS_0_BASE_ADDR_REMAP PCI_0CS_0_BASE_ADDRESS_REMAP /*0xc501 */ +#define PCI_1_DEVCS_0_BASE_ADDR_REMAP PCI_1CS_0_BASE_ADDRESS_REMAP /*0xcd01 */ +#define PCI_0_DEVCS_1_BASE_ADDR_REMAP PCI_0CS_1_BASE_ADDRESS_REMAP /*0xd501 */ +#define PCI_1_DEVCS_1_BASE_ADDR_REMAP PCI_1CS_1_BASE_ADDRESS_REMAP /*0xdd01 */ +#define PCI_0_DEVCS_2_BASE_ADDR_REMAP PCI_0CS_2_BASE_ADDRESS_REMAP /*0xd581 */ +#define PCI_1_DEVCS_2_BASE_ADDR_REMAP PCI_1CS_2_BASE_ADDRESS_REMAP /*0xdd81 */ +#define PCI_0_DEVCS_3_BASE_ADDR_REMAP PCI_0CS_3_BASE_ADDRESS_REMAP /*0xc541 */ +#define PCI_1_DEVCS_3_BASE_ADDR_REMAP PCI_1CS_3_BASE_ADDRESS_REMAP /*0xcd41 */ +#define PCI_0_DEVCS_BOOTCS_BASE_ADDR_REMAP PCI_0CS_BOOTCS_BASE_ADDRESS_REMAP /*0xd541 */ +#define PCI_1_DEVCS_BOOTCS_BASE_ADDR_REMAP PCI_1CS_BOOTCS_BASE_ADDRESS_REMAP /*0xdd41 */ +#define PCI_0_P2P_MEM0_BASE_ADDR_REMAP_LOW PCI_0P2P_MEM0_BASE_ADDRESS_REMAP_LOW /*0xd5c1 */ +#define PCI_1_P2P_MEM0_BASE_ADDR_REMAP_LOW PCI_1P2P_MEM0_BASE_ADDRESS_REMAP_LOW /*0xddc1 */ +#define PCI_0_P2P_MEM0_BASE_ADDR_REMAP_HIGH PCI_0P2P_MEM0_BASE_ADDRESS_REMAP_HIGH /*0xd601 */ +#define PCI_1_P2P_MEM0_BASE_ADDR_REMAP_HIGH PCI_1P2P_MEM0_BASE_ADDRESS_REMAP_HIGH /*0xde01 */ +#define PCI_0_P2P_MEM1_BASE_ADDR_REMAP_LOW PCI_0P2P_MEM1_BASE_ADDRESS_REMAP_LOW /*0xd641 */ +#define PCI_1_P2P_MEM1_BASE_ADDR_REMAP_LOW PCI_1P2P_MEM1_BASE_ADDRESS_REMAP_LOW /*0xde41 */ +#define PCI_0_P2P_MEM1_BASE_ADDR_REMAP_HIGH PCI_0P2P_MEM1_BASE_ADDRESS_REMAP_HIGH /*0xd681 */ +#define PCI_1_P2P_MEM1_BASE_ADDR_REMAP_HIGH PCI_1P2P_MEM1_BASE_ADDRESS_REMAP_HIGH /*0xde81 */ +#define PCI_0_P2P_I_O_BASE_ADDR_REMAP PCI_0P2P_I_O_BASE_ADDRESS_REMAP /*0xd6c1 */ +#define PCI_1_P2P_I_O_BASE_ADDR_REMAP PCI_1P2P_I_O_BASE_ADDRESS_REMAP /*0xdec 1 */ +#define PCI_0_CPU_BASE_ADDR_REMAP_LOW PCI_0CPU_BASE_ADDRESS_REMAP /*0xd701 */ +#define PCI_1_CPU_BASE_ADDR_REMAP_LOW PCI_1CPU_BASE_ADDRESS_REMAP /*0xdf01 */ +#define PCI_0_CPU_BASE_ADDR_REMAP_HIGH 0xd74 +#define PCI_1_CPU_BASE_ADDR_REMAP_HIGH 0xdf4 +#define PCI_0_INTEGRATED_SRAM_BASE_ADDR_REMAP PCI_0DAC_SCS_0_BASE_ADDRESS_REMAP /*0xf001 */ +#define PCI_1_INTEGRATED_SRAM_BASE_ADDR_REMAP 0xf80 +#define PCI_0_EXPANSION_ROM_BASE_ADDR_REMAP PCI_0EXPANSION_ROM_BASE_ADDRESS_REMAP /*0xf381 */ +#define PCI_1_EXPANSION_ROM_BASE_ADDR_REMAP PCI_1EXPANSION_ROM_BASE_ADDRESS_REMAP /*0xfb81 */ +#define PCI_0_ADDR_DECODE_CONTROL PCI_0ADDRESS_DECODE_CONTROL /*0xd3c1 */ +#define PCI_1_ADDR_DECODE_CONTROL PCI_1ADDRESS_DECODE_CONTROL /*0xdbc1 */ +#define PCI_0_HEADERS_RETARGET_CONTROL 0xF40 +#define PCI_1_HEADERS_RETARGET_CONTROL 0xFc0 +#define PCI_0_HEADERS_RETARGET_BASE 0xF44 +#define PCI_1_HEADERS_RETARGET_BASE 0xFc4 +#define PCI_0_HEADERS_RETARGET_HIGH 0xF48 +#define PCI_1_HEADERS_RETARGET_HIGH 0xFc8 + +#define PCI_0SCS_0_BANK_SIZE 0xc08 +#define PCI_1SCS_0_BANK_SIZE 0xc88 +#define PCI_0SCS_1_BANK_SIZE 0xd08 +#define PCI_1SCS_1_BANK_SIZE 0xd88 +#define PCI_0SCS_2_BANK_SIZE 0xc0c +#define PCI_1SCS_2_BANK_SIZE 0xc8c +#define PCI_0SCS_3_BANK_SIZE 0xd0c +#define PCI_1SCS_3_BANK_SIZE 0xd8c +#define PCI_0CS_0_BANK_SIZE 0xc10 +#define PCI_1CS_0_BANK_SIZE 0xc90 +#define PCI_0CS_1_BANK_SIZE 0xd10 +#define PCI_1CS_1_BANK_SIZE 0xd90 +#define PCI_0CS_2_BANK_SIZE 0xd18 +#define PCI_1CS_2_BANK_SIZE 0xd98 +#define PCI_0CS_3_BANK_SIZE 0xc14 +#define PCI_1CS_3_BANK_SIZE 0xc94 +#define PCI_0CS_BOOT_BANK_SIZE 0xd14 +#define PCI_1CS_BOOT_BANK_SIZE 0xd94 +#define PCI_0P2P_MEM0_BAR_SIZE 0xd1c +#define PCI_1P2P_MEM0_BAR_SIZE 0xd9c +#define PCI_0P2P_MEM1_BAR_SIZE 0xd20 +#define PCI_1P2P_MEM1_BAR_SIZE 0xda0 +#define PCI_0P2P_I_O_BAR_SIZE 0xd24 +#define PCI_1P2P_I_O_BAR_SIZE 0xda4 +#define PCI_0CPU_BAR_SIZE 0xd28 +#define PCI_1CPU_BAR_SIZE 0xda8 +#define PCI_0DAC_SCS_0_BANK_SIZE 0xe00 +#define PCI_1DAC_SCS_0_BANK_SIZE 0xe80 +#define PCI_0DAC_SCS_1_BANK_SIZE 0xe04 +#define PCI_1DAC_SCS_1_BANK_SIZE 0xe84 +#define PCI_0DAC_SCS_2_BANK_SIZE 0xe08 +#define PCI_1DAC_SCS_2_BANK_SIZE 0xe88 +#define PCI_0DAC_SCS_3_BANK_SIZE 0xe0c +#define PCI_1DAC_SCS_3_BANK_SIZE 0xe8c +#define PCI_0DAC_CS_0_BANK_SIZE 0xe10 +#define PCI_1DAC_CS_0_BANK_SIZE 0xe90 +#define PCI_0DAC_CS_1_BANK_SIZE 0xe14 +#define PCI_1DAC_CS_1_BANK_SIZE 0xe94 +#define PCI_0DAC_CS_2_BANK_SIZE 0xe18 +#define PCI_1DAC_CS_2_BANK_SIZE 0xe98 +#define PCI_0DAC_CS_3_BANK_SIZE 0xe1c +#define PCI_1DAC_CS_3_BANK_SIZE 0xe9c +#define PCI_0DAC_BOOTCS_BANK_SIZE 0xe20 +#define PCI_1DAC_BOOTCS_BANK_SIZE 0xea0 + +#define PCI_0DAC_P2P_MEM0_BAR_SIZE 0xe24 +#define PCI_1DAC_P2P_MEM0_BAR_SIZE 0xea4 +#define PCI_0DAC_P2P_MEM1_BAR_SIZE 0xe28 +#define PCI_1DAC_P2P_MEM1_BAR_SIZE 0xea8 +#define PCI_0DAC_CPU_BAR_SIZE 0xe2c +#define PCI_1DAC_CPU_BAR_SIZE 0xeac +#define PCI_0EXPANSION_ROM_BAR_SIZE 0xd2c +#define PCI_1EXPANSION_ROM_BAR_SIZE 0xdac +#define PCI_0BASE_ADDRESS_REGISTERS_ENABLE 0xc3c +#define PCI_1BASE_ADDRESS_REGISTERS_ENABLE 0xcbc +#define PCI_0SCS_0_BASE_ADDRESS_REMAP 0xc48 +#define PCI_1SCS_0_BASE_ADDRESS_REMAP 0xcc8 +#define PCI_0SCS_1_BASE_ADDRESS_REMAP 0xd48 +#define PCI_1SCS_1_BASE_ADDRESS_REMAP 0xdc8 +#define PCI_0SCS_2_BASE_ADDRESS_REMAP 0xc4c +#define PCI_1SCS_2_BASE_ADDRESS_REMAP 0xccc +#define PCI_0SCS_3_BASE_ADDRESS_REMAP 0xd4c +#define PCI_1SCS_3_BASE_ADDRESS_REMAP 0xdcc +#define PCI_0CS_0_BASE_ADDRESS_REMAP 0xc50 +#define PCI_1CS_0_BASE_ADDRESS_REMAP 0xcd0 +#define PCI_0CS_1_BASE_ADDRESS_REMAP 0xd50 +#define PCI_1CS_1_BASE_ADDRESS_REMAP 0xdd0 +#define PCI_0CS_2_BASE_ADDRESS_REMAP 0xd58 +#define PCI_1CS_2_BASE_ADDRESS_REMAP 0xdd8 +#define PCI_0CS_3_BASE_ADDRESS_REMAP 0xc54 +#define PCI_1CS_3_BASE_ADDRESS_REMAP 0xcd4 +#define PCI_0CS_BOOTCS_BASE_ADDRESS_REMAP 0xd54 +#define PCI_1CS_BOOTCS_BASE_ADDRESS_REMAP 0xdd4 +#define PCI_0P2P_MEM0_BASE_ADDRESS_REMAP_LOW 0xd5c +#define PCI_1P2P_MEM0_BASE_ADDRESS_REMAP_LOW 0xddc +#define PCI_0P2P_MEM0_BASE_ADDRESS_REMAP_HIGH 0xd60 +#define PCI_1P2P_MEM0_BASE_ADDRESS_REMAP_HIGH 0xde0 +#define PCI_0P2P_MEM1_BASE_ADDRESS_REMAP_LOW 0xd64 +#define PCI_1P2P_MEM1_BASE_ADDRESS_REMAP_LOW 0xde4 +#define PCI_0P2P_MEM1_BASE_ADDRESS_REMAP_HIGH 0xd68 +#define PCI_1P2P_MEM1_BASE_ADDRESS_REMAP_HIGH 0xde8 +#define PCI_0P2P_I_O_BASE_ADDRESS_REMAP 0xd6c +#define PCI_1P2P_I_O_BASE_ADDRESS_REMAP 0xdec +#define PCI_0CPU_BASE_ADDRESS_REMAP 0xd70 +#define PCI_1CPU_BASE_ADDRESS_REMAP 0xdf0 +#define PCI_0DAC_SCS_0_BASE_ADDRESS_REMAP 0xf00 +#define PCI_1DAC_SCS_0_BASE_ADDRESS_REMAP 0xff0 +#define PCI_0DAC_SCS_1_BASE_ADDRESS_REMAP 0xf04 +#define PCI_1DAC_SCS_1_BASE_ADDRESS_REMAP 0xf84 +#define PCI_0DAC_SCS_2_BASE_ADDRESS_REMAP 0xf08 +#define PCI_1DAC_SCS_2_BASE_ADDRESS_REMAP 0xf88 +#define PCI_0DAC_SCS_3_BASE_ADDRESS_REMAP 0xf0c +#define PCI_1DAC_SCS_3_BASE_ADDRESS_REMAP 0xf8c +#define PCI_0DAC_CS_0_BASE_ADDRESS_REMAP 0xf10 +#define PCI_1DAC_CS_0_BASE_ADDRESS_REMAP 0xf90 +#define PCI_0DAC_CS_1_BASE_ADDRESS_REMAP 0xf14 +#define PCI_1DAC_CS_1_BASE_ADDRESS_REMAP 0xf94 +#define PCI_0DAC_CS_2_BASE_ADDRESS_REMAP 0xf18 +#define PCI_1DAC_CS_2_BASE_ADDRESS_REMAP 0xf98 +#define PCI_0DAC_CS_3_BASE_ADDRESS_REMAP 0xf1c +#define PCI_1DAC_CS_3_BASE_ADDRESS_REMAP 0xf9c +#define PCI_0DAC_BOOTCS_BASE_ADDRESS_REMAP 0xf20 +#define PCI_1DAC_BOOTCS_BASE_ADDRESS_REMAP 0xfa0 +#define PCI_0DAC_P2P_MEM0_BASE_ADDRESS_REMAP_LOW 0xf24 +#define PCI_1DAC_P2P_MEM0_BASE_ADDRESS_REMAP_LOW 0xfa4 +#define PCI_0DAC_P2P_MEM0_BASE_ADDRESS_REMAP_HIGH 0xf28 +#define PCI_1DAC_P2P_MEM0_BASE_ADDRESS_REMAP_HIGH 0xfa8 +#define PCI_0DAC_P2P_MEM1_BASE_ADDRESS_REMAP_LOW 0xf2c +#define PCI_1DAC_P2P_MEM1_BASE_ADDRESS_REMAP_LOW 0xfac +#define PCI_0DAC_P2P_MEM1_BASE_ADDRESS_REMAP_HIGH 0xf30 +#define PCI_1DAC_P2P_MEM1_BASE_ADDRESS_REMAP_HIGH 0xfb0 +#define PCI_0DAC_CPU_BASE_ADDRESS_REMAP 0xf34 +#define PCI_1DAC_CPU_BASE_ADDRESS_REMAP 0xfb4 +#define PCI_0EXPANSION_ROM_BASE_ADDRESS_REMAP 0xf38 +#define PCI_1EXPANSION_ROM_BASE_ADDRESS_REMAP 0xfb8 +#define PCI_0ADDRESS_DECODE_CONTROL 0xd3c +#define PCI_1ADDRESS_DECODE_CONTROL 0xdbc + +/****************************************/ +/* PCI Control */ +/****************************************/ + +#define PCI_0COMMAND 0xc00 +#define PCI_1COMMAND 0xc80 +#define PCI_0MODE 0xd00 +#define PCI_1MODE 0xd80 +#define PCI_0TIMEOUT_RETRY 0xc04 +#define PCI_1TIMEOUT_RETRY 0xc84 +#define PCI_0READ_BUFFER_DISCARD_TIMER 0xd04 +#define PCI_1READ_BUFFER_DISCARD_TIMER 0xd84 +#define MSI_0TRIGGER_TIMER 0xc38 +#define MSI_1TRIGGER_TIMER 0xcb8 +#define PCI_0ARBITER_CONTROL 0x1d00 +#define PCI_1ARBITER_CONTROL 0x1d80 +/* changing untill here */ +#define PCI_0CROSS_BAR_CONTROL_LOW 0x1d08 +#define PCI_0CROSS_BAR_CONTROL_HIGH 0x1d0c +#define PCI_0CROSS_BAR_TIMEOUT 0x1d04 +#define PCI_0READ_RESPONSE_CROSS_BAR_CONTROL_LOW 0x1d18 +#define PCI_0READ_RESPONSE_CROSS_BAR_CONTROL_HIGH 0x1d1c +#define PCI_0SYNC_BARRIER_VIRTUAL_REGISTER 0x1d10 +#define PCI_0P2P_CONFIGURATION 0x1d14 +#define PCI_0ACCESS_CONTROL_BASE_0_LOW 0x1e00 +#define PCI_0ACCESS_CONTROL_BASE_0_HIGH 0x1e04 +#define PCI_0ACCESS_CONTROL_TOP_0 0x1e08 +#define PCI_0ACCESS_CONTROL_BASE_1_LOW 0x1e10 +#define PCI_0ACCESS_CONTROL_BASE_1_HIGH 0x1e14 +#define PCI_0ACCESS_CONTROL_TOP_1 0x1e18 +#define PCI_0ACCESS_CONTROL_BASE_2_LOW 0x1e20 +#define PCI_0ACCESS_CONTROL_BASE_2_HIGH 0x1e24 +#define PCI_0ACCESS_CONTROL_TOP_2 0x1e28 +#define PCI_0ACCESS_CONTROL_BASE_3_LOW 0x1e30 +#define PCI_0ACCESS_CONTROL_BASE_3_HIGH 0x1e34 +#define PCI_0ACCESS_CONTROL_TOP_3 0x1e38 +#define PCI_0ACCESS_CONTROL_BASE_4_LOW 0x1e40 +#define PCI_0ACCESS_CONTROL_BASE_4_HIGH 0x1e44 +#define PCI_0ACCESS_CONTROL_TOP_4 0x1e48 +#define PCI_0ACCESS_CONTROL_BASE_5_LOW 0x1e50 +#define PCI_0ACCESS_CONTROL_BASE_5_HIGH 0x1e54 +#define PCI_0ACCESS_CONTROL_TOP_5 0x1e58 +#define PCI_0ACCESS_CONTROL_BASE_6_LOW 0x1e60 +#define PCI_0ACCESS_CONTROL_BASE_6_HIGH 0x1e64 +#define PCI_0ACCESS_CONTROL_TOP_6 0x1e68 +#define PCI_0ACCESS_CONTROL_BASE_7_LOW 0x1e70 +#define PCI_0ACCESS_CONTROL_BASE_7_HIGH 0x1e74 +#define PCI_0ACCESS_CONTROL_TOP_7 0x1e78 +#define PCI_1CROSS_BAR_CONTROL_LOW 0x1d88 +#define PCI_1CROSS_BAR_CONTROL_HIGH 0x1d8c +#define PCI_1CROSS_BAR_TIMEOUT 0x1d84 +#define PCI_1READ_RESPONSE_CROSS_BAR_CONTROL_LOW 0x1d98 +#define PCI_1READ_RESPONSE_CROSS_BAR_CONTROL_HIGH 0x1d9c +#define PCI_1SYNC_BARRIER_VIRTUAL_REGISTER 0x1d90 +#define PCI_1P2P_CONFIGURATION 0x1d94 +#define PCI_1ACCESS_CONTROL_BASE_0_LOW 0x1e80 +#define PCI_1ACCESS_CONTROL_BASE_0_HIGH 0x1e84 +#define PCI_1ACCESS_CONTROL_TOP_0 0x1e88 +#define PCI_1ACCESS_CONTROL_BASE_1_LOW 0x1e90 +#define PCI_1ACCESS_CONTROL_BASE_1_HIGH 0x1e94 +#define PCI_1ACCESS_CONTROL_TOP_1 0x1e98 +#define PCI_1ACCESS_CONTROL_BASE_2_LOW 0x1ea0 +#define PCI_1ACCESS_CONTROL_BASE_2_HIGH 0x1ea4 +#define PCI_1ACCESS_CONTROL_TOP_2 0x1ea8 +#define PCI_1ACCESS_CONTROL_BASE_3_LOW 0x1eb0 +#define PCI_1ACCESS_CONTROL_BASE_3_HIGH 0x1eb4 +#define PCI_1ACCESS_CONTROL_TOP_3 0x1eb8 +#define PCI_1ACCESS_CONTROL_BASE_4_LOW 0x1ec0 +#define PCI_1ACCESS_CONTROL_BASE_4_HIGH 0x1ec4 +#define PCI_1ACCESS_CONTROL_TOP_4 0x1ec8 +#define PCI_1ACCESS_CONTROL_BASE_5_LOW 0x1ed0 +#define PCI_1ACCESS_CONTROL_BASE_5_HIGH 0x1ed4 +#define PCI_1ACCESS_CONTROL_TOP_5 0x1ed8 +#define PCI_1ACCESS_CONTROL_BASE_6_LOW 0x1ee0 +#define PCI_1ACCESS_CONTROL_BASE_6_HIGH 0x1ee4 +#define PCI_1ACCESS_CONTROL_TOP_6 0x1ee8 +#define PCI_1ACCESS_CONTROL_BASE_7_LOW 0x1ef0 +#define PCI_1ACCESS_CONTROL_BASE_7_HIGH 0x1ef4 +#define PCI_1ACCESS_CONTROL_TOP_7 0x1ef8 + +/****************************************/ +/* PCI Snoop Control */ +/****************************************/ + +#define PCI_0SNOOP_CONTROL_BASE_0_LOW 0x1f00 +#define PCI_0SNOOP_CONTROL_BASE_0_HIGH 0x1f04 +#define PCI_0SNOOP_CONTROL_TOP_0 0x1f08 +#define PCI_0SNOOP_CONTROL_BASE_1_0_LOW 0x1f10 +#define PCI_0SNOOP_CONTROL_BASE_1_0_HIGH 0x1f14 +#define PCI_0SNOOP_CONTROL_TOP_1 0x1f18 +#define PCI_0SNOOP_CONTROL_BASE_2_0_LOW 0x1f20 +#define PCI_0SNOOP_CONTROL_BASE_2_0_HIGH 0x1f24 +#define PCI_0SNOOP_CONTROL_TOP_2 0x1f28 +#define PCI_0SNOOP_CONTROL_BASE_3_0_LOW 0x1f30 +#define PCI_0SNOOP_CONTROL_BASE_3_0_HIGH 0x1f34 +#define PCI_0SNOOP_CONTROL_TOP_3 0x1f38 +#define PCI_1SNOOP_CONTROL_BASE_0_LOW 0x1f80 +#define PCI_1SNOOP_CONTROL_BASE_0_HIGH 0x1f84 +#define PCI_1SNOOP_CONTROL_TOP_0 0x1f88 +#define PCI_1SNOOP_CONTROL_BASE_1_0_LOW 0x1f90 +#define PCI_1SNOOP_CONTROL_BASE_1_0_HIGH 0x1f94 +#define PCI_1SNOOP_CONTROL_TOP_1 0x1f98 +#define PCI_1SNOOP_CONTROL_BASE_2_0_LOW 0x1fa0 +#define PCI_1SNOOP_CONTROL_BASE_2_0_HIGH 0x1fa4 +#define PCI_1SNOOP_CONTROL_TOP_2 0x1fa8 +#define PCI_1SNOOP_CONTROL_BASE_3_0_LOW 0x1fb0 +#define PCI_1SNOOP_CONTROL_BASE_3_0_HIGH 0x1fb4 +#define PCI_1SNOOP_CONTROL_TOP_3 0x1fb8 + +/****************************************/ +/* PCI Configuration Address */ +/****************************************/ + +#define PCI_0CONFIGURATION_ADDRESS 0xcf8 +#define PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER 0xcfc +#define PCI_1CONFIGURATION_ADDRESS 0xc78 +#define PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER 0xc7c +#define PCI_0INTERRUPT_ACKNOWLEDGE_VIRTUAL_REGISTER 0xc34 +#define PCI_1INTERRUPT_ACKNOWLEDGE_VIRTUAL_REGISTER 0xcb4 + +/****************************************/ +/* PCI Error Report */ +/****************************************/ + +#define PCI_0SERR_MASK 0xc28 +#define PCI_0ERROR_ADDRESS_LOW 0x1d40 +#define PCI_0ERROR_ADDRESS_HIGH 0x1d44 +#define PCI_0ERROR_DATA_LOW 0x1d48 +#define PCI_0ERROR_DATA_HIGH 0x1d4c +#define PCI_0ERROR_COMMAND 0x1d50 +#define PCI_0ERROR_CAUSE 0x1d58 +#define PCI_0ERROR_MASK 0x1d5c +#define PCI_1SERR_MASK 0xca8 +#define PCI_1ERROR_ADDRESS_LOW 0x1dc0 +#define PCI_1ERROR_ADDRESS_HIGH 0x1dc4 +#define PCI_1ERROR_DATA_LOW 0x1dc8 +#define PCI_1ERROR_DATA_HIGH 0x1dcc +#define PCI_1ERROR_COMMAND 0x1dd0 +#define PCI_1ERROR_CAUSE 0x1dd8 +#define PCI_1ERROR_MASK 0x1ddc + + +/****************************************/ +/* Lslave Debug (for internal use) */ +/****************************************/ + +#define L_SLAVE_X0_ADDRESS 0x1d20 +#define L_SLAVE_X0_COMMAND_AND_ID 0x1d24 +#define L_SLAVE_X1_ADDRESS 0x1d28 +#define L_SLAVE_X1_COMMAND_AND_ID 0x1d2c +#define L_SLAVE_WRITE_DATA_LOW 0x1d30 +#define L_SLAVE_WRITE_DATA_HIGH 0x1d34 +#define L_SLAVE_WRITE_BYTE_ENABLE 0x1d60 +#define L_SLAVE_READ_DATA_LOW 0x1d38 +#define L_SLAVE_READ_DATA_HIGH 0x1d3c +#define L_SLAVE_READ_ID 0x1d64 + +/****************************************/ +/* PCI Configuration Function 0 */ +/****************************************/ + +#define PCI_DEVICE_AND_VENDOR_ID 0x000 +#define PCI_STATUS_AND_COMMAND 0x004 +#define PCI_CLASS_CODE_AND_REVISION_ID 0x008 +#define PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE 0x00C +#define PCI_SCS_0_BASE_ADDRESS 0x010 +#define PCI_SCS_1_BASE_ADDRESS 0x014 +#define PCI_SCS_2_BASE_ADDRESS 0x018 +#define PCI_SCS_3_BASE_ADDRESS 0x01C +#define PCI_INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS 0x020 +#define PCI_INTERNAL_REGISTERS_I_OMAPPED_BASE_ADDRESS 0x024 +#define PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID 0x02C +#define PCI_EXPANSION_ROM_BASE_ADDRESS_REGISTER 0x030 +#define PCI_CAPABILTY_LIST_POINTER 0x034 +#define PCI_INTERRUPT_PIN_AND_LINE 0x03C +#define PCI_POWER_MANAGEMENT_CAPABILITY 0x040 +#define PCI_POWER_MANAGEMENT_STATUS_AND_CONTROL 0x044 +#define PCI_VPD_ADDRESS 0x048 +#define PCI_VPD_DATA 0x04c +#define PCI_MSI_MESSAGE_CONTROL 0x050 +#define PCI_MSI_MESSAGE_ADDRESS 0x054 +#define PCI_MSI_MESSAGE_UPPER_ADDRESS 0x058 +#define PCI_MSI_MESSAGE_DATA 0x05c +#define PCI_COMPACT_PCI_HOT_SWAP_CAPABILITY 0x058 + +/****************************************/ +/* PCI Configuration Function 1 */ +/****************************************/ + +#define PCI_CS_0_BASE_ADDRESS 0x110 +#define PCI_CS_1_BASE_ADDRESS 0x114 +#define PCI_CS_2_BASE_ADDRESS 0x118 +#define PCI_CS_3_BASE_ADDRESS 0x11c +#define PCI_BOOTCS_BASE_ADDRESS 0x120 + +/****************************************/ +/* PCI Configuration Function 2 */ +/****************************************/ + +#define PCI_P2P_MEM0_BASE_ADDRESS 0x210 + /*#define PCI_P2P_MEM1_BASE_ADDRESS 0x2141 */ +#define PCI_P2P_I_O_BASE_ADDRESS 0x218 + /*#define PCI_CPU_BASE_ADDRESS 0x21c1 */ + +/****************************************/ +/* PCI Configuration Function 4 */ +/****************************************/ + +#define PCI_DAC_SCS_0_BASE_ADDRESS_LOW 0x410 +#define PCI_DAC_SCS_0_BASE_ADDRESS_HIGH 0x414 +#define PCI_DAC_SCS_1_BASE_ADDRESS_LOW 0x418 +#define PCI_DAC_SCS_1_BASE_ADDRESS_HIGH 0x41c +#define PCI_DAC_P2P_MEM0_BASE_ADDRESS_LOW 0x420 +#define PCI_DAC_P2P_MEM0_BASE_ADDRESS_HIGH 0x424 + + +/****************************************/ +/* PCI Configuration Function 5 */ +/****************************************/ + +#define PCI_DAC_SCS_2_BASE_ADDRESS_LOW 0x510 +#define PCI_DAC_SCS_2_BASE_ADDRESS_HIGH 0x514 +#define PCI_DAC_SCS_3_BASE_ADDRESS_LOW 0x518 +#define PCI_DAC_SCS_3_BASE_ADDRESS_HIGH 0x51c +#define PCI_DAC_P2P_MEM1_BASE_ADDRESS_LOW 0x520 +#define PCI_DAC_P2P_MEM1_BASE_ADDRESS_HIGH 0x524 + + +/****************************************/ +/* PCI Configuration Function 6 */ +/****************************************/ + +#define PCI_DAC_CS_0_BASE_ADDRESS_LOW 0x610 +#define PCI_DAC_CS_0_BASE_ADDRESS_HIGH 0x614 +#define PCI_DAC_CS_1_BASE_ADDRESS_LOW 0x618 +#define PCI_DAC_CS_1_BASE_ADDRESS_HIGH 0x61c +#define PCI_DAC_CS_2_BASE_ADDRESS_LOW 0x620 +#define PCI_DAC_CS_2_BASE_ADDRESS_HIGH 0x624 + +/****************************************/ +/* PCI Configuration Function 7 */ +/****************************************/ + +#define PCI_DAC_CS_3_BASE_ADDRESS_LOW 0x710 +#define PCI_DAC_CS_3_BASE_ADDRESS_HIGH 0x714 +#define PCI_DAC_BOOTCS_BASE_ADDRESS_LOW 0x718 +#define PCI_DAC_BOOTCS_BASE_ADDRESS_HIGH 0x71c +#define PCI_DAC_CPU_BASE_ADDRESS_LOW 0x720 +#define PCI_DAC_CPU_BASE_ADDRESS_HIGH 0x724 + +/****************************** MV64360 and MV64460 PCI ***************************/ +/***********************************/ +/* PCI Control Register Map */ +/***********************************/ + +#define PCI_0_DLL_STATUS_AND_COMMAND 0x1d20 +#define PCI_1_DLL_STATUS_AND_COMMAND 0x1da0 +#define PCI_0_MPP_PADS_DRIVE_CONTROL 0x1d1C +#define PCI_1_MPP_PADS_DRIVE_CONTROL 0x1d9C +#define PCI_0_COMMAND 0xc00 +#define PCI_1_COMMAND 0xc80 +#define PCI_0_MODE 0xd00 +#define PCI_1_MODE 0xd80 +#define PCI_0_RETRY 0xc04 +#define PCI_1_RETRY 0xc84 +#define PCI_0_READ_BUFFER_DISCARD_TIMER 0xd04 +#define PCI_1_READ_BUFFER_DISCARD_TIMER 0xd84 +#define PCI_0_MSI_TRIGGER_TIMER 0xc38 +#define PCI_1_MSI_TRIGGER_TIMER 0xcb8 +#define PCI_0_ARBITER_CONTROL 0x1d00 +#define PCI_1_ARBITER_CONTROL 0x1d80 +#define PCI_0_CROSS_BAR_CONTROL_LOW 0x1d08 +#define PCI_1_CROSS_BAR_CONTROL_LOW 0x1d88 +#define PCI_0_CROSS_BAR_CONTROL_HIGH 0x1d0c +#define PCI_1_CROSS_BAR_CONTROL_HIGH 0x1d8c +#define PCI_0_CROSS_BAR_TIMEOUT 0x1d04 +#define PCI_1_CROSS_BAR_TIMEOUT 0x1d84 +#define PCI_0_SYNC_BARRIER_TRIGGER_REG 0x1D18 +#define PCI_1_SYNC_BARRIER_TRIGGER_REG 0x1D98 +#define PCI_0_SYNC_BARRIER_VIRTUAL_REG 0x1d10 +#define PCI_1_SYNC_BARRIER_VIRTUAL_REG 0x1d90 +#define PCI_0_P2P_CONFIG 0x1d14 +#define PCI_1_P2P_CONFIG 0x1d94 + +#define PCI_0_ACCESS_CONTROL_BASE_0_LOW 0x1e00 +#define PCI_0_ACCESS_CONTROL_BASE_0_HIGH 0x1e04 +#define PCI_0_ACCESS_CONTROL_SIZE_0 0x1e08 +#define PCI_0_ACCESS_CONTROL_BASE_1_LOW 0x1e10 +#define PCI_0_ACCESS_CONTROL_BASE_1_HIGH 0x1e14 +#define PCI_0_ACCESS_CONTROL_SIZE_1 0x1e18 +#define PCI_0_ACCESS_CONTROL_BASE_2_LOW 0x1e20 +#define PCI_0_ACCESS_CONTROL_BASE_2_HIGH 0x1e24 +#define PCI_0_ACCESS_CONTROL_SIZE_2 0x1e28 +#define PCI_0_ACCESS_CONTROL_BASE_3_LOW 0x1e30 +#define PCI_0_ACCESS_CONTROL_BASE_3_HIGH 0x1e34 +#define PCI_0_ACCESS_CONTROL_SIZE_3 0x1e38 +#define PCI_0_ACCESS_CONTROL_BASE_4_LOW 0x1e40 +#define PCI_0_ACCESS_CONTROL_BASE_4_HIGH 0x1e44 +#define PCI_0_ACCESS_CONTROL_SIZE_4 0x1e48 +#define PCI_0_ACCESS_CONTROL_BASE_5_LOW 0x1e50 +#define PCI_0_ACCESS_CONTROL_BASE_5_HIGH 0x1e54 +#define PCI_0_ACCESS_CONTROL_SIZE_5 0x1e58 + +#define PCI_1_ACCESS_CONTROL_BASE_0_LOW 0x1e80 +#define PCI_1_ACCESS_CONTROL_BASE_0_HIGH 0x1e84 +#define PCI_1_ACCESS_CONTROL_SIZE_0 0x1e88 +#define PCI_1_ACCESS_CONTROL_BASE_1_LOW 0x1e90 +#define PCI_1_ACCESS_CONTROL_BASE_1_HIGH 0x1e94 +#define PCI_1_ACCESS_CONTROL_SIZE_1 0x1e98 +#define PCI_1_ACCESS_CONTROL_BASE_2_LOW 0x1ea0 +#define PCI_1_ACCESS_CONTROL_BASE_2_HIGH 0x1ea4 +#define PCI_1_ACCESS_CONTROL_SIZE_2 0x1ea8 +#define PCI_1_ACCESS_CONTROL_BASE_3_LOW 0x1eb0 +#define PCI_1_ACCESS_CONTROL_BASE_3_HIGH 0x1eb4 +#define PCI_1_ACCESS_CONTROL_SIZE_3 0x1eb8 +#define PCI_1_ACCESS_CONTROL_BASE_4_LOW 0x1ec0 +#define PCI_1_ACCESS_CONTROL_BASE_4_HIGH 0x1ec4 +#define PCI_1_ACCESS_CONTROL_SIZE_4 0x1ec8 +#define PCI_1_ACCESS_CONTROL_BASE_5_LOW 0x1ed0 +#define PCI_1_ACCESS_CONTROL_BASE_5_HIGH 0x1ed4 +#define PCI_1_ACCESS_CONTROL_SIZE_5 0x1ed8 + +/****************************************/ +/* PCI Configuration Access Registers */ +/****************************************/ + +#define PCI_0_CONFIG_ADDR 0xcf8 +#define PCI_0_CONFIG_DATA_VIRTUAL_REG 0xcfc +#define PCI_1_CONFIG_ADDR 0xc78 +#define PCI_1_CONFIG_DATA_VIRTUAL_REG 0xc7c +#define PCI_0_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG 0xc34 +#define PCI_1_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG 0xcb4 + +/****************************************/ +/* PCI Error Report Registers */ +/****************************************/ + +#define PCI_0_SERR_MASK 0xc28 +#define PCI_1_SERR_MASK 0xca8 +#define PCI_0_ERROR_ADDR_LOW 0x1d40 +#define PCI_1_ERROR_ADDR_LOW 0x1dc0 +#define PCI_0_ERROR_ADDR_HIGH 0x1d44 +#define PCI_1_ERROR_ADDR_HIGH 0x1dc4 +#define PCI_0_ERROR_ATTRIBUTE 0x1d48 +#define PCI_1_ERROR_ATTRIBUTE 0x1dc8 +#define PCI_0_ERROR_COMMAND 0x1d50 +#define PCI_1_ERROR_COMMAND 0x1dd0 +#define PCI_0_ERROR_CAUSE 0x1d58 +#define PCI_1_ERROR_CAUSE 0x1dd8 +#define PCI_0_ERROR_MASK 0x1d5c +#define PCI_1_ERROR_MASK 0x1ddc + +/****************************************/ +/* PCI Debug Registers */ +/****************************************/ + +#define PCI_0_MMASK 0X1D24 +#define PCI_1_MMASK 0X1DA4 + +/*********************************************/ +/* PCI Configuration, Function 0, Registers */ +/*********************************************/ + +#define PCI_DEVICE_AND_VENDOR_ID 0x000 +#define PCI_STATUS_AND_COMMAND 0x004 +#define PCI_CLASS_CODE_AND_REVISION_ID 0x008 +#define PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE 0x00C + +#define PCI_SCS_0_BASE_ADDR_LOW 0x010 +#define PCI_SCS_0_BASE_ADDR_HIGH 0x014 +#define PCI_SCS_1_BASE_ADDR_LOW 0x018 +#define PCI_SCS_1_BASE_ADDR_HIGH 0x01C +#define PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_LOW 0x020 +#define PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_HIGH 0x024 + /*#define PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID 0x02c1 */ +#define PCI_EXPANSION_ROM_BASE_ADDR_REG 0x030 +#define PCI_CAPABILTY_LIST_POINTER 0x034 +#define PCI_INTERRUPT_PIN_AND_LINE 0x03C + /* capability list */ +#define PCI_POWER_MANAGEMENT_CAPABILITY 0x040 +#define PCI_POWER_MANAGEMENT_STATUS_AND_CONTROL 0x044 +#define PCI_VPD_ADDR 0x048 +#define PCI_VPD_DATA 0x04c +#define PCI_MSI_MESSAGE_CONTROL 0x050 +#define PCI_MSI_MESSAGE_ADDR 0x054 +#define PCI_MSI_MESSAGE_UPPER_ADDR 0x058 +#define PCI_MSI_MESSAGE_DATA 0x05c +#define PCI_X_COMMAND 0x060 +#define PCI_X_STATUS 0x064 +#define PCI_COMPACT_PCI_HOT_SWAP 0x068 + +/***********************************************/ +/* PCI Configuration, Function 1, Registers */ +/***********************************************/ + +#define PCI_SCS_2_BASE_ADDR_LOW 0x110 +#define PCI_SCS_2_BASE_ADDR_HIGH 0x114 +#define PCI_SCS_3_BASE_ADDR_LOW 0x118 +#define PCI_SCS_3_BASE_ADDR_HIGH 0x11c +#define PCI_INTERNAL_SRAM_BASE_ADDR_LOW 0x120 +#define PCI_INTERNAL_SRAM_BASE_ADDR_HIGH 0x124 + +/***********************************************/ +/* PCI Configuration, Function 2, Registers */ +/***********************************************/ + +#define PCI_DEVCS_0_BASE_ADDR_LOW 0x210 +#define PCI_DEVCS_0_BASE_ADDR_HIGH 0x214 +#define PCI_DEVCS_1_BASE_ADDR_LOW 0x218 +#define PCI_DEVCS_1_BASE_ADDR_HIGH 0x21c +#define PCI_DEVCS_2_BASE_ADDR_LOW 0x220 +#define PCI_DEVCS_2_BASE_ADDR_HIGH 0x224 + +/***********************************************/ +/* PCI Configuration, Function 3, Registers */ +/***********************************************/ + +#define PCI_DEVCS_3_BASE_ADDR_LOW 0x310 +#define PCI_DEVCS_3_BASE_ADDR_HIGH 0x314 +#define PCI_BOOT_CS_BASE_ADDR_LOW 0x318 +#define PCI_BOOT_CS_BASE_ADDR_HIGH 0x31c +#define PCI_CPU_BASE_ADDR_LOW 0x220 +#define PCI_CPU_BASE_ADDR_HIGH 0x224 + +/***********************************************/ +/* PCI Configuration, Function 4, Registers */ +/***********************************************/ + +#define PCI_P2P_MEM0_BASE_ADDR_LOW 0x410 +#define PCI_P2P_MEM0_BASE_ADDR_HIGH 0x414 +#define PCI_P2P_MEM1_BASE_ADDR_LOW 0x418 +#define PCI_P2P_MEM1_BASE_ADDR_HIGH 0x41c +#define PCI_P2P_I_O_BASE_ADDR 0x420 +#define PCI_INTERNAL_REGS_I_O_MAPPED_BASE_ADDR 0x424 + +/****************************** MV64360 and MV64460 PCI End ***************************/ +/****************************************/ +/* I20 Support registers */ +/****************************************/ + +#define INBOUND_MESSAGE_REGISTER0_PCI_SIDE 0x010 +#define INBOUND_MESSAGE_REGISTER1_PCI_SIDE 0x014 +#define OUTBOUND_MESSAGE_REGISTER0_PCI_SIDE 0x018 +#define OUTBOUND_MESSAGE_REGISTER1_PCI_SIDE 0x01C +#define INBOUND_DOORBELL_REGISTER_PCI_SIDE 0x020 +#define INBOUND_INTERRUPT_CAUSE_REGISTER_PCI_SIDE 0x024 +#define INBOUND_INTERRUPT_MASK_REGISTER_PCI_SIDE 0x028 +#define OUTBOUND_DOORBELL_REGISTER_PCI_SIDE 0x02C +#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_PCI_SIDE 0x030 +#define OUTBOUND_INTERRUPT_MASK_REGISTER_PCI_SIDE 0x034 +#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI_SIDE 0x040 +#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI_SIDE 0x044 +#define QUEUE_CONTROL_REGISTER_PCI_SIDE 0x050 +#define QUEUE_BASE_ADDRESS_REGISTER_PCI_SIDE 0x054 +#define INBOUND_FREE_HEAD_POINTER_REGISTER_PCI_SIDE 0x060 +#define INBOUND_FREE_TAIL_POINTER_REGISTER_PCI_SIDE 0x064 +#define INBOUND_POST_HEAD_POINTER_REGISTER_PCI_SIDE 0x068 +#define INBOUND_POST_TAIL_POINTER_REGISTER_PCI_SIDE 0x06C +#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_PCI_SIDE 0x070 +#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_PCI_SIDE 0x074 +#define OUTBOUND_POST_HEAD_POINTER_REGISTER_PCI_SIDE 0x078 +#define OUTBOUND_POST_TAIL_POINTER_REGISTER_PCI_SIDE 0x07C + +#define INBOUND_MESSAGE_REGISTER0_CPU_SIDE 0x1C10 +#define INBOUND_MESSAGE_REGISTER1_CPU_SIDE 0x1C14 +#define OUTBOUND_MESSAGE_REGISTER0_CPU_SIDE 0x1C18 +#define OUTBOUND_MESSAGE_REGISTER1_CPU_SIDE 0x1C1C +#define INBOUND_DOORBELL_REGISTER_CPU_SIDE 0x1C20 +#define INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE 0x1C24 +#define INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE 0x1C28 +#define OUTBOUND_DOORBELL_REGISTER_CPU_SIDE 0x1C2C +#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE 0x1C30 +#define OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE 0x1C34 +#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU_SIDE 0x1C40 +#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU_SIDE 0x1C44 +#define QUEUE_CONTROL_REGISTER_CPU_SIDE 0x1C50 +#define QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE 0x1C54 +#define INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE 0x1C60 +#define INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE 0x1C64 +#define INBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE 0x1C68 +#define INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE 0x1C6C +#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE 0x1C70 +#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE 0x1C74 +#define OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE 0x1C78 +#define OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE 0x1C7C + + +/****************************************/ +/* Messaging Unit Registers (I20) */ +/****************************************/ + +#define I2O_INBOUND_MESSAGE_REG0_PCI_0_SIDE 0x010 +#define I2O_INBOUND_MESSAGE_REG1_PCI_0_SIDE 0x014 +#define I2O_OUTBOUND_MESSAGE_REG0_PCI_0_SIDE 0x018 +#define I2O_OUTBOUND_MESSAGE_REG1_PCI_0_SIDE 0x01C +#define I2O_INBOUND_DOORBELL_REG_PCI_0_SIDE 0x020 +#define I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE 0x024 +#define I2O_INBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE 0x028 +#define I2O_OUTBOUND_DOORBELL_REG_PCI_0_SIDE 0x02C +#define I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE 0x030 +#define I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE 0x034 +#define I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE 0x040 +#define I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE 0x044 +#define I2O_QUEUE_CONTROL_REG_PCI_0_SIDE 0x050 +#define I2O_QUEUE_BASE_ADDR_REG_PCI_0_SIDE 0x054 +#define I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE 0x060 +#define I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE 0x064 +#define I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE 0x068 +#define I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE 0x06C +#define I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE 0x070 +#define I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE 0x074 +#define I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE 0x0F8 +#define I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE 0x0FC + +#define I2O_INBOUND_MESSAGE_REG0_PCI_1_SIDE 0x090 +#define I2O_INBOUND_MESSAGE_REG1_PCI_1_SIDE 0x094 +#define I2O_OUTBOUND_MESSAGE_REG0_PCI_1_SIDE 0x098 +#define I2O_OUTBOUND_MESSAGE_REG1_PCI_1_SIDE 0x09C +#define I2O_INBOUND_DOORBELL_REG_PCI_1_SIDE 0x0A0 +#define I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE 0x0A4 +#define I2O_INBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE 0x0A8 +#define I2O_OUTBOUND_DOORBELL_REG_PCI_1_SIDE 0x0AC +#define I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE 0x0B0 +#define I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE 0x0B4 +#define I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE 0x0C0 +#define I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE 0x0C4 +#define I2O_QUEUE_CONTROL_REG_PCI_1_SIDE 0x0D0 +#define I2O_QUEUE_BASE_ADDR_REG_PCI_1_SIDE 0x0D4 +#define I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE 0x0E0 +#define I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE 0x0E4 +#define I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE 0x0E8 +#define I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE 0x0EC +#define I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE 0x0F0 +#define I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE 0x0F4 +#define I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE 0x078 +#define I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE 0x07C + +#define I2O_INBOUND_MESSAGE_REG0_CPU0_SIDE 0x1C10 +#define I2O_INBOUND_MESSAGE_REG1_CPU0_SIDE 0x1C14 +#define I2O_OUTBOUND_MESSAGE_REG0_CPU0_SIDE 0x1C18 +#define I2O_OUTBOUND_MESSAGE_REG1_CPU0_SIDE 0x1C1C +#define I2O_INBOUND_DOORBELL_REG_CPU0_SIDE 0x1C20 +#define I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE 0x1C24 +#define I2O_INBOUND_INTERRUPT_MASK_REG_CPU0_SIDE 0x1C28 +#define I2O_OUTBOUND_DOORBELL_REG_CPU0_SIDE 0x1C2C +#define I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE 0x1C30 +#define I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU0_SIDE 0x1C34 +#define I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE 0x1C40 +#define I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE 0x1C44 +#define I2O_QUEUE_CONTROL_REG_CPU0_SIDE 0x1C50 +#define I2O_QUEUE_BASE_ADDR_REG_CPU0_SIDE 0x1C54 +#define I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE 0x1C60 +#define I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE 0x1C64 +#define I2O_INBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE 0x1C68 +#define I2O_INBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE 0x1C6C +#define I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE 0x1C70 +#define I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE 0x1C74 +#define I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE 0x1CF8 +#define I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE 0x1CFC +#define I2O_INBOUND_MESSAGE_REG0_CPU1_SIDE 0x1C90 +#define I2O_INBOUND_MESSAGE_REG1_CPU1_SIDE 0x1C94 +#define I2O_OUTBOUND_MESSAGE_REG0_CPU1_SIDE 0x1C98 +#define I2O_OUTBOUND_MESSAGE_REG1_CPU1_SIDE 0x1C9C +#define I2O_INBOUND_DOORBELL_REG_CPU1_SIDE 0x1CA0 +#define I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE 0x1CA4 +#define I2O_INBOUND_INTERRUPT_MASK_REG_CPU1_SIDE 0x1CA8 +#define I2O_OUTBOUND_DOORBELL_REG_CPU1_SIDE 0x1CAC +#define I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE 0x1CB0 +#define I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU1_SIDE 0x1CB4 +#define I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE 0x1CC0 +#define I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE 0x1CC4 +#define I2O_QUEUE_CONTROL_REG_CPU1_SIDE 0x1CD0 +#define I2O_QUEUE_BASE_ADDR_REG_CPU1_SIDE 0x1CD4 +#define I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE 0x1CE0 +#define I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE 0x1CE4 +#define I2O_INBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE 0x1CE8 +#define I2O_INBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE 0x1CEC +#define I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE 0x1CF0 +#define I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE 0x1CF4 +#define I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE 0x1C78 +#define I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE 0x1C7C + + +/****************************************/ +/* Communication Unit Registers */ +/****************************************/ +/* +#define ETHERNET_0_ADDRESS_CONTROL_LOW 0xf200 +#define ETHERNET_0_ADDRESS_CONTROL_HIGH 0xf204 +#define ETHERNET_0_RECEIVE_BUFFER_PCI_HIGH_ADDRESS 0xf208 +#define ETHERNET_0_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS 0xf20c +#define ETHERNET_0_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf210 +#define ETHERNET_0_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf214 +#define ETHERNET_0_HASH_TABLE_PCI_HIGH_ADDRESS 0xf218 +#define ETHERNET_1_ADDRESS_CONTROL_LOW 0xf220 +#define ETHERNET_1_ADDRESS_CONTROL_HIGH 0xf224 +#define ETHERNET_1_RECEIVE_BUFFER_PCI_HIGH_ADDRESS 0xf228 +#define ETHERNET_1_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS 0xf22c +#define ETHERNET_1_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf230 +#define ETHERNET_1_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf234 +#define ETHERNET_1_HASH_TABLE_PCI_HIGH_ADDRESS 0xf238 +#define ETHERNET_2_ADDRESS_CONTROL_LOW 0xf240 +#define ETHERNET_2_ADDRESS_CONTROL_HIGH 0xf244 +#define ETHERNET_2_RECEIVE_BUFFER_PCI_HIGH_ADDRESS 0xf248 +#define ETHERNET_2_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS 0xf24c +#define ETHERNET_2_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf250 +#define ETHERNET_2_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf254 +#define ETHERNET_2_HASH_TABLE_PCI_HIGH_ADDRESS 0xf258 + */ +#define MPSC_0_ADDRESS_CONTROL_LOW 0xf280 +#define MPSC_0_ADDRESS_CONTROL_HIGH 0xf284 +#define MPSC_0_RECEIVE_BUFFER_PCI_HIGH_ADDRESS 0xf288 +#define MPSC_0_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS 0xf28c +#define MPSC_0_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf290 +#define MPSC_0_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf294 +#define MPSC_1_ADDRESS_CONTROL_LOW 0xf2c0 +#define MPSC_1_ADDRESS_CONTROL_HIGH 0xf2c4 +#define MPSC_1_RECEIVE_BUFFER_PCI_HIGH_ADDRESS 0xf2c8 +#define MPSC_1_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS 0xf2cc +#define MPSC_1_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf2d0 +#define MPSC_1_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf2d4 + /*#define SERIAL_INIT_PCI_HIGH_ADDRESS 0xf3201 */ +#define COMM_UNIT_ARBITER_CONTROL 0xf300 +#define COMM_UNIT_CROSS_BAR_TIMEOUT 0xf304 +#define COMM_UNIT_INTERRUPT_CAUSE 0xf310 +#define COMM_UNIT_INTERRUPT_MASK 0xf314 +#define COMM_UNIT_ERROR_ADDRESS 0xf314 +/****************************************/ +/* Serial Initialization registers */ +/****************************************/ + + /*#define SERIAL_INIT_LAST_DATA 0xf3241 */ + /*#define SERIAL_INIT_STATUS_AND_CONTROL 0xf3281 */ +#define SERIAL_INIT_LAST_DATA 0xf324 +#define SERIAL_INIT_CONTROL 0xf328 +#define SERIAL_INIT_STATUS 0xf32c + + +/****************************************/ +/* Ethernet Unit Registers */ +/****************************************/ + +#define ETH_PHY_ADDR_REG 0x2000 +#define ETH_SMI_REG 0x2004 +#define ETH_UNIT_DEFAULT_ADDR_REG 0x2008 +#define ETH_UNIT_DEFAULTID_REG 0x200c +#define ETH_UNIT_INTERRUPT_CAUSE_REG 0x2080 +#define ETH_UNIT_INTERRUPT_MASK_REG 0x2084 +#define ETH_UNIT_INTERNAL_USE_REG 0x24fc +#define ETH_UNIT_ERROR_ADDR_REG 0x2094 +#define ETH_BAR_0 0x2200 +#define ETH_BAR_1 0x2208 +#define ETH_BAR_2 0x2210 +#define ETH_BAR_3 0x2218 +#define ETH_BAR_4 0x2220 +#define ETH_BAR_5 0x2228 +#define ETH_SIZE_REG_0 0x2204 +#define ETH_SIZE_REG_1 0x220c +#define ETH_SIZE_REG_2 0x2214 +#define ETH_SIZE_REG_3 0x221c +#define ETH_SIZE_REG_4 0x2224 +#define ETH_SIZE_REG_5 0x222c +#define ETH_HEADERS_RETARGET_BASE_REG 0x2230 +#define ETH_HEADERS_RETARGET_CONTROL_REG 0x2234 +#define ETH_HIGH_ADDR_REMAP_REG_0 0x2280 +#define ETH_HIGH_ADDR_REMAP_REG_1 0x2284 +#define ETH_HIGH_ADDR_REMAP_REG_2 0x2288 +#define ETH_HIGH_ADDR_REMAP_REG_3 0x228c +#define ETH_BASE_ADDR_ENABLE_REG 0x2290 +#define ETH_ACCESS_PROTECTION_REG(port) (0x2294 + (port<<2)) +#define ETH_MIB_COUNTERS_BASE(port) (0x3000 + (port<<7)) +#define ETH_PORT_CONFIG_REG(port) (0x2400 + (port<<10)) +#define ETH_PORT_CONFIG_EXTEND_REG(port) (0x2404 + (port<<10)) +#define ETH_MII_SERIAL_PARAMETRS_REG(port) (0x2408 + (port<<10)) +#define ETH_GMII_SERIAL_PARAMETRS_REG(port) (0x240c + (port<<10)) +#define ETH_VLAN_ETHERTYPE_REG(port) (0x2410 + (port<<10)) +#define ETH_MAC_ADDR_LOW(port) (0x2414 + (port<<10)) +#define ETH_MAC_ADDR_HIGH(port) (0x2418 + (port<<10)) +#define ETH_SDMA_CONFIG_REG(port) (0x241c + (port<<10)) +#define ETH_DSCP_0(port) (0x2420 + (port<<10)) +#define ETH_DSCP_1(port) (0x2424 + (port<<10)) +#define ETH_DSCP_2(port) (0x2428 + (port<<10)) +#define ETH_DSCP_3(port) (0x242c + (port<<10)) +#define ETH_DSCP_4(port) (0x2430 + (port<<10)) +#define ETH_DSCP_5(port) (0x2434 + (port<<10)) +#define ETH_DSCP_6(port) (0x2438 + (port<<10)) +#define ETH_PORT_SERIAL_CONTROL_REG(port) (0x243c + (port<<10)) +#define ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port) (0x2440 + (port<<10)) +#define ETH_PORT_STATUS_REG(port) (0x2444 + (port<<10)) +#define ETH_TRANSMIT_QUEUE_COMMAND_REG(port) (0x2448 + (port<<10)) +#define ETH_TX_QUEUE_FIXED_PRIORITY(port) (0x244c + (port<<10)) +#define ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port) (0x2450 + (port<<10)) +#define ETH_MAXIMUM_TRANSMIT_UNIT(port) (0x2458 + (port<<10)) +#define ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port) (0x245c + (port<<10)) +#define ETH_INTERRUPT_CAUSE_REG(port) (0x2460 + (port<<10)) +#define ETH_INTERRUPT_CAUSE_EXTEND_REG(port) (0x2464 + (port<<10)) +#define ETH_INTERRUPT_MASK_REG(port) (0x2468 + (port<<10)) +#define ETH_INTERRUPT_EXTEND_MASK_REG(port) (0x246c + (port<<10)) +#define ETH_RX_FIFO_URGENT_THRESHOLD_REG(port) (0x2470 + (port<<10)) +#define ETH_TX_FIFO_URGENT_THRESHOLD_REG(port) (0x2474 + (port<<10)) +#define ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (0x247c + (port<<10)) +#define ETH_RX_DISCARDED_FRAMES_COUNTER(port) (0x2484 + (port<<10) +#define ETH_PORT_DEBUG_0_REG(port) (0x248c + (port<<10)) +#define ETH_PORT_DEBUG_1_REG(port) (0x2490 + (port<<10)) +#define ETH_PORT_INTERNAL_ADDR_ERROR_REG(port) (0x2494 + (port<<10)) +#define ETH_INTERNAL_USE_REG(port) (0x24fc + (port<<10)) +#define ETH_RECEIVE_QUEUE_COMMAND_REG(port) (0x2680 + (port<<10)) +#define ETH_CURRENT_SERVED_TX_DESC_PTR(port) (0x2684 + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port) (0x260c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port) (0x261c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port) (0x262c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port) (0x263c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port) (0x264c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port) (0x265c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port) (0x266c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port) (0x267c + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port) (0x26c0 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port) (0x26c4 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port) (0x26c8 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port) (0x26cc + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port) (0x26d0 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port) (0x26d4 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port) (0x26d8 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port) (0x26dc + (port<<10)) +#define ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port) (0x2700 + (port<<10)) +#define ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port) (0x2710 + (port<<10)) +#define ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port) (0x2720 + (port<<10)) +#define ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port) (0x2730 + (port<<10)) +#define ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port) (0x2740 + (port<<10)) +#define ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port) (0x2750 + (port<<10)) +#define ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port) (0x2760 + (port<<10)) +#define ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port) (0x2770 + (port<<10)) +#define ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port) (0x2704 + (port<<10)) +#define ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port) (0x2714 + (port<<10)) +#define ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port) (0x2724 + (port<<10)) +#define ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port) (0x2734 + (port<<10)) +#define ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port) (0x2744 + (port<<10)) +#define ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port) (0x2754 + (port<<10)) +#define ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port) (0x2764 + (port<<10)) +#define ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port) (0x2774 + (port<<10)) +#define ETH_TX_QUEUE_0_ARBITER_CONFIG(port) (0x2708 + (port<<10)) +#define ETH_TX_QUEUE_1_ARBITER_CONFIG(port) (0x2718 + (port<<10)) +#define ETH_TX_QUEUE_2_ARBITER_CONFIG(port) (0x2728 + (port<<10)) +#define ETH_TX_QUEUE_3_ARBITER_CONFIG(port) (0x2738 + (port<<10)) +#define ETH_TX_QUEUE_4_ARBITER_CONFIG(port) (0x2748 + (port<<10)) +#define ETH_TX_QUEUE_5_ARBITER_CONFIG(port) (0x2758 + (port<<10)) +#define ETH_TX_QUEUE_6_ARBITER_CONFIG(port) (0x2768 + (port<<10)) +#define ETH_TX_QUEUE_7_ARBITER_CONFIG(port) (0x2778 + (port<<10)) +#define ETH_PORT_TX_TOKEN_BUCKET_COUNT(port) (0x2780 + (port<<10)) +#define ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port) (0x3400 + (port<<10)) +#define ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port) (0x3500 + (port<<10)) +#define ETH_DA_FILTER_UNICAST_TABLE_BASE(port) (0x3600 + (port<<10)) + +/****************************************/ +/* Cunit Debug (for internal use) */ +/****************************************/ + +#define CUNIT_ADDRESS 0xf340 +#define CUNIT_COMMAND_AND_ID 0xf344 +#define CUNIT_WRITE_DATA_LOW 0xf348 +#define CUNIT_WRITE_DATA_HIGH 0xf34c +#define CUNIT_WRITE_BYTE_ENABLE 0xf358 +#define CUNIT_READ_DATA_LOW 0xf350 +#define CUNIT_READ_DATA_HIGH 0xf354 +#define CUNIT_READ_ID 0xf35c + +/****************************************/ +/* Fast Ethernet Unit Registers */ +/****************************************/ + +/****************************************/ +/* Ethernet Unit Registers */ +/****************************************/ + +#define ETH_PHY_ADDR_REG 0x2000 +#define ETH_SMI_REG 0x2004 +#define ETH_UNIT_DEFAULT_ADDR_REG 0x2008 +#define ETH_UNIT_DEFAULTID_REG 0x200c +#define ETH_UNIT_INTERRUPT_CAUSE_REG 0x2080 +#define ETH_UNIT_INTERRUPT_MASK_REG 0x2084 +#define ETH_UNIT_INTERNAL_USE_REG 0x24fc +#define ETH_UNIT_ERROR_ADDR_REG 0x2094 +#define ETH_BAR_0 0x2200 +#define ETH_BAR_1 0x2208 +#define ETH_BAR_2 0x2210 +#define ETH_BAR_3 0x2218 +#define ETH_BAR_4 0x2220 +#define ETH_BAR_5 0x2228 +#define ETH_SIZE_REG_0 0x2204 +#define ETH_SIZE_REG_1 0x220c +#define ETH_SIZE_REG_2 0x2214 +#define ETH_SIZE_REG_3 0x221c +#define ETH_SIZE_REG_4 0x2224 +#define ETH_SIZE_REG_5 0x222c +#define ETH_HEADERS_RETARGET_BASE_REG 0x2230 +#define ETH_HEADERS_RETARGET_CONTROL_REG 0x2234 +#define ETH_HIGH_ADDR_REMAP_REG_0 0x2280 +#define ETH_HIGH_ADDR_REMAP_REG_1 0x2284 +#define ETH_HIGH_ADDR_REMAP_REG_2 0x2288 +#define ETH_HIGH_ADDR_REMAP_REG_3 0x228c +#define ETH_BASE_ADDR_ENABLE_REG 0x2290 +#define ETH_ACCESS_PROTECTION_REG(port) (0x2294 + (port<<2)) +#define ETH_MIB_COUNTERS_BASE(port) (0x3000 + (port<<7)) +#define ETH_PORT_CONFIG_REG(port) (0x2400 + (port<<10)) +#define ETH_PORT_CONFIG_EXTEND_REG(port) (0x2404 + (port<<10)) +#define ETH_MII_SERIAL_PARAMETRS_REG(port) (0x2408 + (port<<10)) +#define ETH_GMII_SERIAL_PARAMETRS_REG(port) (0x240c + (port<<10)) +#define ETH_VLAN_ETHERTYPE_REG(port) (0x2410 + (port<<10)) +#define ETH_MAC_ADDR_LOW(port) (0x2414 + (port<<10)) +#define ETH_MAC_ADDR_HIGH(port) (0x2418 + (port<<10)) +#define ETH_SDMA_CONFIG_REG(port) (0x241c + (port<<10)) +#define ETH_DSCP_0(port) (0x2420 + (port<<10)) +#define ETH_DSCP_1(port) (0x2424 + (port<<10)) +#define ETH_DSCP_2(port) (0x2428 + (port<<10)) +#define ETH_DSCP_3(port) (0x242c + (port<<10)) +#define ETH_DSCP_4(port) (0x2430 + (port<<10)) +#define ETH_DSCP_5(port) (0x2434 + (port<<10)) +#define ETH_DSCP_6(port) (0x2438 + (port<<10)) +#define ETH_PORT_SERIAL_CONTROL_REG(port) (0x243c + (port<<10)) +#define ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port) (0x2440 + (port<<10)) +#define ETH_PORT_STATUS_REG(port) (0x2444 + (port<<10)) +#define ETH_TRANSMIT_QUEUE_COMMAND_REG(port) (0x2448 + (port<<10)) +#define ETH_TX_QUEUE_FIXED_PRIORITY(port) (0x244c + (port<<10)) +#define ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port) (0x2450 + (port<<10)) +#define ETH_MAXIMUM_TRANSMIT_UNIT(port) (0x2458 + (port<<10)) +#define ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port) (0x245c + (port<<10)) +#define ETH_INTERRUPT_CAUSE_REG(port) (0x2460 + (port<<10)) +#define ETH_INTERRUPT_CAUSE_EXTEND_REG(port) (0x2464 + (port<<10)) +#define ETH_INTERRUPT_MASK_REG(port) (0x2468 + (port<<10)) +#define ETH_INTERRUPT_EXTEND_MASK_REG(port) (0x246c + (port<<10)) +#define ETH_RX_FIFO_URGENT_THRESHOLD_REG(port) (0x2470 + (port<<10)) +#define ETH_TX_FIFO_URGENT_THRESHOLD_REG(port) (0x2474 + (port<<10)) +#define ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (0x247c + (port<<10)) +#define ETH_RX_DISCARDED_FRAMES_COUNTER(port) (0x2484 + (port<<10) +#define ETH_PORT_DEBUG_0_REG(port) (0x248c + (port<<10)) +#define ETH_PORT_DEBUG_1_REG(port) (0x2490 + (port<<10)) +#define ETH_PORT_INTERNAL_ADDR_ERROR_REG(port) (0x2494 + (port<<10)) +#define ETH_INTERNAL_USE_REG(port) (0x24fc + (port<<10)) +#define ETH_RECEIVE_QUEUE_COMMAND_REG(port) (0x2680 + (port<<10)) +#define ETH_CURRENT_SERVED_TX_DESC_PTR(port) (0x2684 + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port) (0x260c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port) (0x261c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port) (0x262c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port) (0x263c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port) (0x264c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port) (0x265c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port) (0x266c + (port<<10)) +#define ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port) (0x267c + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port) (0x26c0 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port) (0x26c4 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port) (0x26c8 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port) (0x26cc + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port) (0x26d0 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port) (0x26d4 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port) (0x26d8 + (port<<10)) +#define ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port) (0x26dc + (port<<10)) +#define ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port) (0x2700 + (port<<10)) +#define ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port) (0x2710 + (port<<10)) +#define ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port) (0x2720 + (port<<10)) +#define ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port) (0x2730 + (port<<10)) +#define ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port) (0x2740 + (port<<10)) +#define ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port) (0x2750 + (port<<10)) +#define ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port) (0x2760 + (port<<10)) +#define ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port) (0x2770 + (port<<10)) +#define ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port) (0x2704 + (port<<10)) +#define ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port) (0x2714 + (port<<10)) +#define ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port) (0x2724 + (port<<10)) +#define ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port) (0x2734 + (port<<10)) +#define ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port) (0x2744 + (port<<10)) +#define ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port) (0x2754 + (port<<10)) +#define ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port) (0x2764 + (port<<10)) +#define ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port) (0x2774 + (port<<10)) +#define ETH_TX_QUEUE_0_ARBITER_CONFIG(port) (0x2708 + (port<<10)) +#define ETH_TX_QUEUE_1_ARBITER_CONFIG(port) (0x2718 + (port<<10)) +#define ETH_TX_QUEUE_2_ARBITER_CONFIG(port) (0x2728 + (port<<10)) +#define ETH_TX_QUEUE_3_ARBITER_CONFIG(port) (0x2738 + (port<<10)) +#define ETH_TX_QUEUE_4_ARBITER_CONFIG(port) (0x2748 + (port<<10)) +#define ETH_TX_QUEUE_5_ARBITER_CONFIG(port) (0x2758 + (port<<10)) +#define ETH_TX_QUEUE_6_ARBITER_CONFIG(port) (0x2768 + (port<<10)) +#define ETH_TX_QUEUE_7_ARBITER_CONFIG(port) (0x2778 + (port<<10)) +#define ETH_PORT_TX_TOKEN_BUCKET_COUNT(port) (0x2780 + (port<<10)) +#define ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port) (0x3400 + (port<<10)) +#define ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port) (0x3500 + (port<<10)) +#define ETH_DA_FILTER_UNICAST_TABLE_BASE(port) (0x3600 + (port<<10)) + + +/* Ethernet GT64260 */ +/* +#define ETHERNET_PHY_ADDRESS_REGISTER 0x2000 +#define ETHERNET_SMI_REGISTER 0x2010 +*/ +/* Ethernet 0 */ +/* +#define ETHERNET0_PORT_CONFIGURATION_REGISTER 0x2400 +#define ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER 0x2408 +#define ETHERNET0_PORT_COMMAND_REGISTER 0x2410 +#define ETHERNET0_PORT_STATUS_REGISTER 0x2418 +#define ETHERNET0_SERIAL_PARAMETRS_REGISTER 0x2420 +#define ETHERNET0_HASH_TABLE_POINTER_REGISTER 0x2428 +#define ETHERNET0_FLOW_CONTROL_SOURCE_ADDRESS_LOW 0x2430 +#define ETHERNET0_FLOW_CONTROL_SOURCE_ADDRESS_HIGH 0x2438 +#define ETHERNET0_SDMA_CONFIGURATION_REGISTER 0x2440 +#define ETHERNET0_SDMA_COMMAND_REGISTER 0x2448 +#define ETHERNET0_INTERRUPT_CAUSE_REGISTER 0x2450 +#define ETHERNET0_INTERRUPT_MASK_REGISTER 0x2458 +#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0 0x2480 +#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER1 0x2484 +#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER2 0x2488 +#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER3 0x248c +#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0 0x24a0 +#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER1 0x24a4 +#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER2 0x24a8 +#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER3 0x24ac +#define ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0 0x24e0 +#define ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER1 0x24e4 +#define ETHERNET0_MIB_COUNTER_BASE 0x2500 +*/ +/* Ethernet 1 */ +/* +#define ETHERNET1_PORT_CONFIGURATION_REGISTER 0x2800 +#define ETHERNET1_PORT_CONFIGURATION_EXTEND_REGISTER 0x2808 +#define ETHERNET1_PORT_COMMAND_REGISTER 0x2810 +#define ETHERNET1_PORT_STATUS_REGISTER 0x2818 +#define ETHERNET1_SERIAL_PARAMETRS_REGISTER 0x2820 +#define ETHERNET1_HASH_TABLE_POINTER_REGISTER 0x2828 +#define ETHERNET1_FLOW_CONTROL_SOURCE_ADDRESS_LOW 0x2830 +#define ETHERNET1_FLOW_CONTROL_SOURCE_ADDRESS_HIGH 0x2838 +#define ETHERNET1_SDMA_CONFIGURATION_REGISTER 0x2840 +#define ETHERNET1_SDMA_COMMAND_REGISTER 0x2848 +#define ETHERNET1_INTERRUPT_CAUSE_REGISTER 0x2850 +#define ETHERNET1_INTERRUPT_MASK_REGISTER 0x2858 +#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER0 0x2880 +#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER1 0x2884 +#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER2 0x2888 +#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER3 0x288c +#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER0 0x28a0 +#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER1 0x28a4 +#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER2 0x28a8 +#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER3 0x28ac +#define ETHERNET1_CURRENT_TX_DESCRIPTOR_POINTER0 0x28e0 +#define ETHERNET1_CURRENT_TX_DESCRIPTOR_POINTER1 0x28e4 +#define ETHERNET1_MIB_COUNTER_BASE 0x2900 +*/ +/* Ethernet 2 */ +/* +#define ETHERNET2_PORT_CONFIGURATION_REGISTER 0x2c00 +#define ETHERNET2_PORT_CONFIGURATION_EXTEND_REGISTER 0x2c08 +#define ETHERNET2_PORT_COMMAND_REGISTER 0x2c10 +#define ETHERNET2_PORT_STATUS_REGISTER 0x2c18 +#define ETHERNET2_SERIAL_PARAMETRS_REGISTER 0x2c20 +#define ETHERNET2_HASH_TABLE_POINTER_REGISTER 0x2c28 +#define ETHERNET2_FLOW_CONTROL_SOURCE_ADDRESS_LOW 0x2c30 +#define ETHERNET2_FLOW_CONTROL_SOURCE_ADDRESS_HIGH 0x2c38 +#define ETHERNET2_SDMA_CONFIGURATION_REGISTER 0x2c40 +#define ETHERNET2_SDMA_COMMAND_REGISTER 0x2c48 +#define ETHERNET2_INTERRUPT_CAUSE_REGISTER 0x2c50 +#define ETHERNET2_INTERRUPT_MASK_REGISTER 0x2c58 +#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER0 0x2c80 +#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER1 0x2c84 +#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER2 0x2c88 +#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER3 0x2c8c +#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER0 0x2ca0 +#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER1 0x2ca4 +#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER2 0x2ca8 +#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER3 0x2cac +#define ETHERNET2_CURRENT_TX_DESCRIPTOR_POINTER0 0x2ce0 +#define ETHERNET2_CURRENT_TX_DESCRIPTOR_POINTER1 0x2ce4 +#define ETHERNET2_MIB_COUNTER_BASE 0x2d00 +*/ + +/****************************************/ +/* SDMA Registers */ +/****************************************/ + +#define SDMA_GROUP_CONFIGURATION_REGISTER 0xb1f0 +#define CHANNEL0_CONFIGURATION_REGISTER 0x4000 +#define CHANNEL0_COMMAND_REGISTER 0x4008 +#define CHANNEL0_RX_CMD_STATUS 0x4800 +#define CHANNEL0_RX_PACKET_AND_BUFFER_SIZES 0x4804 +#define CHANNEL0_RX_BUFFER_POINTER 0x4808 +#define CHANNEL0_RX_NEXT_POINTER 0x480c +#define CHANNEL0_CURRENT_RX_DESCRIPTOR_POINTER 0x4810 +#define CHANNEL0_TX_CMD_STATUS 0x4C00 +#define CHANNEL0_TX_PACKET_SIZE 0x4C04 +#define CHANNEL0_TX_BUFFER_POINTER 0x4C08 +#define CHANNEL0_TX_NEXT_POINTER 0x4C0c +#define CHANNEL0_CURRENT_TX_DESCRIPTOR_POINTER 0x4c10 +#define CHANNEL0_FIRST_TX_DESCRIPTOR_POINTER 0x4c14 +/* +#define CHANNEL1_CONFIGURATION_REGISTER 0x5000 +#define CHANNEL1_COMMAND_REGISTER 0x5008 +#define CHANNEL1_RX_CMD_STATUS 0x5800 +#define CHANNEL1_RX_PACKET_AND_BUFFER_SIZES 0x5804 +#define CHANNEL1_RX_BUFFER_POINTER 0x5808 +#define CHANNEL1_RX_NEXT_POINTER 0x580c +#define CHANNEL1_TX_CMD_STATUS 0x5C00 +#define CHANNEL1_TX_PACKET_SIZE 0x5C04 +#define CHANNEL1_TX_BUFFER_POINTER 0x5C08 +#define CHANNEL1_TX_NEXT_POINTER 0x5C0c +#define CHANNEL1_CURRENT_RX_DESCRIPTOR_POINTER 0x5810 +#define CHANNEL1_CURRENT_TX_DESCRIPTOR_POINTER 0x5c10 +#define CHANNEL1_FIRST_TX_DESCRIPTOR_POINTER 0x5c14 +#define CHANNEL2_CONFIGURATION_REGISTER 0x6000 +#define CHANNEL2_COMMAND_REGISTER 0x6008 +#define CHANNEL2_RX_CMD_STATUS 0x6800 +#define CHANNEL2_RX_PACKET_AND_BUFFER_SIZES 0x6804 +#define CHANNEL2_RX_BUFFER_POINTER 0x6808 +#define CHANNEL2_RX_NEXT_POINTER 0x680c +#define CHANNEL2_CURRENT_RX_DESCRIPTOR_POINTER 0x6810 +#define CHANNEL2_TX_CMD_STATUS 0x6C00 +#define CHANNEL2_TX_PACKET_SIZE 0x6C04 +#define CHANNEL2_TX_BUFFER_POINTER 0x6C08 +#define CHANNEL2_TX_NEXT_POINTER 0x6C0c +#define CHANNEL2_CURRENT_RX_DESCRIPTOR_POINTER 0x6810 +#define CHANNEL2_CURRENT_TX_DESCRIPTOR_POINTER 0x6c10 +#define CHANNEL2_FIRST_TX_DESCRIPTOR_POINTER 0x6c14 +*/ +/* SDMA Interrupt */ +/* +#define SDMA_CAUSE 0xb820 +#define SDMA_MASK 0xb8a0 +*/ +/***************************************/ +/* SDMA Registers */ +/***************************************/ + +#define SDMA_CONFIG_REG(channel) (0x4000 + (channel<<13)) +#define SDMA_COMMAND_REG(channel) (0x4008 + (channel<<13)) +#define SDMA_CURRENT_RX_DESCRIPTOR_POINTER(channel) (0x4810 + (channel<<13)) +#define SDMA_CURRENT_TX_DESCRIPTOR_POINTER(channel) (0x4c10 + (channel<<13)) +#define SDMA_FIRST_TX_DESCRIPTOR_POINTER(channel) (0x4c14 + (channel<<13)) + +#define SDMA_CAUSE_REG 0xb800 +#define SDMA_MASK_REG 0xb880 + +/****************************************/ +/* Baude Rate Generators Registers */ +/****************************************/ + +/* BRG 0 */ +#define BRG0_CONFIGURATION_REGISTER 0xb200 +#define BRG0_BAUDE_TUNING_REGISTER 0xb204 + +/* BRG 1 */ +#define BRG1_CONFIGURATION_REGISTER 0xb208 +#define BRG1_BAUDE_TUNING_REGISTER 0xb20c + +/* BRG 2 */ +#define BRG2_CONFIGURATION_REGISTER 0xb210 +#define BRG2_BAUDE_TUNING_REGISTER 0xb214 + +/* BRG Interrupts */ +#define BRG_CAUSE_REGISTER 0xb834 +#define BRG_MASK_REGISTER 0xb8b4 +#define BRG_CONFIG_REG(brg) (0xb200 + (brg<<3)) +#define BRG_BAUDE_TUNING_REG(brg) (0xb208 + (brg<<3)) +#define BRG_CAUSE_REG BRG_CAUSE_REGISTER /*0xb8341 */ +#define BRG_MASK_REG BRG_MASK_REGISTER /*0xb8b41 */ + +/* MISC */ + +#define MAIN_ROUTING_REGISTER 0xb400 +#define RECEIVE_CLOCK_ROUTING_REGISTER 0xb404 +#define TRANSMIT_CLOCK_ROUTING_REGISTER 0xb408 +#define COMM_UNIT_ARBITER_CONFIGURATION_REGISTER 0xb40c + +/****************************************/ +/* Watchdog registers */ +/****************************************/ +#define WATCHDOG_CONFIGURATION_REGISTER 0xb410 +#define WATCHDOG_VALUE_REGISTER 0xb414 +#define WATCHDOG_CONFIG_REG WATCHDOG_CONFIGURATION_REGISTER /*0xb4101 */ +#define WATCHDOG_VALUE_REG WATCHDOG_VALUE_REGISTER /*0xb4141 */ + + +/****************************************/ +/* Flex TDM Registers */ +/****************************************/ + +/* FTDM Port */ + +#define FLEXTDM_TRANSMIT_READ_POINTER 0xa800 +#define FLEXTDM_RECEIVE_READ_POINTER 0xa804 +#define FLEXTDM_CONFIGURATION_REGISTER 0xa808 +#define FLEXTDM_AUX_CHANNELA_TX_REGISTER 0xa80c +#define FLEXTDM_AUX_CHANNELA_RX_REGISTER 0xa810 +#define FLEXTDM_AUX_CHANNELB_TX_REGISTER 0xa814 +#define FLEXTDM_AUX_CHANNELB_RX_REGISTER 0xa818 + +/* FTDM Interrupts */ + +#define FTDM_CAUSE_REGISTER 0xb830 +#define FTDM_MASK_REGISTER 0xb8b0 + + +/****************************************/ +/* GPP Interface Registers */ +/****************************************/ + +#define GPP_IO_CONTROL 0xf100 +#define GPP_LEVEL_CONTROL 0xf110 +#define GPP_VALUE 0xf104 +#define GPP_INTERRUPT_CAUSE 0xf108 +#define GPP_INTERRUPT_MASK 0xf10c +#define GPP_INTERRUPT_MASK0 GPP_INTERRUPT_MASK /* 0xf10c1 */ +#define GPP_INTERRUPT_MASK1 0xf114 +#define GPP_VALUE_SET 0xf118 +#define GPP_VALUE_CLEAR 0xf11c + +/****************************************/ +/* MPP Interface Registers */ +/****************************************/ +#define MPP_CONTROL0 0xf000 +#define MPP_CONTROL1 0xf004 +#define MPP_CONTROL2 0xf008 +#define MPP_CONTROL3 0xf00c +#define DEBUG_PORT_MULTIPLEX 0xf014 + /*#define SERIAL_PORT_MULTIPLEX 0xf0101 */ + +/****************************************/ +/* Interrupt Controller Registers */ +/****************************************/ + +/****************************************/ +/* Interrupts */ +/****************************************/ +/****************************************/ +/* Interrupts (checked I.A. 14.10.02) */ +/****************************************/ + +#define LOW_INTERRUPT_CAUSE_REGISTER 0x004 /* gt64260: 0xc181 */ +#define HIGH_INTERRUPT_CAUSE_REGISTER 0x00c /* gt64260: 0xc681 */ +#define CPU_INTERRUPT_MASK_REGISTER_LOW 0x014 /* gt64260: 0xc1c1 */ +#define CPU_INTERRUPT_MASK_REGISTER_HIGH 0x01c /* gt64260: 0xc6c1 */ +#define CPU_SELECT_CAUSE_REGISTER 0x024 /* gt64260: 0xc701 */ +#define CPU_INTERRUPT_1_MASK_REGISTER_LOW 0x034 /* new in the MV64360 and MV64460 */ +#define CPU_INTERRUPT_1_MASK_REGISTER_HIGH 0x03c /* new in the MV64360 and MV64460 */ +#define CPU_SELECT_1_CAUSE_REGISTER 0x044 /* new in the MV64360 and MV64460 */ +#define PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW 0x054 /* gt64260: 0xc241 */ +#define PCI_0INTERRUPT_CAUSE_MASK_REGISTER_HIGH 0x05c /* gt64260: 0xc641 */ +#define PCI_0SELECT_CAUSE 0x064 /* gt64260: 0xc741 */ +#define PCI_1INTERRUPT_CAUSE_MASK_REGISTER_LOW 0x074 /* gt64260: 0xca41 */ +#define PCI_1INTERRUPT_CAUSE_MASK_REGISTER_HIGH 0x07c /* gt64260: 0xce41 */ +#define PCI_1SELECT_CAUSE 0x084 /* gt64260: 0xcf41 */ +/*#define CPU_INT_0_MASK 0xe60 signal is not multiplexed on MPP in the MV64360 and MV64460 */ +/*#define CPU_INT_1_MASK 0xe64 signal is not multiplexed on MPP in the MV64360 and MV64460 */ +/*#define CPU_INT_2_MASK 0xe68 signal is not multiplexed on MPP in the MV64360 and MV64460 */ +/*#define CPU_INT_3_MASK 0xe6c signal is not multiplexed on MPP in the MV64360 and MV64460 */ + +#define MAIN_INTERRUPT_CAUSE_LOW LOW_INTERRUPT_CAUSE_REGISTER /* 0x0041 */ +#define MAIN_INTERRUPT_CAUSE_HIGH HIGH_INTERRUPT_CAUSE_REGISTER /* 0x00c1 */ +#define CPU_INTERRUPT0_MASK_LOW CPU_INTERRUPT_MASK_REGISTER_LOW /* 0x0141 */ +#define CPU_INTERRUPT0_MASK_HIGH CPU_INTERRUPT_MASK_REGISTER_HIGH /*0x01c1 */ +#define CPU_INTERRUPT0_SELECT_CAUSE CPU_SELECT_CAUSE_REGISTER /* 0x0241 */ +#define CPU_INTERRUPT1_MASK_LOW CPU_INTERRUPT_1_MASK_REGISTER_LOW /* 0x0341 */ +#define CPU_INTERRUPT1_MASK_HIGH CPU_INTERRUPT_1_MASK_REGISTER_HIGH /* 0x03c1 */ +#define CPU_INTERRUPT1_SELECT_CAUSE CPU_SELECT_1_CAUSE_REGISTER /* 0x0441 */ +#define INTERRUPT0_MASK_0_LOW PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW /* 0x0541 */ +#define INTERRUPT0_MASK_0_HIGH PCI_0INTERRUPT_CAUSE_MASK_REGISTER_HIGH /* 0x05c1 */ +#define INTERRUPT0_SELECT_CAUSE PCI_0SELECT_CAUSE /* 0x0641 */ +#define INTERRUPT1_MASK_0_LOW PCI_1INTERRUPT_CAUSE_MASK_REGISTER_LOW /* 0x0741 */ +#define INTERRUPT1_MASK_0_HIGH PCI_1INTERRUPT_CAUSE_MASK_REGISTER_HIGH /* 0x07c1 */ +#define INTERRUPT1_SELECT_CAUSE PCI_1SELECT_CAUSE /* 0x0841 */ + +/****************************************/ +/* I2C Registers */ +/****************************************/ + +#define I2C_SLAVE_ADDRESS 0xc000 +#define I2C_EXTENDED_SLAVE_ADDRESS 0xc040 +#define I2C_DATA 0xc004 +#define I2C_CONTROL 0xc008 +#define I2C_STATUS_BAUDE_RATE 0xc00C +#define I2C_SOFT_RESET 0xc01c +#define I2C_SLAVE_ADDR I2C_SLAVE_ADDRESS /* 0xc0001 */ +#define I2C_EXTENDED_SLAVE_ADDR I2C_EXTENDED_SLAVE_ADDRESS /*0xc0101 */ + +/****************************************/ +/* MPSC Registers */ +/****************************************/ + + /* MPSCs Clocks Routing Registers */ + +#define MPSC_ROUTING_REG 0xb400 +#define MPSC_RX_CLOCK_ROUTING_REG 0xb404 +#define MPSC_TX_CLOCK_ROUTING_REG 0xb408 + + /* MPSCs Interrupts Registers */ + +#define MPSC_CAUSE_REG(port) (0xb804 + (port<<3)) +#define MPSC_MASK_REG(port) (0xb884 + (port<<3)) + +#define MPSC_MAIN_CONFIG_LOW(port) (0x8000 + (port<<12)) +#define MPSC_MAIN_CONFIG_HIGH(port) (0x8004 + (port<<12)) +#define MPSC_PROTOCOL_CONFIG(port) (0x8008 + (port<<12)) +#define MPSC_CHANNEL_REG1(port) (0x800c + (port<<12)) +#define MPSC_CHANNEL_REG2(port) (0x8010 + (port<<12)) +#define MPSC_CHANNEL_REG3(port) (0x8014 + (port<<12)) +#define MPSC_CHANNEL_REG4(port) (0x8018 + (port<<12)) +#define MPSC_CHANNEL_REG5(port) (0x801c + (port<<12)) +#define MPSC_CHANNEL_REG6(port) (0x8020 + (port<<12)) +#define MPSC_CHANNEL_REG7(port) (0x8024 + (port<<12)) +#define MPSC_CHANNEL_REG8(port) (0x8028 + (port<<12)) +#define MPSC_CHANNEL_REG9(port) (0x802c + (port<<12)) +#define MPSC_CHANNEL_REG10(port) (0x8030 + (port<<12)) + + +/* MPSC0 */ + +#define MPSC0_MAIN_CONFIGURATION_LOW 0x8000 +#define MPSC0_MAIN_CONFIGURATION_HIGH 0x8004 +#define MPSC0_PROTOCOL_CONFIGURATION 0x8008 +#define CHANNEL0_REGISTER1 0x800c +#define CHANNEL0_REGISTER2 0x8010 +#define CHANNEL0_REGISTER3 0x8014 +#define CHANNEL0_REGISTER4 0x8018 +#define CHANNEL0_REGISTER5 0x801c +#define CHANNEL0_REGISTER6 0x8020 +#define CHANNEL0_REGISTER7 0x8024 +#define CHANNEL0_REGISTER8 0x8028 +#define CHANNEL0_REGISTER9 0x802c +#define CHANNEL0_REGISTER10 0x8030 +#define CHANNEL0_REGISTER11 0x8034 + +/* MPSC1 */ + +#define MPSC1_MAIN_CONFIGURATION_LOW 0x8840 +#define MPSC1_MAIN_CONFIGURATION_HIGH 0x8844 +#define MPSC1_PROTOCOL_CONFIGURATION 0x8848 +#define CHANNEL1_REGISTER1 0x884c +#define CHANNEL1_REGISTER2 0x8850 +#define CHANNEL1_REGISTER3 0x8854 +#define CHANNEL1_REGISTER4 0x8858 +#define CHANNEL1_REGISTER5 0x885c +#define CHANNEL1_REGISTER6 0x8860 +#define CHANNEL1_REGISTER7 0x8864 +#define CHANNEL1_REGISTER8 0x8868 +#define CHANNEL1_REGISTER9 0x886c +#define CHANNEL1_REGISTER10 0x8870 +#define CHANNEL1_REGISTER11 0x8874 + +/* MPSC2 */ + +#define MPSC2_MAIN_CONFIGURATION_LOW 0x9040 +#define MPSC2_MAIN_CONFIGURATION_HIGH 0x9044 +#define MPSC2_PROTOCOL_CONFIGURATION 0x9048 +#define CHANNEL2_REGISTER1 0x904c +#define CHANNEL2_REGISTER2 0x9050 +#define CHANNEL2_REGISTER3 0x9054 +#define CHANNEL2_REGISTER4 0x9058 +#define CHANNEL2_REGISTER5 0x905c +#define CHANNEL2_REGISTER6 0x9060 +#define CHANNEL2_REGISTER7 0x9064 +#define CHANNEL2_REGISTER8 0x9068 +#define CHANNEL2_REGISTER9 0x906c +#define CHANNEL2_REGISTER10 0x9070 +#define CHANNEL2_REGISTER11 0x9074 + +/* MPSCs Interupts */ + +#define MPSC0_CAUSE 0xb824 +#define MPSC0_MASK 0xb8a4 +#define MPSC1_CAUSE 0xb828 +#define MPSC1_MASK 0xb8a8 +#define MPSC2_CAUSE 0xb82c +#define MPSC2_MASK 0xb8ac + +/*******************************************/ +/* CUNIT Registers */ +/*******************************************/ + + /* Address Decoding Register Map */ + +#define CUNIT_BASE_ADDR_REG0 0xf200 +#define CUNIT_BASE_ADDR_REG1 0xf208 +#define CUNIT_BASE_ADDR_REG2 0xf210 +#define CUNIT_BASE_ADDR_REG3 0xf218 +#define CUNIT_SIZE0 0xf204 +#define CUNIT_SIZE1 0xf20c +#define CUNIT_SIZE2 0xf214 +#define CUNIT_SIZE3 0xf21c +#define CUNIT_HIGH_ADDR_REMAP_REG0 0xf240 +#define CUNIT_HIGH_ADDR_REMAP_REG1 0xf244 +#define CUNIT_BASE_ADDR_ENABLE_REG 0xf250 +#define MPSC0_ACCESS_PROTECTION_REG 0xf254 +#define MPSC1_ACCESS_PROTECTION_REG 0xf258 +#define CUNIT_INTERNAL_SPACE_BASE_ADDR_REG 0xf25C + + /* Error Report Registers */ + +#define CUNIT_INTERRUPT_CAUSE_REG 0xf310 +#define CUNIT_INTERRUPT_MASK_REG 0xf314 +#define CUNIT_ERROR_ADDR 0xf318 + + /* Cunit Control Registers */ + +#define CUNIT_ARBITER_CONTROL_REG 0xf300 +#define CUNIT_CONFIG_REG 0xb40c +#define CUNIT_CRROSBAR_TIMEOUT_REG 0xf304 + + /* Cunit Debug Registers */ + +#define CUNIT_DEBUG_LOW 0xf340 +#define CUNIT_DEBUG_HIGH 0xf344 +#define CUNIT_MMASK 0xf380 + +#endif /* __INCmv_gen_regh */ diff --git a/board/Marvell/include/pci.h b/board/Marvell/include/pci.h new file mode 100644 index 0000000..167248d --- /dev/null +++ b/board/Marvell/include/pci.h @@ -0,0 +1,293 @@ +/* PCI.h - PCI functions header file */ + +/* Copyright - Galileo technology. */ + +#ifndef __INCpcih +#define __INCpcih + +/* includes */ + +#include"core.h" +#include"memory.h" + +/* According to PCI REV 2.1 MAX agents allowed on the bus are -21- */ +#define PCI_MAX_DEVICES 22 + + +/* Macros */ + +/* The next Macros configurate the initiator board (SELF) or any any agent on + the PCI to become: MASTER, response to MEMORY transactions , response to + IO transactions or TWO both MEMORY_IO transactions. Those configuration + are for both PCI0 and PCI1. */ + +#define PCI_MEMORY_ENABLE(host, deviceNumber) pciWriteConfigReg(host, \ + PCI_STATUS_AND_COMMAND,deviceNumber,MEMORY_ENABLE | \ + pciReadConfigReg(host, PCI_STATUS_AND_COMMAND,deviceNumber) ) + +#define PCI_IO_ENABLE(host, deviceNumber) pciWriteConfigReg(host, \ + PCI_STATUS_AND_COMMAND,deviceNumber,I_O_ENABLE | \ + pciReadConfigReg(host, PCI_STATUS_AND_COMMAND,deviceNumber) ) + +#define PCI_SLAVE_ENABLE(host, deviceNumber) pciWriteConfigReg(host, \ + PCI_STATUS_AND_COMMAND,deviceNumber,MEMORY_ENABLE | I_O_ENABLE | \ + pciReadConfigReg(host, PCI_STATUS_AND_COMMAND,deviceNumber) ) + +#define PCI_DISABLE(host, deviceNumber) pciWriteConfigReg(host, \ + PCI_STATUS_AND_COMMAND,deviceNumber,0xfffffff8 & \ + pciReadConfigReg(host, PCI_STATUS_AND_COMMAND,deviceNumber)) + +#define PCI_MASTER_ENABLE(host,deviceNumber) pciWriteConfigReg(host, \ + PCI_STATUS_AND_COMMAND,deviceNumber,MASTER_ENABLE | \ + pciReadConfigReg(host,PCI_STATUS_AND_COMMAND,deviceNumber) ) + +#define PCI_MASTER_DISABLE(deviceNumber) pciWriteConfigReg(host, \ + PCI_STATUS_AND_COMMAND,deviceNumber,~MASTER_ENABLE & \ + pciReadConfigReg(host,PCI_STATUS_AND_COMMAND,deviceNumber) ) + +#define MASTER_ENABLE BIT2 +#define MEMORY_ENABLE BIT1 +#define I_O_ENABLE BIT0 +#define SELF 32 + +/* Agent on the PCI bus may have up to 6 BARS. */ +#define BAR0 0x10 +#define BAR1 0x14 +#define BAR2 0x18 +#define BAR3 0x1c +#define BAR4 0x20 +#define BAR5 0x24 +#define BAR_SEL_MEM_IO BIT0 +#define BAR_MEM_TYPE_32_BIT NO_BIT +#define BAR_MEM_TYPE_BELOW_1M BIT1 +#define BAR_MEM_TYPE_64_BIT BIT2 +#define BAR_MEM_TYPE_RESERVED (BIT1 | BIT2) +#define BAR_MEM_TYPE_MASK (BIT1 | BIT2) +#define BAR_PREFETCHABLE BIT3 +#define BAR_CONFIG_MASK (BIT0 | BIT1 | BIT2 | BIT3) + +/* Defines for the access regions. */ +#define PREFETCH_ENABLE BIT12 +#define PREFETCH_DISABLE NO_BIT +#define DELAYED_READ_ENABLE BIT13 +/* #define CACHING_ENABLE BIT14 */ +/* aggressive prefetch: PCI slave prefetch two burst in advance*/ +#define AGGRESSIVE_PREFETCH BIT16 +/* read line aggresive prefetch: PCI slave prefetch two burst in advance*/ +#define READ_LINE_AGGRESSIVE_PREFETCH BIT17 +/* read multiple aggresive prefetch: PCI slave prefetch two burst in advance*/ +#define READ_MULTI_AGGRESSIVE_PREFETCH BIT18 +#define MAX_BURST_4 NO_BIT +#define MAX_BURST_8 BIT20 /* Bits[21:20] = 01 */ +#define MAX_BURST_16 BIT21 /* Bits[21:20] = 10 */ +#define PCI_BYTE_SWAP NO_BIT /* Bits[25:24] = 00 */ +#define PCI_NO_SWAP BIT24 /* Bits[25:24] = 01 */ +#define PCI_BYTE_AND_WORD_SWAP BIT25 /* Bits[25:24] = 10 */ +#define PCI_WORD_SWAP (BIT24 | BIT25) /* Bits[25:24] = 11 */ +#define PCI_ACCESS_PROTECT BIT28 +#define PCI_WRITE_PROTECT BIT29 + +/* typedefs */ + +typedef enum __pciAccessRegions{REGION0,REGION1,REGION2,REGION3,REGION4,REGION5, + REGION6,REGION7} PCI_ACCESS_REGIONS; + +typedef enum __pciAgentPrio{LOW_AGENT_PRIO,HI_AGENT_PRIO} PCI_AGENT_PRIO; +typedef enum __pciAgentPark{PARK_ON_AGENT,DONT_PARK_ON_AGENT} PCI_AGENT_PARK; + +typedef enum __pciSnoopType{PCI_NO_SNOOP,PCI_SNOOP_WT,PCI_SNOOP_WB} + PCI_SNOOP_TYPE; +typedef enum __pciSnoopRegion{PCI_SNOOP_REGION0,PCI_SNOOP_REGION1, + PCI_SNOOP_REGION2,PCI_SNOOP_REGION3} + PCI_SNOOP_REGION; + +typedef enum __memPciHost{PCI_HOST0,PCI_HOST1} PCI_HOST; +typedef enum __memPciRegion{PCI_REGION0,PCI_REGION1, + PCI_REGION2,PCI_REGION3, + PCI_IO} + PCI_REGION; + +/*ronen 7/Dec/03 */ +typedef enum __pci_bar_windows{PCI_CS0_BAR, PCI_CS1_BAR, PCI_CS2_BAR, + PCI_CS3_BAR, PCI_DEV_CS0_BAR, PCI_DEV_CS1_BAR, + PCI_DEV_CS2_BAR, PCI_DEV_CS3_BAR, PCI_BOOT_CS_BAR, + PCI_MEM_INT_REG_BAR, PCI_IO_INT_REG_BAR, + PCI_P2P_MEM0_BAR, PCI_P2P_MEM1_BAR, + PCI_P2P_IO_BAR, PCI_CPU_BAR, PCI_INT_SRAM_BAR, + PCI_LAST_BAR} PCI_INTERNAL_BAR; + +typedef struct pciBar { + unsigned int detectBase; + unsigned int base; + unsigned int size; + unsigned int type; +} PCI_BAR; + +typedef struct pciDevice { + PCI_HOST host; + char type[40]; + unsigned int deviceNum; + unsigned int venID; + unsigned int deviceID; + PCI_BAR bar[6]; +} PCI_DEVICE; + +typedef struct pciSelfBars { + unsigned int SCS0Base; + unsigned int SCS0Size; + unsigned int SCS1Base; + unsigned int SCS1Size; + unsigned int SCS2Base; + unsigned int SCS2Size; + unsigned int SCS3Base; + unsigned int SCS3Size; + unsigned int internalMemBase; + unsigned int internalIOBase; + unsigned int CS0Base; + unsigned int CS0Size; + unsigned int CS1Base; + unsigned int CS1Size; + unsigned int CS2Base; + unsigned int CS2Size; + unsigned int CS3Base; + unsigned int CS3Size; + unsigned int CSBootBase; + unsigned int CSBootSize; + unsigned int P2PMem0Base; + unsigned int P2PMem0Size; + unsigned int P2PMem1Base; + unsigned int P2PMem1Size; + unsigned int P2PIOBase; + unsigned int P2PIOSize; + unsigned int CPUBase; + unsigned int CPUSize; +} PCI_SELF_BARS; + +/* read/write configuration registers on local PCI bus. */ +void pciWriteConfigReg(PCI_HOST host, unsigned int regOffset, + unsigned int pciDevNum, unsigned int data); +unsigned int pciReadConfigReg (PCI_HOST host, unsigned int regOffset, + unsigned int pciDevNum); + +/* read/write configuration registers on another PCI bus. */ +void pciOverBridgeWriteConfigReg(PCI_HOST host, + unsigned int regOffset, + unsigned int pciDevNum, + unsigned int busNum,unsigned int data); +unsigned int pciOverBridgeReadConfigReg(PCI_HOST host, + unsigned int regOffset, + unsigned int pciDevNum, + unsigned int busNum); + +/* Performs full scane on both PCI and returns all detail possible on the + agents which exist on the bus. */ +void pciScanDevices(PCI_HOST host, PCI_DEVICE *pci0Detect, + unsigned int numberOfElment); + +/* Master`s memory space */ +bool pciMapSpace(PCI_HOST host, PCI_REGION region, + unsigned int remapBase, + unsigned int deviceBase, + unsigned int deviceLength); +unsigned int pciGetSpaceBase(PCI_HOST host, PCI_REGION region); +unsigned int pciGetSpaceSize(PCI_HOST host, PCI_REGION region); + +/* Slave`s memory space */ +void pciMapMemoryBank(PCI_HOST host, MEMORY_BANK bank, + unsigned int pci0Dram0Base, unsigned int pci0Dram0Size); + +#if 0 /* GARBAGE routines - dont use till they get cleaned up */ +void pci0ScanSelfBars(PCI_SELF_BARS *pci0SelfBars); +void pci1ScanSelfBars(PCI_SELF_BARS *pci1SelfBars); +void pci0MapInternalRegSpace(unsigned int pci0InternalBase); +void pci1MapInternalRegSpace(unsigned int pci1InternalBase); +void pci0MapInternalRegIOSpace(unsigned int pci0InternalBase); +void pci1MapInternalRegIOSpace(unsigned int pci1InternalBase); +void pci0MapDevice0MemorySpace(unsigned int pci0Dev0Base, + unsigned int pci0Dev0Length); +void pci1MapDevice0MemorySpace(unsigned int pci1Dev0Base, + unsigned int pci1Dev0Length); +void pci0MapDevice1MemorySpace(unsigned int pci0Dev1Base, + unsigned int pci0Dev1Length); +void pci1MapDevice1MemorySpace(unsigned int pci1Dev1Base, + unsigned int pci1Dev1Length); +void pci0MapDevice2MemorySpace(unsigned int pci0Dev2Base, + unsigned int pci0Dev2Length); +void pci1MapDevice2MemorySpace(unsigned int pci1Dev2Base, + unsigned int pci1Dev2Length); +void pci0MapDevice3MemorySpace(unsigned int pci0Dev3Base, + unsigned int pci0Dev3Length); +void pci1MapDevice3MemorySpace(unsigned int pci1Dev3Base, + unsigned int pci1Dev3Length); +void pci0MapBootDeviceMemorySpace(unsigned int pci0DevBootBase, + unsigned int pci0DevBootLength); +void pci1MapBootDeviceMemorySpace(unsigned int pci1DevBootBase, + unsigned int pci1DevBootLength); +void pci0MapP2pMem0Space(unsigned int pci0P2pMem0Base, + unsigned int pci0P2pMem0Length); +void pci1MapP2pMem0Space(unsigned int pci1P2pMem0Base, + unsigned int pci1P2pMem0Length); +void pci0MapP2pMem1Space(unsigned int pci0P2pMem1Base, + unsigned int pci0P2pMem1Length); +void pci1MapP2pMem1Space(unsigned int pci1P2pMem1Base, + unsigned int pci1P2pMem1Length); +void pci0MapP2pIoSpace(unsigned int pci0P2pIoBase, + unsigned int pci0P2pIoLength); +void pci1MapP2pIoSpace(unsigned int pci1P2pIoBase, + unsigned int pci1P2pIoLength); + +void pci0MapCPUspace(unsigned int pci0CpuBase, unsigned int pci0CpuLengs); +void pci1MapCPUspace(unsigned int pci1CpuBase, unsigned int pci1CpuLengs); +#endif + +/* PCI region options */ + +bool pciSetRegionFeatures(PCI_HOST host, PCI_ACCESS_REGIONS region, + unsigned int features, unsigned int baseAddress, + unsigned int regionLength); + +void pciDisableAccessRegion(PCI_HOST host, PCI_ACCESS_REGIONS region); + +/* PCI arbiter */ + +bool pciArbiterEnable(PCI_HOST host); +bool pciArbiterDisable(PCI_HOST host); +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); +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); +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); +bool pciEnableBrokenAgentDetection(PCI_HOST host, unsigned char brokenValue); +bool pciEnableBrokenAgentDetection(PCI_HOST host, unsigned char brokenValue); + +/* PCI-to-PCI (P2P) */ + +bool pciP2PConfig(PCI_HOST host, + unsigned int SecondBusLow,unsigned int SecondBusHigh, + unsigned int busNum,unsigned int devNum); +/* PCI Cache-coherency */ + +bool pciSetRegionSnoopMode(PCI_HOST host, PCI_SNOOP_REGION region, + PCI_SNOOP_TYPE snoopType, + unsigned int baseAddress, + unsigned int regionLength); + +PCI_DEVICE * pciFindDevice(unsigned short ven, unsigned short dev); + +#endif /* __INCpcih */ diff --git a/board/mpl/pati/cmd_pati.c b/board/mpl/pati/cmd_pati.c index cdab286..98429c0 100644 --- a/board/mpl/pati/cmd_pati.c +++ b/board/mpl/pati/cmd_pati.c @@ -296,8 +296,6 @@ static int pati_pci_eeprom_read(unsigned short offset, unsigned long addr, unsig return 0; } - - /****************************************************************************** * PCI Bridge Registers Dump *******************************************************************************/ diff --git a/board/mpl/pati/plx9056.h b/board/mpl/pati/plx9056.h index 763a793..963857f 100644 --- a/board/mpl/pati/plx9056.h +++ b/board/mpl/pati/plx9056.h @@ -1,114 +1,114 @@ -/*
- * (C) Copyright 2003
- * Denis Peter, d.peter@mpl.ch
- * 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
- */
-/* PLX9096 register definitions
-*/
-#ifndef __PLX9056_H_
-#define __PLX9056_H_ 1
-
-#include <pci.h>
-
-#ifdef PLX9056_LOC
-#define LOCAL_OFFSET 0x080
-/* PCI Config regs */
-#else
-#define LOCAL_OFFSET 0x000
-#endif
-
-#define PCI9056_VENDOR_ID PCI_VENDOR_ID
-//#define PCI9656_DEVICE_ID PCI_DEVICE_ID
-#define PCI9056_COMMAND PCI_COMMAND
-//#define PCI9656_STATUS PCI_STATUS
-#define PCI9056_REVISION PCI_REVISION_ID
-
-#define PCI9056_CACHE_SIZE PCI_CACHE_LINE_SIZE
-#define PCI9056_RTR_BASE PCI_BASE_ADDRESS_0
-#define PCI9056_RTR_IO_BASE PCI_BASE_ADDRESS_1
-#define PCI9056_LOCAL_BASE0 PCI_BASE_ADDRESS_2
-#define PCI9056_LOCAL_BASE1 PCI_BASE_ADDRESS_3
-#define PCI9056_UNUSED_BASE1 PCI_BASE_ADDRESS_4
-#define PCI9056_UNUSED_BASE2 PCI_BASE_ADDRESS_5
-#define PCI9056_CIS_PTR PCI_CARDBUS_CIS
-#define PCI9056_SUB_ID PCI_SUBSYSTEM_VENDOR_ID
-#define PCI9056_EXP_ROM_BASE PCI_ROM_ADDRESS
-#define PCI9056_CAP_PTR PCI_CAPABILITY_LIST
-#define PCI9056_INT_LINE PCI_INTERRUPT_LINE
-
-#if defined(PLX9056_LOC)
- #define PCI9056_PM_CAP_ID 0x180
- #define PCI9056_PM_CSR 0x184
- #define PCI9056_HS_CAP_ID 0x188
- #define PCI9056_VPD_CAP_ID 0x18C
- #define PCI9056_VPD_DATA 0x190
-#endif
-
-
-
-#define PCI_DEVICE_ID_PLX9056 0x9056
-
-/* Local Configuration Registers Accessible via the PCI Base address + Variable */
-#define PCI9056_SPACE0_RANGE (0x000 + LOCAL_OFFSET)
-#define PCI9056_SPACE0_REMAP (0x004 + LOCAL_OFFSET)
-#define PCI9056_LOCAL_DMA_ARBIT (0x008 + LOCAL_OFFSET)
-#define PCI9056_ENDIAN_DESC (0x00c + LOCAL_OFFSET)
-#define PCI9056_EXP_ROM_RANGE (0x010 + LOCAL_OFFSET)
-#define PCI9056_EXP_ROM_REMAP (0x014 + LOCAL_OFFSET)
-#define PCI9056_SPACE0_ROM_DESC (0x018 + LOCAL_OFFSET)
-#define PCI9056_DM_RANGE (0x01c + LOCAL_OFFSET)
-#define PCI9056_DM_MEM_BASE (0x020 + LOCAL_OFFSET)
-#define PCI9056_DM_IO_BASE (0x024 + LOCAL_OFFSET)
-#define PCI9056_DM_PCI_MEM_REMAP (0x028 + LOCAL_OFFSET)
-#define PCI9056_DM_PCI_IO_CONFIG (0x02c + LOCAL_OFFSET)
-#define PCI9056_SPACE1_RANGE (0x0f0 + LOCAL_OFFSET)
-#define PCI9056_SPACE1_REMAP (0x0f4 + LOCAL_OFFSET)
-#define PCI9056_SPACE1_DESC (0x0f8 + LOCAL_OFFSET)
-#define PCI9056_DM_DAC (0x0fc + LOCAL_OFFSET)
-
-#ifdef PLX9056_LOC
-#define PCI9056_ARBITER_CTRL 0x1A0
-#define PCI9056_ABORT_ADDRESS 0x1A4
-#endif
-
-/* Runtime registers PCI Address + LOCAL_OFFSET */
-#ifdef PLX9056_LOC
-#define PCI9056_MAILBOX0 0x0C0
-#define PCI9056_MAILBOX1 0x0C4
-#else
-#define PCI9056_MAILBOX0 0x078
-#define PCI9056_MAILBOX1 0x07c
-#endif
-
-#define PCI9056_MAILBOX2 (0x048 + LOCAL_OFFSET)
-#define PCI9056_MAILBOX3 (0x04c + LOCAL_OFFSET)
-#define PCI9056_MAILBOX4 (0x050 + LOCAL_OFFSET)
-#define PCI9056_MAILBOX5 (0x054 + LOCAL_OFFSET)
-#define PCI9056_MAILBOX6 (0x058 + LOCAL_OFFSET)
-#define PCI9056_MAILBOX7 (0x05c + LOCAL_OFFSET)
-#define PCI9056_PCI_TO_LOC_DBELL (0x060 + LOCAL_OFFSET)
-#define PCI9056_LOC_TO_PCI_DBELL (0x064 + LOCAL_OFFSET)
-#define PCI9056_INT_CTRL_STAT (0x068 + LOCAL_OFFSET)
-#define PCI9056_EEPROM_CTRL_STAT (0x06c + LOCAL_OFFSET)
-#define PCI9056_PERM_VENDOR_ID (0x070 + LOCAL_OFFSET)
-#define PCI9056_REVISION_ID (0x074 + LOCAL_OFFSET)
-
-
-#endif /* #ifndef __PLX9056_H_ */
-
+/* + * (C) Copyright 2003 + * Denis Peter, d.peter@mpl.ch + * 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 + */ +/* PLX9096 register definitions +*/ +#ifndef __PLX9056_H_ +#define __PLX9056_H_ 1 + +#include <pci.h> + +#ifdef PLX9056_LOC +#define LOCAL_OFFSET 0x080 +/* PCI Config regs */ +#else +#define LOCAL_OFFSET 0x000 +#endif + +#define PCI9056_VENDOR_ID PCI_VENDOR_ID +/*#define PCI9656_DEVICE_ID PCI_DEVICE_ID */ +#define PCI9056_COMMAND PCI_COMMAND +/*#define PCI9656_STATUS PCI_STATUS */ +#define PCI9056_REVISION PCI_REVISION_ID + +#define PCI9056_CACHE_SIZE PCI_CACHE_LINE_SIZE +#define PCI9056_RTR_BASE PCI_BASE_ADDRESS_0 +#define PCI9056_RTR_IO_BASE PCI_BASE_ADDRESS_1 +#define PCI9056_LOCAL_BASE0 PCI_BASE_ADDRESS_2 +#define PCI9056_LOCAL_BASE1 PCI_BASE_ADDRESS_3 +#define PCI9056_UNUSED_BASE1 PCI_BASE_ADDRESS_4 +#define PCI9056_UNUSED_BASE2 PCI_BASE_ADDRESS_5 +#define PCI9056_CIS_PTR PCI_CARDBUS_CIS +#define PCI9056_SUB_ID PCI_SUBSYSTEM_VENDOR_ID +#define PCI9056_EXP_ROM_BASE PCI_ROM_ADDRESS +#define PCI9056_CAP_PTR PCI_CAPABILITY_LIST +#define PCI9056_INT_LINE PCI_INTERRUPT_LINE + +#if defined(PLX9056_LOC) + #define PCI9056_PM_CAP_ID 0x180 + #define PCI9056_PM_CSR 0x184 + #define PCI9056_HS_CAP_ID 0x188 + #define PCI9056_VPD_CAP_ID 0x18C + #define PCI9056_VPD_DATA 0x190 +#endif + + + +#define PCI_DEVICE_ID_PLX9056 0x9056 + +/* Local Configuration Registers Accessible via the PCI Base address + Variable */ +#define PCI9056_SPACE0_RANGE (0x000 + LOCAL_OFFSET) +#define PCI9056_SPACE0_REMAP (0x004 + LOCAL_OFFSET) +#define PCI9056_LOCAL_DMA_ARBIT (0x008 + LOCAL_OFFSET) +#define PCI9056_ENDIAN_DESC (0x00c + LOCAL_OFFSET) +#define PCI9056_EXP_ROM_RANGE (0x010 + LOCAL_OFFSET) +#define PCI9056_EXP_ROM_REMAP (0x014 + LOCAL_OFFSET) +#define PCI9056_SPACE0_ROM_DESC (0x018 + LOCAL_OFFSET) +#define PCI9056_DM_RANGE (0x01c + LOCAL_OFFSET) +#define PCI9056_DM_MEM_BASE (0x020 + LOCAL_OFFSET) +#define PCI9056_DM_IO_BASE (0x024 + LOCAL_OFFSET) +#define PCI9056_DM_PCI_MEM_REMAP (0x028 + LOCAL_OFFSET) +#define PCI9056_DM_PCI_IO_CONFIG (0x02c + LOCAL_OFFSET) +#define PCI9056_SPACE1_RANGE (0x0f0 + LOCAL_OFFSET) +#define PCI9056_SPACE1_REMAP (0x0f4 + LOCAL_OFFSET) +#define PCI9056_SPACE1_DESC (0x0f8 + LOCAL_OFFSET) +#define PCI9056_DM_DAC (0x0fc + LOCAL_OFFSET) + +#ifdef PLX9056_LOC +#define PCI9056_ARBITER_CTRL 0x1A0 +#define PCI9056_ABORT_ADDRESS 0x1A4 +#endif + +/* Runtime registers PCI Address + LOCAL_OFFSET */ +#ifdef PLX9056_LOC +#define PCI9056_MAILBOX0 0x0C0 +#define PCI9056_MAILBOX1 0x0C4 +#else +#define PCI9056_MAILBOX0 0x078 +#define PCI9056_MAILBOX1 0x07c +#endif + +#define PCI9056_MAILBOX2 (0x048 + LOCAL_OFFSET) +#define PCI9056_MAILBOX3 (0x04c + LOCAL_OFFSET) +#define PCI9056_MAILBOX4 (0x050 + LOCAL_OFFSET) +#define PCI9056_MAILBOX5 (0x054 + LOCAL_OFFSET) +#define PCI9056_MAILBOX6 (0x058 + LOCAL_OFFSET) +#define PCI9056_MAILBOX7 (0x05c + LOCAL_OFFSET) +#define PCI9056_PCI_TO_LOC_DBELL (0x060 + LOCAL_OFFSET) +#define PCI9056_LOC_TO_PCI_DBELL (0x064 + LOCAL_OFFSET) +#define PCI9056_INT_CTRL_STAT (0x068 + LOCAL_OFFSET) +#define PCI9056_EEPROM_CTRL_STAT (0x06c + LOCAL_OFFSET) +#define PCI9056_PERM_VENDOR_ID (0x070 + LOCAL_OFFSET) +#define PCI9056_REVISION_ID (0x074 + LOCAL_OFFSET) + + +#endif /* #ifndef __PLX9056_H_ */ + |